diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..d43e6d09 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required (VERSION 2.6) +project (UQTk) + +# set( CMAKE_VERBOSE_MAKEFILE on ) # see all output +include( CTest ) + +# # set cpack for packagin +# SET(CPACK_GENERATOR "STGZ;TGZ;TZ") +# SET(CPACK_PACKAGE_NAME "UQTk") +# SET(CPACK_PACKAGE_VERSION "3.0") +# SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Bert Debusschere") #required +# INCLUDE(CPack) + + +IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + SET(CMAKE_INSTALL_PREFIX + "${PROJECT_BINARY_DIR}" CACHE PATH "FOO install prefix" FORCE + ) +ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + +set(INSTALL_LIB_DIR lib ) +set(INSTALL_BIN_DIR bin ) +set(INSTALL_INCLUDE_DIR include) +set(INSTALL_INCLUDE_DIR include) + +# Make relative paths absolute (needed later on) +foreach(p LIB BIN INCLUDE) + set(var INSTALL_${p}_DIR) + if(NOT IS_ABSOLUTE "${${var}}") + set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") + endif() +endforeach() + +option(PyUQTk "PyUQTk" OFF) +option(DFI "DFI" OFF) + +# CXX flags +#set(CMAKE_CXX_FLAGS "-O2") +set(CMAKE_CXX_FLAGS "-O2 -std=c++11") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_HDF5 -I/opt/local/hdf5/include -L/opt/local/hdf5/lib -lhdf5_hl -lhdf5_cpp -lhdf5 -lhdf5_fortran -lhdf5_hl_cpp") + +add_definitions(-D__wsu) +add_definitions(-fPIC) +add_definitions(-w) + +add_subdirectory (dep ) +add_subdirectory (cpp ) +add_subdirectory (examples) +add_subdirectory (PyUQTk ) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..0a041280 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + 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 that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU 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 as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/PyUQTk/.!99768!.DS_Store b/PyUQTk/.!99768!.DS_Store new file mode 100644 index 00000000..e69de29b diff --git a/PyUQTk/.!99769!.DS_Store b/PyUQTk/.!99769!.DS_Store new file mode 100644 index 00000000..e69de29b diff --git a/PyUQTk/.DS_Store b/PyUQTk/.DS_Store new file mode 100644 index 00000000..c80ebc7c Binary files /dev/null and b/PyUQTk/.DS_Store differ diff --git a/PyUQTk/CMakeLists.txt b/PyUQTk/CMakeLists.txt new file mode 100644 index 00000000..96176065 --- /dev/null +++ b/PyUQTk/CMakeLists.txt @@ -0,0 +1,30 @@ +project (UQTk) + +add_subdirectory (inference) +add_subdirectory (plotting) +add_subdirectory (sens) +add_subdirectory (multirun) +add_subdirectory (utils) + +SET(copy_FILES + __init__.py + ) +INSTALL(FILES ${copy_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION PyUQTk/ +) + +if ("${PyUQTk}" STREQUAL "ON") + include(numpy.cmake) + + add_subdirectory (uqtkarray) + add_subdirectory (quad) + add_subdirectory (tools) + #add_subdirectory (kle) + add_subdirectory (pce) + add_subdirectory (bcs) + # add_subdirectory (mcmc) + #add_subdirectory (dfi) + + add_subdirectory(pytests) +endif() diff --git a/PyUQTk/__init__.py b/PyUQTk/__init__.py new file mode 100644 index 00000000..90cbb2c5 --- /dev/null +++ b/PyUQTk/__init__.py @@ -0,0 +1,77 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# swig interface modules (only compiled if PyUQTK=On) +try: + import uqtkarray +except ImportError: + print "PyUQTk SWIG array interface not created." + +try: + import quad +except ImportError: + print "PyUQTk SWIG quad interface not created." + +try: + import tools +except ImportError: + print "PyUQTk SWIG tools interface not created." + +try: + import kle +except ImportError: + print "PyUQTk SWIG kle interface not created." + +try: + import pce +except ImportError: + print "PyUQTk SWIG pce interface not created." + +try: + import bcs +except ImportError: + print "PyUQTk SWIG bcs interface not created." + +try: + import mcmc +except ImportError: + print "PyUQTk SWIG mcmc interface not created." + +try: + import dfi +except: + print "PyUQTk SWIG dfi interface not created." + +# pure python tools (always included) +try: + import inference + import plotting + import sens +except: + print "Scipy and/or matplotlib may need to be installed" + +import utils +import multirun diff --git a/PyUQTk/bcs/CMakeLists.txt b/PyUQTk/bcs/CMakeLists.txt new file mode 100644 index 00000000..4319d381 --- /dev/null +++ b/PyUQTk/bcs/CMakeLists.txt @@ -0,0 +1,65 @@ +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}/../../Extras/lib/python/numpy/core/include) + +#include source files +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/) # array classes, array input output, and array tools +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/include/) # utilities like error handlers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/) # tools like multindex, etc. +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/) # quad class +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/kle/) # kle class +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/) # PCSet and PCBasis classes +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/bcs/) # bcs + +# include dependencies +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/blas/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lapack/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/dsfmt/) # dsfmt +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/figtree/) # figtree +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/slatec/) # slatec headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/cvode-2.7.0/include) # cvode +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/dep/cvode-2.7.0/include) +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/dep/cvode-2.7.0/include/nvector) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../numpy/) # numpy headers + +SET(CMAKE_SWIG_FLAGS "") +SET_SOURCE_FILES_PROPERTIES(bcs.i PROPERTIES CPLUSPLUS ON) + +# compile swig with cpp extensions +SWIG_ADD_MODULE( + bcs python bcs.i + # array tools needed to compile misc tools source files + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arrayio.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arraytools.cpp + + # source code for quad and kle class + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/quad.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/kle/kle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/bcs/bcs.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/PCSet.cpp + + # source code for tools + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/combin.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/gq.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/minmax.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/multiindex.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/pcmaps.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/probability.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/rosenblatt.cpp +) + +# link python and 3rd party libraries, e.g., gfortran and blas +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + SWIG_LINK_LIBRARIES(bcs uqtkpce uqtktools uqtkquad uqtkarray depnvec deplapack depblas depslatec depdsfmt depann depfigtree depcvode gfortran ${PYTHON_LIBRARIES}) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + SWIG_LINK_LIBRARIES(bcs uqtkpce uqtktools uqtkquad uqtkarray depnvec deplapack depblas depslatec depdsfmt depann depfigtree depcvode ifcore ${PYTHON_LIBRARIES}) +endif() + +INSTALL(TARGETS _bcs DESTINATION PyUQTk/) +INSTALL(FILES ${CMAKE_BINARY_DIR}/${outdir}PyUQTk/bcs/bcs.py DESTINATION PyUQTk) diff --git a/PyUQTk/bcs/bcs.i b/PyUQTk/bcs/bcs.i new file mode 100644 index 00000000..2279bb0b --- /dev/null +++ b/PyUQTk/bcs/bcs.i @@ -0,0 +1,139 @@ +%module(directors="1") bcs +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== + +%{ +#define SWIG_FILE_WITH_INIT +#include +#include +#include +#include +#include +// #include "../../cpp/lib/array/Array1D.h" +// #include "../../cpp/lib/array/Array2D.h" +// #include "../../cpp/lib/array/arrayio.h" +// #include "../../cpp/lib/array/arraytools.h" +// #include "../../cpp/lib/tools/combin.h" +// #include "../../cpp/lib/tools/gq.h" +// #include "../../cpp/lib/tools/minmax.h" +// #include "../../cpp/lib/tools/multiindex.h" +// #include "../../cpp/lib/tools/pcmaps.h" +// #include "../../cpp/lib/tools/probability.h" +// #include "../../cpp/lib/tools/rosenblatt.h" + +// #include "../../cpp/lib/quad/quad.h" +// #include "../../cpp/lib/kle/kle.h" +// #include "../../cpp/lib/pce/PCBasis.h" +// #include "../../cpp/lib/pce/PCSet.h" +#include "../../cpp/lib/bcs/bcs.h" + +%} + +/************************************************************* +// Standard SWIG Templates +*************************************************************/ + +// Include standard SWIG templates +// Numpy array templates and wrapping +%include "pyabc.i" +%include "../numpy/numpy.i" +%include "std_vector.i" +%include "std_string.i" +%include "cpointer.i" + +%init %{ + import_array(); +%} + +%pointer_functions(double, doublep); + +/************************************************************* +// Numpy SWIG Interface files +*************************************************************/ + +// // Basic typemap for an Arrays and its length. +// // Must come before %include statement below + +// // For Array1D setnumpyarray4py function +// %apply (long* IN_ARRAY1, int DIM1) {(long* inarray, int n)} +// %apply (double* IN_ARRAY1, int DIM1) {(double* inarray, int n)} +// // get numpy int and double array +// %apply (long* INPLACE_ARRAY1, int DIM1) {(long* outarray, int n)} +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* outarray, int n)} + +// // For Array2D numpysetarray4py function +// %apply (double* IN_FARRAY2, int DIM1, int DIM2) {(double* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (double* INPLACE_FARRAY2, int DIM1, int DIM2) {(double* outarray, int n1, int n2)} +// // For Array2D numpysetarray4py function +// %apply (long* IN_FARRAY2, int DIM1, int DIM2) {(long* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (long* INPLACE_FARRAY2, int DIM1, int DIM2) {(long* outarray, int n1, int n2)} + + +// // For mcmc test to get log probabilities +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* l, int n)} + +/************************************************************* +// Include header files +*************************************************************/ + +// // The above typemap is applied to header files below +// %include "../../cpp/lib/array/Array1D.h" +// %include "../../cpp/lib/array/Array2D.h" +// %include "../../cpp/lib/array/arrayio.h" +// %include "../../cpp/lib/array/arraytools.h" +// %include "../../cpp/lib/tools/combin.h" +// %include "../../cpp/lib/tools/gq.h" +// %include "../../cpp/lib/tools/minmax.h" +// %include "../../cpp/lib/tools/multiindex.h" +// %include "../../cpp/lib/tools/pcmaps.h" +// %include "../../cpp/lib/tools/probability.h" +// %include "../../cpp/lib/tools/rosenblatt.h" + +// %include "../../cpp/lib/quad/quad.h" +// %include "../../cpp/lib/kle/kle.h" +// %include "../../cpp/lib/pce/PCBasis.h" +// %include "../../cpp/lib/pce/PCSet.h" +%include "../../cpp/lib/bcs/bcs.h" + +// // Typemaps for standard vector +// // Needed to prevent to memory leak due to lack of destructor +// // must use namespace std +// namespace std{ +// %template(dblVector) vector; +// %template(intVector) vector; +// %template(strVector) vector; + +// } + + +%include "bcs_ext.py" + + + + diff --git a/PyUQTk/bcs/bcs_ext.py b/PyUQTk/bcs/bcs_ext.py new file mode 100644 index 00000000..182342e2 --- /dev/null +++ b/PyUQTk/bcs/bcs_ext.py @@ -0,0 +1,171 @@ +%pythoncode %{ + +import numpy as np +import matplotlib.pyplot as mpl +import uqtkarray as uqtkarray +import pce as uqtkpce +import tools as uqtktools +from uqtkarray import uqtk2numpy, numpy2uqtk +# BCS already added to path in compilation and install + + +class bcsreg: + ''' + Class to compute the bcs regression coefficients for a scalar function of ndim dimensions. + ''' + def __init__(self,ndim,pcorder,pctype): + ''' + Construction has the following inputs: + ndim : (int) number of input dimensions (features) + pcorder : (int) the initial order of the polynomial (changes in the algorithm) + pctype : ('LU','HG') type of polynomial basis functions, e.g., Legendre, Hermite + + ''' + self.ndim = ndim # int + self.pcorder = pcorder # int + self.pctype = pctype # 'LU', 'HG' + + # generate multi index + self.__mindex_uqtk = uqtkarray.intArray2D() + uqtktools.computeMultiIndex(self.ndim,self.pcorder,self.__mindex_uqtk); + self.mindex = uqtk2numpy(self.__mindex_uqtk) + self.__mindex0_uqtk = self.__mindex_uqtk # keep original + + # get projection/ Vandermonde matrix + self.__Phi_uqtk = uqtkarray.dblArray2D() + + # check if compiled + self.__compiled = False + self.compile() + + def compile(self,l_init=0.0,adaptive=0,optimal=1,scale=.1,verbose=0): + ''' + Setting up variables for the BCS algorithm. Most of the variables do not need to be set. Default settings are sufficient for more cases. See the C++ code for more information about variables. + ''' + # now we begin BCS routine + # set work variables + self.__newmindex_uqtk = uqtkarray.intArray2D() # for uporder iteration + self.__sigma2_p = uqtktools.new_doublep() # initial noise variance + self.__lambda_init = uqtkarray.dblArray1D() # hierarchical prior parameter + self.__adaptive, self.__optimal, self.__scale, self.__verbose = adaptive,optimal,scale,verbose + self.__weights_uqtk = uqtkarray.dblArray1D() # weights/ coefficients for basis + self.__used_uqtk = uqtkarray.intArray1D() # index of weights retained (nonzero) + self.__errbars_uqtk = uqtkarray.dblArray1D() # error bars for each weight + self.__nextbasis_uqtk = uqtkarray.dblArray1D() # if adaptive + self.__alpha_uqtk = uqtkarray.dblArray1D() # prior hyperparameter (1/gamma) + self.__lambda_p = uqtktools.new_doublep() + + uqtktools.doublep_assign(self.__lambda_p,l_init) + + self.__compiled = True + + def leastsq(self,X,y): + ''' + perform simple least squares based on the original + pc order. + ''' + # convert input to uqtk arrays + self.__X_uqtk = numpy2uqtk(X) + self.__y_uqtk = numpy2uqtk(y) + + # get vandermonde matrix w.r.t. original pc basis + self.__V_uqtk = uqtkarray.dblArray2D() + self.__pcmodel0 = uqtkpce.PCSet("NISPnoq",self.__mindex0_uqtk,self.pctype,0.0,1.0) # initiate + self.__pcmodel0.EvalBasisAtCustPts(self.__X_uqtk,self.__V_uqtk) + self.Vandermonde = uqtk2numpy(self.__V_uqtk) + self.__sol = np.linalg.lstsq(self.Vandermonde,y) + return self.__sol[0], self.__sol[1] + + def fit(self,X,y,tol=1e-8,sigsq=None,upit=0): + ''' + Train bcs model coefficients with X and y data + X : 2d numpy of inputs/ feature data + y : 1d numpy array of labels/ outputs + tol : tolerance (smaller means we keep more coefficients) + sigsq : initial noise set automatically based on y data + upit : (int) number of iterations to add higher order terms + + returns the polynomial coefficient (weights), and the mulitindex. One can also return the sensitivity indices by calling self.sens + ''' + if self.__compiled == False: + print "Need to compile first!" + + # convert numpy test data into uqtk data types + self.__X_uqtk = numpy2uqtk(X) + self.__y_uqtk = numpy2uqtk(y) + self.Xtrain = X + self.ytrain = y + + if sigsq == None: + self.__sigma2 = np.var(y)/1e2 + else: self.__sigma2 = sigsq + uqtktools.doublep_assign(self.__sigma2_p,self.__sigma2) + + self.__tol = tol + self.__upit = upit + + # begin uporder iterations + for iter in range(self.__upit+1): + + # get projection/ Vandermonde matrix + self.__pcmodel = uqtkpce.PCSet("NISPnoq",self.__mindex_uqtk,self.pctype,0.0,1.0) # initiate with new mindex + self.__pcmodel.EvalBasisAtCustPts(self.__X_uqtk,self.__Phi_uqtk) + self.__Phi = uqtk2numpy(self.__Phi_uqtk) + + # resest sigma parameter (if not, may get seg fault) + uqtktools.doublep_assign(self.__sigma2_p,self.__sigma2) + + # change to uqtkbcs.BCS if testing outside source + BCS(self.__Phi_uqtk,self.__y_uqtk,self.__sigma2_p,self.__tol,self.__lambda_init,self.__adaptive,self.__optimal,self.__scale,self.__verbose,self.__weights_uqtk,self.__used_uqtk,self.__errbars_uqtk,self.__nextbasis_uqtk,self.__alpha_uqtk,self.__lambda_p) + + # add new mulitindex to newmindex + uqtkarray.subMatrix_row_int(self.__mindex_uqtk,self.__used_uqtk,self.__newmindex_uqtk) + + if iter < self.__upit : + # redefine mindex = newmindex if still iterating + self.__newmindex_added_uqtk = uqtkarray.intArray2D() + uqtktools.upOrder(self.__newmindex_uqtk,self.__newmindex_added_uqtk) + self.__mindex_uqtk = self.__newmindex_added_uqtk + print "New mindex basis: ", uqtk2numpy(self.__mindex_uqtk)[len(self.__newmindex_uqtk):] + + # return new multiindex to create new pce model + self.__pcmodel_new = uqtkpce.PCSet("NISPnoq",self.__newmindex_uqtk,self.pctype,0.0,1.0) + self.mindex = uqtk2numpy(self.__newmindex_uqtk) + eff_dim = self.ndim - sum(sum(self.mindex,0) == 0) + + self.weights = uqtk2numpy(self.__weights_uqtk) + self.weight_index = uqtk2numpy(self.__used_uqtk) + self.error_bars = uqtk2numpy(self.__errbars_uqtk) + + # get main effect sensitivity indices + self.__main_eff_uqtk = uqtkarray.dblArray1D() + self.__tot_eff_uqtk = uqtkarray.dblArray1D() + self.__joint_eff_uqtk = uqtkarray.dblArray2D() + self.__pcmodel_new.ComputeMainSens(self.__weights_uqtk,self.__main_eff_uqtk) + self.__pcmodel_new.ComputeTotSens(self.__weights_uqtk,self.__tot_eff_uqtk) + self.__pcmodel_new.ComputeJointSens(self.__weights_uqtk,self.__joint_eff_uqtk) + self.main_eff = uqtk2numpy(self.__main_eff_uqtk) + self.tot_eff = uqtk2numpy(self.__tot_eff_uqtk) + self.joint_eff = uqtk2numpy(self.__joint_eff_uqtk) + self.senssum = {"main effect": self.main_eff, "total effect": self.tot_eff, "joint effect": self.joint_eff} + return self.weights, self.mindex + + def predict(self,Xtest): + ''' + Predict values after training the data + Xtest : 2d numpy array + + returns 1d numpy scalar array of predictions + ''' + self.__Xtest_uqtk = numpy2uqtk(Xtest) + self.__ytest_uqtk = uqtkarray.dblArray1D() + self.__pcmodel_new.EvalPCAtCustPoints(self.__ytest_uqtk,self.__Xtest_uqtk,self.__weights_uqtk) + self.__ytest = uqtk2numpy(self.__ytest_uqtk) + return self.__ytest + def getsens(self): + ''' + return sensitivities as dictionary + ''' + return self.senssum + +%} diff --git a/PyUQTk/inference/CMakeLists.txt b/PyUQTk/inference/CMakeLists.txt new file mode 100644 index 00000000..e972b60d --- /dev/null +++ b/PyUQTk/inference/CMakeLists.txt @@ -0,0 +1,12 @@ +project (UQTk) + +SET(copy_FILES + __init__.py + mcmc.py + postproc.py + ) + +INSTALL(FILES ${copy_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION PyUQTk/inference +) diff --git a/PyUQTk/inference/__init__.py b/PyUQTk/inference/__init__.py new file mode 100755 index 00000000..160bea8d --- /dev/null +++ b/PyUQTk/inference/__init__.py @@ -0,0 +1,28 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import mcmc +import postproc diff --git a/PyUQTk/inference/arch/mcmc.py b/PyUQTk/inference/arch/mcmc.py new file mode 100755 index 00000000..74e91b29 --- /dev/null +++ b/PyUQTk/inference/arch/mcmc.py @@ -0,0 +1,411 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import numpy as npy +import scipy.stats +import scipy.linalg +import math +import matplotlib.pyplot as plt + +global Rmat,invRmat + + +#--------------------------------------------------------------------------------------- +# Simple Hamiltonian MCMC routine +# Uses Leapfrog for the time stepping +#--------------------------------------------------------------------------------------- +def HMCMC(U,grad_U,dt,nT,q): + ''' + Hamiltonian MCMC routine + + Input: + ----- + + U - potential energy function, -log(posterior) + grad_U - gradient of potential energy function + dt - time step, dt, for leapfrog method + nT - number of time steps in leapfrog method + q - initial state of chain (position vector) + + Output: + ------ + Next vector in the chain state + + Example: + ------- + q_next = HMCMC(U,grad_U,1e-2,25,q_current) + + ''' + current_q = npy.copy(q) # save current + + # generate current p + # propcov = 4*array([[ 0.01175383, 0.02065261],[ 0.02065261, 0.04296117]]) + p = npy.random.randn(len(current_q)) + # p = random.multivariate_normal([0,0],propcov) + current_p = npy.copy(p) # save current p + + # make half step for momentum used for leap frog step + p = p - dt * grad_U(q)/2.0 + + for i in range(nT): + # p = p - dt * grad_U(q)/2.0 + q = q + dt*p + # p = p - dt * grad_U(q)/2.0 + if (i != nT-1): p = p - dt*grad_U(q) + + # make a half step for momentum at the end + p = p - dt * grad_U(q)/2.0 + + # negate the momentum to make a symmetric proposal + p = -p + + # Evaluate potential and kinetic energy + current_U = U(current_q)[0] + current_K = npy.sum(current_p**2)/2.0 + proposed_U = U(q)[0] + proposed_K = npy.sum(p**2)/2.0 + + # Accept or reject the state at end of trajectory, returning either + # the position at the end of the trajectory or the initial position + + if (npy.log(npy.random.rand()) < current_U-proposed_U+current_K-proposed_K): + return q + else: + return current_q + + +#--------------------------------------------------------------------------------------- +# Example: +# 1. Banana-shaped posterior density +#--------------------------------------------------------------------------------------- +def norm_pdf_multivariate(x, mu, sigma): + """ + Multi-variate normal pdf + x : list or numpy array + mu : 1D numpy array + sigma: 2D numpy array""" + size = len(x) + if size == len(mu) and (size, size) == sigma.shape: + det = npy.linalg.det(sigma) + if det == 0: + raise NameError("The covariance matrix can't be singular") + norm_const = 1.0/ ( math.pow((2*npy.pi),float(size)/2) * math.pow(det,1.0/2) ) + x_mu = npy.matrix(x - mu) + inv = npy.linalg.inv(sigma) + result = math.pow(math.e, -0.5 * (x_mu * inv * x_mu.T)) + return norm_const * result + else: + raise NameError("The dimensions of the input don't match") + +def tranB(x1,x2,a): + """ + Coordinate transform for banana-shaped pdf + x1,x2: 2D numpy arrays + a: list containing the transform factors + """ + a1 = a[0]; a2 = a[1]; + y1 = a1*x1; + y2 = x2/a1 - a2*(y1**2 + a1**2); + return y1,y2 + +def invTranB(x1,x2,a): + """ Inverse coordinate transform for banana-shaped pdf + x1,x2: 2D numpy arrays + a: list containing the transform factors + """ + a1 = a[0]; a2 = a[1]; + y1 = x1/a1; + y2 = x2*a1 + a1*a2*(x1**2 + a1**2); + return y1,y2 + +def plotBanana(): + """ + Plot banana-shaped function; parameters are hard-wired + """ + xb,yb = npy.mgrid[-3:3:.05, -11:1:.05] + x, y = invTranB(xb,yb,[1,1]) + pos = npy.empty(x.shape + (2,)) + pos[:, :, 0] = x; pos[:, :, 1] = y + mu = npy.array([0.0,0.0]) + cov = npy.array([[1.0, 0.9], [0.9, 1.0]]) + z = x.copy() + for i in range(x.shape[0]): + for j in range(x.shape[1]): + z[i,j] = norm_pdf_multivariate([x[i,j],y[i,j]], mu, cov) + plt.contour(xb,yb,z,50) + plt.show() + return + +def postBanana(spl,postinfo): + """ + Posterior density for banana-shaped pdf + postinfo : setup for the posterior density + + """ + afac = postinfo['afac'] + mu = postinfo['mu' ] + cov = postinfo['cov' ] + xb,yb = spl ; + x, y = invTranB(xb,yb,afac) ; + return npy.log(norm_pdf_multivariate([x,y], mu, cov)) + +#--------------------------------------------------------------------------------------- +# DRAM +#--------------------------------------------------------------------------------------- +def logPropRatio(iq,spls): + """ + Gaussian n:th stage log proposal ratio + log of q_i(y_n,..,y_n-j) / q_i(x,y_1,...,y_j) + """ + global invRmat + stage = len(spls)-1; + if stage == iq: + return (0.0); # symmetric + else: + iRmat = invRmat[iq-1]; # proposal^(-1/2) + y1 = spls[0] ; # y1 + y2 = spls[iq] ; # y_i + y3 = spls[stage ] ; # y_n + y4 = spls[stage-iq] ; # y_(n-i) + return (-0.5*(npy.linalg.norm(npy.dot(y4-y3,iRmat))**2-npy.linalg.norm(npy.dot(y2-y1,iRmat))**2)); + +def logPostRatio(p1,p2): + return (p2-p1); + +def getAlpha(spls,post): + stage = len(spls) - 1; + a1 = 1.0; a2 = 1.0; + for k in range(1,stage): + a1 = a1*(1-getAlpha(spls[:k+1],post[:k+1])); + a2 = a2*(1-getAlpha(spls[-1:-(k+1):-1],post[-1:-(k+1):-1])); + if a2 == 0.0: + return (0.0); + y = logPostRatio(post[0],post[-1]); + for k in range(1,stage+1): + y = y + logPropRatio(k,spls); + return min(1.0, npy.exp(y)*a2/a1); + +def ucov(spl,splmean,cov,lastup): + # + # update covariance + # + if len(spl.shape) == 1: + nspl = 1; + ndim = spl.shape[0]; + else: + (nspl,ndim)=spl.shape; + if nspl>0: + for i in range(nspl): + iglb = lastup+i; + splmean = (iglb*splmean+spl[i])/(iglb+1); + rt = (iglb-1.0)/iglb; + st = (iglb+1.0)/iglb**2; + cov = rt*cov+st*npy.dot(npy.reshape(spl[i]-splmean,(ndim,1)),npy.reshape(spl[i]-splmean,(1,ndim))) + return lastup+nspl,splmean,cov + +def dram_ex(method,nsteps): + # define MCMC parameters + cini = npy.array([-1.0,-4.0]) + spllo = npy.array([-4.0,-12.0]) + splhi = npy.array([ 4.0, 2.0]) + cvini = npy.array([[0.1,0.0],[0.0,0.1]]) + opts={'method':method,'nsteps':nsteps,'nburn':1000,'nadapt':100,'nfinal':10000000, + 'inicov':cvini,'coveps':1.e-10,'burnsc':5,'ndr':2,'drscale':[5,4,3], + 'spllo':spllo,'splhi':splhi} + lpinfo={'afac':[1.0,1.0],'cov': npy.array([[1,0.9],[0.9,1]]),'mu':npy.array([0.0,0.0])} + sol=dram(opts,cini,postBanana,lpinfo) + return sol + +def dram(opts,cini,likTpr,lpinfo): + """ + # + # DRAM + # + Delayed Rejection Adaptive MCMC + opts - dictionary of parameters for DRAM + method : either 'am' (adaptive metropolis) or 'dram' (am+delayed rejection) + nsteps : no. of mcmc steps + nburn : no. of mcmc steps for burn-in (proposal fixed to initial covariance) + nadapt : adapt every nadapt steps after nburn + nfinal : stop adapting after nfinal steps + inicov : initial covariance + coveps : small additive factor to ensure covariance matrix is positive definite + burnsc : factor to scale up/down proposal is acceptance rate is too high/low + ndr : no. of delayed rejection steps (if dram is requested) + drscale: scale factors for delayed rejection + cini - starting mcmc state + likTpr - log-posterior function + lpinfo - dictionary with settings that will be passed to the log-posterior function + + """ + # ------------------------------------------------------------------------------- + # Parse options + # ------------------------------------------------------------------------------- + if 'method' in opts: + method = opts['method'] + else: + print 'Error in dram: method unspecified !'; quit() + nsteps = opts['nsteps'] + nburn = opts['nburn' ] + nadapt = opts['nadapt'] + nfinal = opts['nfinal'] + inicov = opts['inicov'] + coveps = opts['coveps'] + burnsc = opts['burnsc'] + spllo = opts['spllo' ] + splhi = opts['splhi' ] + if method=='dram': + ndr = opts['ndr'] + drscale = opts['drscale'] + rej = 0; + rejlim = 0; + rejsc = 0; + # ------------------------------------------------------------------------------- + # Pre-processing + # ------------------------------------------------------------------------------- + cdim = cini.shape[0]; # chain dimensionality + cov = npy.zeros((cdim,cdim)); # covariance matrix + spls = npy.zeros((nsteps,cdim)); # MCMC samples + na = 0; # counter for accepected jumps + sigcv = 2.4/npy.sqrt(cdim); # covariance factor + spls[0] = cini; # initial sample set + p1 = likTpr(spls[0],lpinfo); # and + pmode = p1; # store chain MAP + cmode = spls[0]; + nref = 0; + for k in range(nsteps-1): + # + # Deal with covariance matrix + # + covMatUpd = False + if k == 0: + splmean = spls[0]; + propcov = inicov ; + Rchol = scipy.linalg.cholesky(propcov) ; + lastup = 1; # last covariance update + covMatUpd = True ; + else: + if (nadapt>0) and ((k+1)%nadapt)==0: + if k0.95: + Rchol = Rchol/burnsc # scale down proposal + covMatUpd = True ; + print "Scaling down the proposal at step",k + elif float(rejsc)/nref<0.05: + Rchol = Rchol*burnsc # scale up proposal + covMatUpd = True ; + print "Scaling up the proposal at step",k + nref = 0 ; + rejsc = 0 ; + else: + lastup,splmean,cov=ucov(spls[lastup:lastup+nadapt,:],splmean,cov,lastup) + try: + Rchol = scipy.linalg.cholesky(cov) + except scipy.linalg.LinAlgError: + try: + # add to diagonal to make the matrix positive definite + Rchol = scipy.linalg.cholesky(cov+coveps*npy.identity(cdim)) + except scipy.linalg.LinAlgError: + print "Covariance matrix is singular even after the correction" + Rchol = Rchol*sigcv + covMatUpd = True ; + if (method == 'dram') and covMatUpd: + Rmat = [Rchol]; invRmat = [scipy.linalg.inv(Rchol)] + for i in range(1,ndr): + Rmat.append(Rmat[i-1]/drscale[i-1]) + invRmat.append(invRmat[i-1]*drscale[i-1]) + #-Done with covariance matrix + nref = nref + 1 ; + # + # generate proposal and check bounds + # + u = spls[k]+npy.dot(npy.random.randn(1,cdim),Rchol)[0]; + if npy.any(npy.less(u,spllo)) or npy.any(npy.greater(u,splhi)): + outofbound = True + accept = False + p2 = -1.e6 + else: + outofbound = False + if not outofbound: + p2 = likTpr(u,lpinfo); + pr = npy.exp(p2-p1); + if (pr>=1.0) or (npy.random.random_sample()<=pr): + spls[k+1] = u.copy(); + p1 = p2; + if p1 > pmode: + pmode = p1 ; + cmode = spls[k+1] ; + accept = True + else: + accept = False + # + # See if we can do anything about a rejected proposal + # + if not accept: + if (method == 'am'): + # if 'am' then reject + spls[k+1]=spls[k]; + rej = rej + 1; + rejsc = rejsc + 1; + if outofbound: + rejlim = rejlim + 1; + elif (method == 'dram'): + # try delayed rejection + tryspls = [spls[k].copy(),u.copy()] + trypost = [p1,p2] + jdr = 1 + while (not accept) and (jdr= 1.0) or (npy.random.random_sample() < alpha): + accept = True; + spls[k+1] = u.copy(); + p1 = p2; + if p1 > pmode: + pmode = p1 ; + cmode = spls[k+1] ; + if not accept: + spls[k+1]=spls[k] ; + rej = rej + 1; + rejsc = rejsc + 1; + if outofbound: + rejlim = rejlim + 1; + else: + print "Unknown MCMC method ",method," -> Quit\n"; quit() + # Done with if over methods + # Done with if over original accept + # Done loop over all steps + return (spls,[cmode,pmode],[1.0-float(rej)/nsteps,1.0-float(rejlim)/nsteps],[rej,rejlim]) diff --git a/PyUQTk/inference/arch/postproc.py b/PyUQTk/inference/arch/postproc.py new file mode 100755 index 00000000..a248bb87 --- /dev/null +++ b/PyUQTk/inference/arch/postproc.py @@ -0,0 +1,781 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# +# Does statistical analysis on samples from an MCMC chain. + + +import os +import sys +import string +import numpy as np +import getopt +import math +import matplotlib.pyplot as plt +from scipy import stats, mgrid, c_, reshape, random, rot90 +from matplotlib.ticker import MultipleLocator, FormatStrFormatter + +#import pyUQTk.utils as ut + +################################################################################## +# Compute autocorrelation a one-dimensional set of samples +# Main function is acor(X), where X is a numpy array of samples +################################################################################## +from numpy import * +from matplotlib.pyplot import * +def acor_in(X, MAXLAG, WINMULT): + + # compute mean of X + L = len(X) + mu = mean(X) + Xhat = X - mu + std = sqrt(var(X)) + + iMax = L - MAXLAG + + # compute autocorrelation + # sind = arange(MAXLAG+1) + iind = arange(iMax) + C = zeros(MAXLAG + 1) + for s in range(MAXLAG+1): + C[s] += sum(Xhat[iind]*Xhat[iind+s]) + C *= 1./iMax + + D = C[0] # diffusion coeff + D += 2*sum(C[1:]) + + sigma = sqrt(abs(D/L)) + tau = D/C[0] + + # print D, L, sigma, tau, tau*WINMULT, MAXLAG + return C[0], D, L, sigma, tau, tau*WINMULT, Xhat +# take in 1d numpy array of samples X +def acor(X,MAXLAG = 10, WINMULT = 5): + C0, D, L, sigma, tau, tauWINMULT, X = acor_in(X, MAXLAG, WINMULT) + # print tau, sigma + Ls = [] + S = [] + while tau*WINMULT >= MAXLAG: + Lh = L/2 + Ls.append(Lh) + j1,j2 = 0,1 + for i in range(Lh): + X[i] = X[j1] + X[j2] + j1 += 2 + j2 += 2 + _, D, L, sigma, tau, tauWINMULT, X = acor_in(X[:Lh], MAXLAG, WINMULT) + S.append(sigma) + if len(S) == 0: + S.append(sigma) + Ls.append(L) + + sigma = S[-1] + Ls = 2*array(Ls[::-1]) + for i in range(len(S)): + D = .25 * sigma**2 * Ls[i] + tau = D/C0 + sigma = sqrt(D/Ls[i]) + + return tau + +################################################################################################### +def read_remaining_lines(samples_file,n_burnin,stride): + """Read all remaining lines in MCMC sample filename, leaving out the first n_burnin, + and only one in every stride lines after that + """ + samples_list = [] + line_no = 0 + done = 0 + while not done: + line = samples_file.readline() + if (line == ""): + done = 1 + else: + line_no += 1 + if (line_no > n_burnin and (line_no - n_burnin) % stride == 0): + records = line.split() + num_records = [float(s) for s in records] + samples_list.append(num_records) + + return samples_list + +################################################################################################### +def remove_MAP_line(samples_list,debug): + """Remove the last line if is has a value < 0 (i.e. -1) in the acceptance_prob column (next to last)""" + if(samples_list[-1][-2] < 0): + # Remove the last line + del samples_list[-1] + if (debug > 0): + print "The last sample line has been deleted as it contained the MAP values" + +################################################################################################### +def extract_vars(samples_file_name,n_burnin,v_names,debug,stride=1): + """From a file with samples in ascii format, with + the first line containing the label for each column, extract + the columns with the labels in v_names and return them + in a numpy array. Remove n_burnin samples from the top. + Only read one in every stride number of lines after that. + Assumes that the first column is the MCMC step number, the next to last column is the acceptance + probability for each step, and the last column is the posterior probability for each step. The + last line is removed if it contains -1 for the acceptance probability (which means this + line contains the MAP values)""" + + # Open text file with all samples, + samples_file = open(samples_file_name,"r") + + # Extract first line with the column labels and find the column + # numbers corresponding to the variables of interest. + labels_line = samples_file.readline().rstrip('\n') + col_labels = [lbl for lbl in labels_line.split()] + + v_indices = [] + for s_v in v_names: + try: + i_v = col_labels.index(s_v) + v_indices.append(i_v) + except ValueError: + print "Variable", s_v, "is not found in the list of labels", col_labels + sys.exit(1) + + if (debug > 0): + print "Column labels in file",samples_file_name,"are:",col_labels + for i_v in range(len(v_names)): + print "The column number of",v_names[i_v],"is:",v_indices[i_v] + + # Read subsequent lines + samples_list = read_remaining_lines(samples_file,n_burnin,stride) + + # Close the file + samples_file.close() + + # Remove MAP values, if present + remove_MAP_line(samples_list,debug) + + # Convert list to array + steady_samples = np.array(samples_list) + + + # Extract all columns of interest + samples_cols = [] + for i_v in v_indices: + samples_cols.append(steady_samples[:,i_v]) + + samples = np.array(samples_cols).T + if (debug > 0): + print "Shape of samples array:",samples.shape + + n_samples = len(samples[:,0]) + n_vars = len(samples[0,:]) + + if (debug > 0): + print "Read in", n_samples, "regular samples of", n_vars, "variables from file", samples_file_name + + return samples + +################################################################################################### +def extract_all_vars(samples_file_name,n_burnin,debug,stride=1,labels=True): + """Extract samples and labels from an MCMC chain file. + Returns a numpy array with the samples, and a list of column labels. + Assumes the following: + * The file is in ASCII format + * The first column contains the MCMC step number + * The next to last column contains the acceptance probability for the jump proposed in this step + * The last column contains the posterior probability of the state in this step + * The columns in between contain the sampled states + * Unless the argument labels == False, the first line contains labels for each column + * If the last line has -1 in the acceptance probability column, then this line contains + the MAP values. This line is removed before returning the samples to the calling program. + Arguments: + * samples_file_name: name of file to parse + * n_burnin: number of lines to skip from the top + * debug: higher values are more verbose in output + * stride: stride to take in parsing sample lines. [default = 1] + * labels: True if the file contains column labels in first line. False if not. [default = True] + If not column labels are present, they are manufactured as aa, ab, ac, ..., az, ba, bb, ... + """ + + # Open text file with all samples + samples_file = open(samples_file_name,"r") + + + if (labels): # Column labels are present in first line + # Extract first line with the column labels + labels_line = samples_file.readline().rstrip('\n') + col_labels = [lbl for lbl in labels_line.split()] + + # Identify the MCMC vars, knowing that the first column is the step + # number and the last two columns are acceptance and posterior prob + n_cols = len(col_labels) + n_vars = n_cols - 3 + + v_names = col_labels[1:1+n_vars] + + if (debug > 0): + print "Column labels in file", samples_file_name, "are:", col_labels + print "MCMC chain variables are", v_names + else: + # Extract first line to see how many columns we have + first_line = samples_file.readline().rstrip('\n') + first_line_items = [item for item in first_line.split()] + + # Identify the MCMC vars, knowing that the first column is the step + # number and the last two columns are acceptance and posterior prob + n_cols = len(first_line_items) + n_vars = n_cols - 3 + + # Generate variable names as aa, ab, ..., az, ba, bb, ... + if (n_vars > 52*26): # only 52 entries in string.letters. If need be, could go higher by allowing aA, aB, ... , Aa, ... + print "In routine extract_all_vars: too many columns for automatic name generation" + sys.exit(1) + + v_names = [] + for i_v in range(n_vars): + name = "" + name += string.letters[i_v/26] + name += string.letters[i_v%26] + v_names.append(name) + + if (debug > 0): + print "There are",n_cols," columns in file", samples_file_name + print "MCMC chain variables have been labeled", v_names + + # Rewind file so the first line will be read just like the other sample lines + samples_file.seek(0) + + # Read subsequent lines + samples_list = read_remaining_lines(samples_file,n_burnin,stride) + + # Close the file + samples_file.close() + + # Remove MAP values, if present + remove_MAP_line(samples_list,debug) + + # Convert list to array + samples = np.array(samples_list) + + n_samples = samples.shape[0] + + if (debug > 0): + print "Read in", n_samples, "regular samples of", n_vars, "variables from file", samples_file_name + + return samples, v_names + +################################################################################################### +def effective_sample_sizes(var_samples,par_mean,par_cov): + """Computes the effective sample size for each column + by dividing the number of samples by the integral + of the autocorrelation between the samples. (i.e. the more + correlated successive samples are, the less independent samples there are + in the chain.) + The algorithm is based on: + Markov Chain Monte Carlo in Practice: A Roundtable Discussion + Robert E. Kass, Bradley P. Carlin, Andrew Gelman and Radford M. Neal + The American Statistician, Vol. 52, No. 2 (May, 1998), pp. 93-100 + Published by: American Statistical Association + Article DOI: 10.2307/2685466 + Article Stable URL: http://www.jstor.org/stable/2685466 + """ + + # Number of variable samples in set + n_sam = var_samples.shape[0] + # Number of variables in this sample set + n_vars = var_samples.shape[1] + + # Array to store effective sample sizes in + ess = [] + + # Cut-off point for autocorrelation + # Ideally, n_a should be chosen such that the autocorrelation goes to 0 at this lag. + # Chosing n_a too low will give inaccurate results (overpredicting ESS), but going + # to much higher lag will create a lot of noise in ESS estimate. + n_a = min(100,n_sam) + for i_v in range(n_vars): + # Subtract mean from current variable samples + v_nm = var_samples[:,i_v] - par_mean[i_v] + # Compute autocorrelation for this variable. np.autocorrelate returns vector with + # lag from -n_sam to n_sam, with the 0 shift in the middle. Only retain from lag 0 to n_a. + r_v = np.correlate(v_nm, v_nm, mode = 'full')[-n_sam:-n_sam+n_a] + # Devide by number of samples in each sum, and normalize by variance + # (note: 0 lag has n_sam samples in sum, lag i has (n_sam - i) samples in sum + r_a = r_v / (par_cov[i_v,i_v]*(np.arange(n_sam, n_sam-n_a, -1))) + # Plot autocorrelation to see if n_a is large enough + #pl1,=plt.plot(r_a) + #plt.show() + # Effective Sample Size (Number of samples devided by integral of autocorrelation) + # Integral relies on symmetry and the fact that r_a is 1 at zero lag + ess.append(n_sam / (1.0+2.0*np.sum(r_a[1:]))) + + return ess + +################################################################################################### +def plot_all_posteriors(d0,vnames,np_kde,out_file_base,debug,dense=False): + """ + Given a set of samples of random variables, this script plots a lower triangular + matrix of marginalized densities. The diagonal contains the density of individual + random variables, marginalized over all other variables. Plots below the diagonal + contain the 2D density of the associated pair of random variables, marginalized over + all other variables. + For chains with many variables, the "dense" option can be selected, which plots the + triangular set of densities for the full chain with minimum spacing and labels, so that + it is less cluttered. In this mode, this function also writes out a set of plots + with the same posterior information, but just for two variables at the time, + which is easier to read. + + Arguments: + d0 : Set of samples, one column per variable + vnames : Variable names + np_kde : Number of points to use to compute posterior densities with KDE + out_file_base: Base name for output files with plots + debug : >0 writes more output to screen (and even more if >1) + dense : Set to True if dense output desired [Defaults to False]. The "dense" output + format puts all plots in the triangular format up against each other, without + any axis labels or space in between them. It is useful when plotting the + posteriors of a chain with many variables. + """ + # Some settings to connect with code Cosmin gave me + nthin = 1 # take only every nthin state (for faster kde) + nskip = 0 # entries to skip + istart = 0 # number of column with first MCMC variable + cend = 0 # extra columns at end to be removed + + nvars=d0.shape[1]-istart-cend # number of variables we will actually process + print 'Number of sample lines in file',d0.shape[0] + print 'Number of vars we will process in file',nvars + + # Section 2 + # set up 2D kde objects + print "Setting up 2D KDE objects" + kern_i_j=[] + for j in range(istart+1,istart+nvars): + for i in range(istart,j): + if (debug > 2): + print i,j + kern_i_j.append(stats.kde.gaussian_kde(c_[d0[nskip::nthin,i],d0[nskip::nthin,j]].T)) + + # Section 3 + # set up 2D meshes and evaluate kde objects on those meshes + # no. of grid points is controlled with kde_idx, defaults to 100 + print "Evaluating 2D KDE objects on meshes. This may take a while ..." + kde_idx = np_kde*1j # complex number to include end points + xmesh=[]; ymesh=[]; zmesh=[]; + icount=0 + cov_idx = np.zeros((nvars,nvars),dtype=np.int) # 2D array to keep track of which index in xmesh etc. the + # the plots corresponding to vars i,j belong to + for j in range(istart+1,istart+nvars): + for i in range(istart,j): + if (debug > 0): + print "Computing 2D marginal distribution between variables:",i,",",j,":",vnames[i]," & ",vnames[j] + x,y = mgrid[d0[nskip:,i].min():d0[nskip:,i].max():kde_idx, d0[nskip:,j].min():d0[nskip:,j].max():kde_idx] + z = reshape(kern_i_j[icount](c_[x.ravel(), y.ravel()].T).T, x.T.shape) + xmesh.append(x); + ymesh.append(y); + zmesh.append(z); + cov_idx[i,j] = icount + icount = icount+1 + + # Section 4 + # evaluate 1D pdfs + print "Evaluating 1D marginal pdfs with KDE" + xlin=[]; pdflin=[]; + for i in range(istart,istart+nvars): + xlin.append(np.linspace(d0[nskip:,i].min(),d0[nskip:,i].max(),np_kde)) ; + kernlin=stats.kde.gaussian_kde(d0[nskip::nthin,i]); + pdflin.append(kernlin(xlin[i-istart])); + + + if (not dense): + # Section 5 + print "Assembling tri-diagonal plots in non-dense format" + + # ds is the distance between subplots + # xs,ys are the coordinates (normalized) of the subplot in the lower left corner + # xe,ye are the distances left in the uppper right corner + # fsizex, fsizey are figure sizes + # ncont are no of contours for 2D pdfs + xs=0.12; ys=0.1; ds=0.04 + xe=0.08; ye=0.05 + fsizex=12; fsizey=12; + ncont=20; + sx=(1-(nvars-1)*ds-xs-xe)/nvars; + sy=(1-(nvars-1)*ds-ys-ye)/nvars; + fs1=20 + majorFormatter = FormatStrFormatter('%6.0e') + + figname=out_file_base+".tridiag.pdf" # figure name + + fig = plt.figure(figsize=(fsizex,fsizey)) + + # Section 5.1 + subs=[] + # add diagonal plots + for i in range(nvars): + subs.append(fig.add_axes([xs+i*(sx+ds),ys+(nvars-1-i)*(sy+ds),sx,sy])) + + # add lower triangular plots + for i in range(nvars-1): + for j in range(i+1): + if (debug > 2): + print j,(nvars-2-i) + subs.append(fig.add_axes([xs+j*(sx+ds),ys+(nvars-2-i)*(sy+ds),sx,sy])) + + subsnp=np.array(subs) + + # Plot 1D pdfs + for i in range(nvars): + subsnp[i].plot(xlin[i],pdflin[i]) + + # Plot 2D pdfs + for i in range(nvars*(nvars-1)/2): + subsnp[nvars+i].contour(xmesh[i],ymesh[i],zmesh[i],ncont) + + # Section 5.2 + # just a few ticks and ticklabels + for subpl in subsnp: + # subpl.set_xticks([]) + # subpl.set_yticks([]) + subpl.locator_params(tight=True, nbins=5) + + # for diagonal plots, put no ticks and lables on y-axis + # and no grid on the plots + for i in range(istart,istart+nvars): + # subsnp[i-istart].set_xticks([d0[nskip:,i].min(),d0[nskip:,i].max()]); + subsnp[i-istart].set_yticks([]) + subsnp[i-istart].grid(False) + + # Set y labels on the right for diagonal plots + for i in range(nvars): + subsnp[i].yaxis.tick_right() + subsnp[i].yaxis.set_label_position("right") + subsnp[i].set_ylabel(vnames[i], fontsize=fs1) + #subsnp[i].set_ylabel(r'$'+vnames[i]+'$', fontsize=fs1) + + plt.savefig(figname) + + else: + # Section 5 + # Dense plot format: print full tri-diagonal matrix but w/o any white space, tick marks or lables. + print "Assembling tri-diagonal plots in dense format" + + # ds is the distance between subplots + # xs,ys are the coordinates (normalized) of the subplot in the lower left corner + # xe,ye are the distances left in the uppper right corner + # fsizex, fsizey are figure sizes + # ncont are no of contours for 2D pdfs + xs=0.12; ys=0.1; ds=0.0 + xe=0.08; ye=0.05 + fsizex=12; fsizey=12; + ncont=10; + sx=(1-(nvars-1)*ds-xs-xe)/nvars; + sy=(1-(nvars-1)*ds-ys-ye)/nvars; + fs1=20 + majorFormatter = FormatStrFormatter('%6.0e') + + figname=out_file_base+".tridiag-dense.pdf" # figure name + + fig_d = plt.figure(figsize=(fsizex,fsizey)) + + # Section 5.1 + subs=[] + # add diagonal plots + for i in range(nvars): + subs.append(fig_d.add_axes([xs+i*(sx+ds),ys+(nvars-1-i)*(sy+ds),sx,sy])) + + # add lower triangular plots + for i in range(nvars-1): + for j in range(i+1): + if (debug > 2): + print j,(nvars-2-i) + subs.append(fig_d.add_axes([xs+j*(sx+ds),ys+(nvars-2-i)*(sy+ds),sx,sy])) + + subsnp=np.array(subs) + + # Plot 1D pdfs along diagonals + for i in range(nvars): + subsnp[i].plot(xlin[i],pdflin[i]) + + # Plot 2D pdfs + for i in range(nvars*(nvars-1)/2): + subsnp[nvars+i].contour(xmesh[i],ymesh[i],zmesh[i],ncont) + + # Section 5.2 + # no ticks and ticklabels + for subpl in subsnp: + subpl.set_xticks([]); + subpl.set_yticks([]); + + # Set variable names + # for i in range(nvars): + # subsnp[i].yaxis.set_label_position("right") + # subsnp[i].set_ylabel(vnames[i], fontsize=fs1) + # #subsnp[i].set_ylabel(r'$'+vnames[i]+'$', fontsize=fs1) + + + plt.savefig(figname) + + print "Assembling marginal density plots for all pairs of MCMC variables" + + # ds is the distance between subplots + # xs,ys are the coordinates (normalized) of the subplot in the lower left corner + # xe,ye are the distances left in the uppper right corner + # fsizex, fsizey are figure sizes + # ncont are no of contours for 2D pdfs + xs=0.12; ys=0.1; ds=0.04 + xe=0.08; ye=0.05 + fsizex=12; fsizey=12; + ncont=20; + nvars_sm=2 + sx=(1-(nvars_sm-1)*ds-xs-xe)/nvars_sm; + sy=(1-(nvars_sm-1)*ds-ys-ye)/nvars_sm; + fs1=20 + majorFormatter = FormatStrFormatter('%6.0e') + + + # loop over all pairs of MCMC variables. + for j in range(istart+1,istart+nvars): + for i in range(istart,j): + + print "Plotting densities for variables",vnames[i],"and",vnames[j] + figname=out_file_base + "." + vnames[i] + "-" + vnames[j] + ".pdf" + + fig_sm = plt.figure(figsize=(fsizex,fsizey)) + + subs=[] + # add diagonal plots + subs.append(fig_sm.add_axes([xs ,ys+(sy+ds),sx,sy])) # marginal for var i + subs.append(fig_sm.add_axes([xs+(sx+ds),ys ,sx,sy])) # marginal for var j + + # add lower triangular plot + subs.append(fig_sm.add_axes([xs ,ys ,sx,sy])) # marginal for vars i,j + + subsnp=np.array(subs) + + # Plot 1D pdfs + subsnp[0].plot(xlin[i],pdflin[i]) + subsnp[1].plot(xlin[j],pdflin[j]) + + # Plot 2D pdfs + i_2D = cov_idx[i,j] + subsnp[2].contour(xmesh[i_2D],ymesh[i_2D],zmesh[i_2D],ncont) + + # set just a few ticks and ticklabels + for subpl in subsnp: + subpl.locator_params(tight=True, nbins=5) + + # no ticks and ticklabels on y axes on diagonals (first two plots in subsnp array) + # no grid on diagonal plots + for subpl in subsnp[0:2]: + subpl.set_yticks([]) + subpl.grid(False) + + # for diagonal plots only put xmin and xmax + #subsnp[0].set_xticks([d0[nskip:,i].min(),d0[nskip:,i].max()]); + #subsnp[1].set_xticks([d0[nskip:,j].min(),d0[nskip:,j].max()]); + + + # Set y labels on the right for diagonal plots + #subsnp[0].yaxis.tick_right() + subsnp[0].yaxis.set_label_position("right") + subsnp[0].set_ylabel(vnames[i], fontsize=fs1) + + #subsnp[1].yaxis.tick_right() + subsnp[1].yaxis.set_label_position("right") + subsnp[1].set_ylabel(vnames[j], fontsize=fs1) + + # Write out figure + plt.savefig(figname) + +################################################################################################### +def get_mcmc_stats(all_samples,v_names,out_file_base,debug): + """ + Generate statistics of the passed in MCMC samples. + Assumes that the first column of all_samples contains the step number, and the last two + columns contain the acceptance probability and the posterior probability for each sampled state. + """ + + # Number of variables, columns, samples in the file + n_vars = len(v_names) + n_cols = all_samples.shape[1] + n_sam = all_samples.shape[0] + + # Extract all MCMC chain variables in separate array + var_samples = all_samples[:,1:1+n_vars] + if (debug > 0): + print var_samples.shape + + # Compute mean parameter values + par_mean = np.mean(var_samples,axis=0,dtype=np.float64) + + #print "\nParameter mean values:\n" + #for i_v in range(n_vars): + # print " ", v_names[i_v], ":", par_mean[i_v] + + # Compute the covariance + par_cov = np.cov(var_samples,rowvar=0) + + print "\nParameter covariances:\n" + print par_cov + + # write out covariance matrix to file + cov_file_name = out_file_base + ".covariance.dat" + np.savetxt(cov_file_name,par_cov) + + # print the square root of the diagonal entries of the covariance + #print "\nParameter standard deviations (proposal width estimates):\n" + #for i_v in range(n_vars): + # print " ", v_names[i_v], ":", math.sqrt(par_cov[i_v,i_v]) + + # + # Compute the MAP values + # (could also get this from the last line of the MCMC output file + # but this line is not always there; and it is more fun + # to do it with Python) + # + + # Sample index with max posterior prop (last column in MCMC file): + i_map = all_samples[:,-1].argmax() + + print "\n", + print '%27s' % "Parameter :", '%15s' % "Mean Value", '%15s' % "MAP values", '%15s' % "Std. Dev." + for i_v in range(n_vars): + print '%25s' % v_names[i_v], ":", '%15.8e' % par_mean[i_v], '%15.8e' % var_samples[i_map,i_v], + print '%15.8e' % math.sqrt(par_cov[i_v,i_v]) + + # Write mean and MAP to file + mean_file_name = out_file_base + ".mean.dat" + np.savetxt(mean_file_name,par_mean) + + map_file_name = out_file_base + ".map.dat" + np.savetxt(map_file_name,var_samples[i_map,:]) + + # Compute mean and standard deviation of acceptance probability + print "\nAcceptance Probability:\n" + + # In some cases, the next to last column contains the ratio of posterior + # values rather than the acceptance probability. First convert this number + # to acceptance probabilities: acc_prob = min(alpha,1) + # (This does no harm if the next to last column already contains the actual acceptance probability) + acc_prob = np.minimum(all_samples[:,-2],np.ones_like(all_samples[:,-2])) + print "Mean :",acc_prob.mean(), + print "Std. Dev.:",acc_prob.std() + + # + # Compute effective sample size (ESS) + # + print "\nEffective Sample Sizes:\n" + + ess = effective_sample_sizes(var_samples,par_mean,par_cov) + + for i_v in range(n_vars): + print " ",v_names[i_v],":",int(ess[i_v]),"out of",n_sam + +################################################################################################### + +help_string = """ +Usage: + mcmc_stats.py [-h] -i [--nb ] [-s ] [--nolabels] +what + Compute elementary statistics of MCMC chain +where + -h = print help info + -i = name of file containing MCMC data + -s = stride with which to read the file [defaults to 1] + --nb = number of burn-in samples to be removed from the chain [defaults to 0] + --nolabels Indicates that the MCMC data file does not contain column labels (in which case they are generated) +""" + +if __name__ == "__main__": + # + # Process inputs + # + try: + opts,v_names = getopt.getopt(sys.argv[1:],"hi:s:",["nb=","nolabels"]) + except getopt.GetoptError, err: + print str(err) + print help_string + sys.exit(1) + + # Default values + samples_file_name="" + n_burnin = 0 + stride = 1 + labels_present = True + + for o,a in opts: + if o == "-h": + print help_string + sys.exit(0) + elif o == "-i": + samples_file_name = a + elif o == "-s": + stride = int(a) + elif o == "--nb": + n_burnin = int(a) + elif o == "--nolabels": + labels_present = False + else: + assert False, "Unhandled command line parsing option. Use -h flag to get usage info." + + # error checking + if(samples_file_name==""): + print "Sample file name must be specified" + print help_string + sys.exit(1) + + if (n_burnin < 0): + print "The number of burn-in samples needs to be >= 0" + print help_string + sys.exit(1) + + if (stride < 0): + print "The file read stride needs to be >= 0" + print help_string + sys.exit(1) + + # Base name of file for outputting results + out_file_base = samples_file_name + ".nb" + str(n_burnin) + ".s" + str(stride) + + # Set to 1 to get more output to screen + # Set to > 1 to get a lot of output to screen + debug = 1 + + # Set to 1 for showing plots interactively + interact = 0 + + # + # Import variables of interest from the MCMC data file + # + all_samples, v_names = extract_all_vars(samples_file_name,n_burnin,debug,stride,labels=labels_present) + + # Get statistics + get_mcmc_stats(all_samples,v_names,out_file_base,debug) + + + + + + diff --git a/PyUQTk/inference/mcmc.py b/PyUQTk/inference/mcmc.py new file mode 100755 index 00000000..5bd2fd7d --- /dev/null +++ b/PyUQTk/inference/mcmc.py @@ -0,0 +1,484 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import numpy as npy +import scipy.stats +import scipy.linalg +import math +import uuid +import matplotlib.pyplot as plt + +global Rmat,invRmat + + +#--------------------------------------------------------------------------------------- +# Simple Hamiltonian MCMC routine +# Uses Leapfrog for the time stepping +#--------------------------------------------------------------------------------------- +def HMCMC(U,grad_U,dt,nT,q): + ''' + Hamiltonian MCMC routine + + Input: + ----- + + U - potential energy function, -log(posterior) + grad_U - gradient of potential energy function + dt - time step, dt, for leapfrog method + nT - number of time steps in leapfrog method + q - initial state of chain (position vector) + + Output: + ------ + Next vector in the chain state + + Example: + ------- + q_next = HMCMC(U,grad_U,1e-2,25,q_current) + + ''' + current_q = npy.copy(q) # save current + + # generate current p + # propcov = 4*array([[ 0.01175383, 0.02065261],[ 0.02065261, 0.04296117]]) + p = npy.random.randn(len(current_q)) + # p = random.multivariate_normal([0,0],propcov) + current_p = npy.copy(p) # save current p + + # make half step for momentum used for leap frog step + p = p - dt * grad_U(q)/2.0 + + for i in range(nT): + # p = p - dt * grad_U(q)/2.0 + q = q + dt*p + # p = p - dt * grad_U(q)/2.0 + if (i != nT-1): p = p - dt*grad_U(q) + + # make a half step for momentum at the end + p = p - dt * grad_U(q)/2.0 + + # negate the momentum to make a symmetric proposal + p = -p + + # Evaluate potential and kinetic energy + current_U = U(current_q)[0] + current_K = npy.sum(current_p**2)/2.0 + proposed_U = U(q)[0] + proposed_K = npy.sum(p**2)/2.0 + + # Accept or reject the state at end of trajectory, returning either + # the position at the end of the trajectory or the initial position + + if (npy.log(npy.random.rand()) < current_U-proposed_U+current_K-proposed_K): + return q + else: + return current_q + + +#--------------------------------------------------------------------------------------- +# Example: +# 1. Banana-shaped posterior density +#--------------------------------------------------------------------------------------- +def norm_pdf_multivariate(x, mu, sigma): + """ + Multi-variate normal pdf + x : list or numpy array + mu : 1D numpy array + sigma: 2D numpy array""" + size = len(x) + if size == len(mu) and (size, size) == sigma.shape: + det = npy.linalg.det(sigma) + if det == 0: + raise NameError("The covariance matrix can't be singular") + norm_const = 1.0/ ( math.pow((2*npy.pi),float(size)/2) * math.pow(det,1.0/2) ) + x_mu = npy.matrix(x - mu) + inv = npy.linalg.inv(sigma) + result = math.pow(math.e, -0.5 * (x_mu * inv * x_mu.T)) + return norm_const * result + else: + raise NameError("The dimensions of the input don't match") + +def tranB(x1,x2,a): + """ + Coordinate transform for banana-shaped pdf + x1,x2: 2D numpy arrays + a: list containing the transform factors + """ + a1 = a[0]; a2 = a[1]; + y1 = a1*x1; + y2 = x2/a1 - a2*(y1**2 + a1**2); + return y1,y2 + +def invTranB(x1,x2,a): + """ Inverse coordinate transform for banana-shaped pdf + x1,x2: 2D numpy arrays + a: list containing the transform factors + """ + a1 = a[0]; a2 = a[1]; + y1 = x1/a1; + y2 = x2*a1 + a1*a2*(x1**2 + a1**2); + return y1,y2 + +def plotBanana(): + """ + Plot banana-shaped function; parameters are hard-wired + """ + xb,yb = npy.mgrid[-3:3:.05, -11:1:.05] + x, y = invTranB(xb,yb,[1,1]) + pos = npy.empty(x.shape + (2,)) + pos[:, :, 0] = x; pos[:, :, 1] = y + mu = npy.array([0.0,0.0]) + cov = npy.array([[1.0, 0.9], [0.9, 1.0]]) + z = x.copy() + for i in range(x.shape[0]): + for j in range(x.shape[1]): + z[i,j] = norm_pdf_multivariate([x[i,j],y[i,j]], mu, cov) + plt.contour(xb,yb,z,50) + plt.show() + return + +def postBanana(spl,postinfo): + """ + Computes the Log of the posterior density for banana-shaped pdf + + Input: + spl: Current parameter set sample + postinfo : Contains parameters for the posterior density + Output: + The log of the posterior density + """ + + afac = postinfo['afac'] + mu = postinfo['mu' ] + cov = postinfo['cov' ] + xb,yb = spl ; + x, y = invTranB(xb,yb,afac) ; + return npy.log(norm_pdf_multivariate([x,y], mu, cov)) + +def dram_ex(method,nsteps): + """ + Example using the DRAM sampler to explore the posterior of the banana-shaped + posterior density. + + Input: + method: either 'am' or 'dram' (see below under the dram function) + nsteps: number of steps to take (samples to take) + Output: + A tuple with samples and other information. See the dram function for more info. + """ + # define MCMC parameters (see below under the dram function for more info about these options) + cini = npy.array([-1.0,-4.0]) # Initial guesses + spllo = npy.array([-4.0,-12.0]) # Lower bounds on samples + splhi = npy.array([ 4.0, 2.0]) # Upper bounda on samples + cvini = npy.array([[0.1,0.0],[0.0,0.1]]) # Initial covariance matrix of proposal distribution + opts={'method':method,'nsteps':nsteps,'nburn':1000,'nadapt':100,'nfinal':10000000, + 'inicov':cvini,'coveps':1.e-10,'burnsc':5,'gamma':1.0,'ndr':2,'drscale':[5,4,3], + 'spllo':spllo,'splhi':splhi} + lpinfo={'afac':[1.0,1.0],'cov': npy.array([[1,0.9],[0.9,1]]),'mu':npy.array([0.0,0.0])} + sol=dram(opts,cini,postBanana,lpinfo) + return sol +#--------------------------------------------------------------------------------------- +# DRAM +#--------------------------------------------------------------------------------------- +def logPropRatio(iq,spls): + """ + Gaussian n:th stage log proposal ratio + log of q_i(y_n,..,y_n-j) / q_i(x,y_1,...,y_j) + """ + global invRmat + stage = len(spls)-1; + if stage == iq: + return (0.0); # symmetric + else: + iRmat = invRmat[iq-1]; # proposal^(-1/2) + y1 = spls[0] ; # y1 + y2 = spls[iq] ; # y_i + y3 = spls[stage ] ; # y_n + y4 = spls[stage-iq] ; # y_(n-i) + return (-0.5*(npy.linalg.norm(npy.dot(y4-y3,iRmat))**2-npy.linalg.norm(npy.dot(y2-y1,iRmat))**2)); + +def logPostRatio(p1,p2): + return (p2-p1); + +def getAlpha(spls,post): + stage = len(spls) - 1; + a1 = 1.0; a2 = 1.0; + for k in range(1,stage): + a1 = a1*(1-getAlpha(spls[:k+1],post[:k+1])); + a2 = a2*(1-getAlpha(spls[-1:-(k+1):-1],post[-1:-(k+1):-1])); + if a2 == 0.0: + return (0.0); + y = logPostRatio(post[0],post[-1]); + for k in range(1,stage+1): + y = y + logPropRatio(k,spls); + return min(1.0, npy.exp(y)*a2/a1); + +def ucov(spl,splmean,cov,lastup): + # + # update covariance + # + if len(spl.shape) == 1: + nspl = 1; + ndim = spl.shape[0]; + else: + (nspl,ndim)=spl.shape; + if nspl>0: + for i in range(nspl): + iglb = lastup+i; + splmean = (iglb*splmean+spl[i])/(iglb+1); + rt = (iglb-1.0)/iglb; + st = (iglb+1.0)/iglb**2; + cov = rt*cov+st*npy.dot(npy.reshape(spl[i]-splmean,(ndim,1)),npy.reshape(spl[i]-splmean,(1,ndim))) + return lastup+nspl,splmean,cov + +def dram(opts,cini,likTpr,lpinfo): + """ + # + # DRAM + # + Delayed Rejection Adaptive MCMC + opts - dictionary of parameters for DRAM + method : either 'am' (adaptive metropolis) or 'dram' (am+delayed rejection) + nsteps : no. of mcmc steps + nburn : no. of mcmc steps for burn-in (proposal fixed to initial covariance) + nadapt : adapt every nadapt steps after nburn + nfinal : stop adapting after nfinal steps + inicov : initial covariance + coveps : small additive factor to ensure covariance matrix is positive definite + (only added to diagonal if covariance matrix is singular without it) + burnsc : factor to scale up/down proposal if acceptance rate is too high/low + gamma : factor to multiply proposed jump size with in the chain past the burn-in phase + (Reduce this factor to get a higher acceptance rate.) + (Defaults to 1.0) + ndr : no. of delayed rejection steps (if dram is requested) + drscale: scale factors for delayed rejection + spllo : lower bounds for chain samples + splhi : upper bounds for chain samples + cini - starting mcmc state + likTpr - log-posterior function + lpinfo - dictionary with settings that will be passed to the log-posterior function + + Output: + spls: chain samples (dimension nsteps x chain dimension) + [cmode,pmode]: MAP estimate (cmode) and posterior at MAP estimate (pmode) + [1.0-float(rej)/nsteps, + 1.0-float(rejlim)/nsteps]: acceptance ratio and fraction of samples inside the bounds + [rej,rejlim]: total number of rejected samples and total number + of samples outside the bounds + meta_info: acceptance probability and posterior probability for each sample (dimension nsteps x 2) + + To Do: + Provide option to dump MCMC chain as the computations proceed, to avoid having such large + files to hold all states, and so that partial output is available during the MCMC run for + preliminary analysis. + """ + # ------------------------------------------------------------------------------- + # Parse options + # ------------------------------------------------------------------------------- + if 'method' in opts: + method = opts['method'] + else: + print 'Error in dram: method unspecified !'; quit() + + nsteps = opts['nsteps'] + nburn = opts['nburn' ] + nadapt = opts['nadapt'] + nfinal = opts['nfinal'] + inicov = opts['inicov'] + coveps = opts['coveps'] + burnsc = opts['burnsc'] + spllo = opts['spllo' ] + splhi = opts['splhi' ] + + if 'gamma' not in opts: + gamma = 1.0 # Default for backwards compatibility + else: + gamma = opts['gamma' ] + + if method=='dram': + ndr = opts['ndr'] + drscale = opts['drscale'] + + if 'ofreq' not in opts: + ofreq = 10000 # Default for backwards compatibility + else: + ofreq = opts['ofreq' ] + + rej = 0; # Counts number of samples rejected + rejlim = 0; # Counts number of samples rejected as out of prior bounds + rejsc = 0; # Counts number of rejected samples since last rescaling + # ------------------------------------------------------------------------------- + # Pre-processing + # ------------------------------------------------------------------------------- + cdim = cini.shape[0]; # chain dimensionality + cov = npy.zeros((cdim,cdim)); # covariance matrix + spls = npy.zeros((nsteps,cdim)); # MCMC samples + meta_info = npy.zeros((nsteps,2)) # Column for acceptance probability and posterior prob. of current sample + na = 0; # counter for accepted jumps + sigcv = 2.4*gamma/npy.sqrt(cdim); # covariance factor + spls[0] = cini; # initial sample set + p1 = likTpr(spls[0],lpinfo); # and posterior probability of initial sample set + meta_info[0] = [0.e0,p1] # Arbitrary initial acceptance and posterior probability of initial guess + pmode = p1; # store current chain MAP probability value + cmode = spls[0]; # current MAP parameter Set + nref = 0; # Samples since last proposal rescaling + # ------------------------------------------------------------------------------- + # Prepare temporary file + # ------------------------------------------------------------------------------- + tmp_file = str(uuid.uuid4())+'.dat' + print 'Saving intermediate chains to ',tmp_file + # ------------------------------------------------------------------------------- + # Main loop + # ------------------------------------------------------------------------------- + for k in range(nsteps-1): + # + # Deal with covariance matrix + # + covMatUpd = False + if k == 0: + splmean = spls[0]; + propcov = inicov ; + Rchol = scipy.linalg.cholesky(propcov) ; + lastup = 1; # last covariance update + covMatUpd = True ; + else: + if (nadapt>0) and ((k+1)%nadapt)==0: + if k0.95: + Rchol = Rchol/burnsc # scale down proposal + covMatUpd = True ; + print "Scaling down the proposal at step",k + elif float(rejsc)/nref<0.05: + Rchol = Rchol*burnsc # scale up proposal + covMatUpd = True ; + print "Scaling up the proposal at step",k + nref = 0 ; + rejsc = 0 ; + else: + lastup,splmean,cov=ucov(spls[lastup:lastup+nadapt,:],splmean,cov,lastup) + try: + Rchol = scipy.linalg.cholesky(cov) + except scipy.linalg.LinAlgError: + try: + # add to diagonal to make the matrix positive definite + Rchol = scipy.linalg.cholesky(cov+coveps*npy.identity(cdim)) + except scipy.linalg.LinAlgError: + print "Covariance matrix is singular even after the correction" + Rchol = Rchol*sigcv + covMatUpd = True ; + if (method == 'dram') and covMatUpd: + Rmat = [Rchol]; invRmat = [scipy.linalg.inv(Rchol)] + for i in range(1,ndr): + Rmat.append(Rmat[i-1]/drscale[i-1]) + invRmat.append(invRmat[i-1]*drscale[i-1]) + #-Done with covariance matrix + nref = nref + 1 ; + # + # generate proposal and check bounds + # + u = spls[k]+npy.dot(npy.random.randn(1,cdim),Rchol)[0]; + if npy.any(npy.less(u,spllo)) or npy.any(npy.greater(u,splhi)): + outofbound = True + accept = False + p2 = -1.e100 # Arbitrarily low posterior likelihood + pr = -1.e100 # Arbitrarily low acceptance probability + else: + outofbound = False + if not outofbound: + p2 = likTpr(u,lpinfo); + pr = npy.exp(p2-p1); + if (pr>=1.0) or (npy.random.random_sample()<=pr): + spls[k+1] = u.copy(); # Store accepted sample + meta_info[k+1] = [pr,p2] # and its meta information + p1 = p2; + if p1 > pmode: + pmode = p1 ; + cmode = spls[k+1] ; + accept = True + else: + accept = False + # + # See if we can do anything about a rejected proposal + # + if not accept: + if (method == 'am'): + # if 'am' then reject + spls[k+1]=spls[k]; + meta_info[k+1,0] = pr # acceptance probability of failed sample + meta_info[k+1,1] = meta_info[k,1] # Posterior probability of sample k that has been retained + rej = rej + 1; + rejsc = rejsc + 1; + if outofbound: + rejlim = rejlim + 1; + elif (method == 'dram'): + # try delayed rejection + tryspls = [spls[k].copy(),u.copy()] + trypost = [p1,p2] + jdr = 1 + while (not accept) and (jdr= 1.0) or (npy.random.random_sample() < alpha): + accept = True; + spls[k+1] = u.copy(); # Store accepted sample + meta_info[k+1] = [alpha,p2] # and its meta information + p1 = p2; + if p1 > pmode: + pmode = p1 ; + cmode = spls[k+1] ; + if not accept: + spls[k+1]=spls[k] ; + meta_info[k+1,0] = alpha # acceptance probability of failed sample + meta_info[k+1,1] = meta_info[k,1] # Posterior probability of sample k that has been retained + rej = rej + 1; + rejsc = rejsc + 1; + if outofbound: + rejlim = rejlim + 1; + else: + print "Unknown MCMC method ",method," -> Quit\n"; quit() + # Done with if over methods + # Done with if over original accept + if ((k+1)%ofreq==0): + print 'No. steps:',k+1,', No. of rej:',rej + fout = open(tmp_file, 'a+') + npy.savetxt(fout, spls[k-ofreq+1:k+1,:], fmt='%.8e',delimiter=' ', newline='\n') + fout.close() + # Done loop over all steps + + # return output: samples, MAP sample and its posterior probability, overall acceptance probability + # and probability of having sample inside prior bounds, overall number of samples rejected, and rejected + # due to being out of bounds. + return (spls,[cmode,pmode],[1.0-float(rej)/nsteps,1.0-float(rejlim)/nsteps],[rej,rejlim],meta_info) diff --git a/PyUQTk/inference/postproc.py b/PyUQTk/inference/postproc.py new file mode 100755 index 00000000..27e7941b --- /dev/null +++ b/PyUQTk/inference/postproc.py @@ -0,0 +1,999 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# +# Does statistical analysis on samples from an MCMC chain. + + +import os +import sys +import string +import numpy as np +import getopt +import math +import matplotlib.pyplot as plt +from scipy import stats, mgrid, c_, reshape, random, rot90 +from matplotlib.ticker import MultipleLocator, FormatStrFormatter + +try: + import pymc + have_pymc = True +except ImportError: + print "PyMC is required for some of the MCMC postprocessing codes." + print "Will proceed without, but some convergence tests will not be available." + have_pymc = False + +################################################################################## +# Compute autocorrelation a one-dimensional set of samples +# Main function is acor(X), where X is a numpy array of samples +################################################################################## +from numpy import * +from matplotlib.pyplot import * +def acor_in(X, MAXLAG, WINMULT): + + # compute mean of X + L = len(X) + mu = mean(X) + Xhat = X - mu + std = sqrt(var(X)) + + iMax = L - MAXLAG + + # compute autocorrelation + # sind = arange(MAXLAG+1) + iind = arange(iMax) + C = zeros(MAXLAG + 1) + for s in range(MAXLAG+1): + C[s] += sum(Xhat[iind]*Xhat[iind+s]) + C *= 1./iMax + + D = C[0] # diffusion coeff + D += 2*sum(C[1:]) + + sigma = sqrt(abs(D/L)) + tau = D/C[0] + + # print D, L, sigma, tau, tau*WINMULT, MAXLAG + return C[0], D, L, sigma, tau, tau*WINMULT, Xhat +# take in 1d numpy array of samples X +def acor(X,MAXLAG = 10, WINMULT = 5): + C0, D, L, sigma, tau, tauWINMULT, X = acor_in(X, MAXLAG, WINMULT) + # print tau, sigma + Ls = [] + S = [] + while tau*WINMULT >= MAXLAG: + Lh = L/2 + Ls.append(Lh) + j1,j2 = 0,1 + for i in range(Lh): + X[i] = X[j1] + X[j2] + j1 += 2 + j2 += 2 + _, D, L, sigma, tau, tauWINMULT, X = acor_in(X[:Lh], MAXLAG, WINMULT) + S.append(sigma) + if len(S) == 0: + S.append(sigma) + Ls.append(L) + + sigma = S[-1] + Ls = 2*array(Ls[::-1]) + for i in range(len(S)): + D = .25 * sigma**2 * Ls[i] + tau = D/C0 + sigma = sqrt(D/Ls[i]) + + return tau +################################################################################################### +def compute_group_auto_corr(v,maxlag): + """Compute autocorrelation of v, an array where each column is a set of samples, + for a lag ranging from 0 to maxlag-1. Ouputs numpy array with autocorrelation.""" + + # Get dimensions of input array with samples + n_pts = np.shape(v)[0] + n_var = np.shape(v)[1] + + # Initialize array + auto_corr = np.zeros((maxlag,n_var)) + + # Get mean and variance of v for each variable over the samples provided + v_m = v.mean(0) + v_var = v.var(0) + + + # Subtract the mean of v + v_nm = v - v_m + + # Compute autocovariance of v over all variables + for lag in range(maxlag): + n_sum = n_pts - lag # total number of terms in sum + for i in range(n_sum): + auto_corr[lag,:] += v_nm[i,:]*v_nm[i+lag,:] + auto_corr[lag,:] /= float(n_sum) + + # Normalize by variance + auto_corr /= v_var + + return auto_corr +################################################################################################### +def compute_auto_corr(v,maxlag): + """Compute autocorrelation of v (1D vector of samples) for a lag ranging from 0 to maxlag-1. + Ouputs numpy array with autocorrelation.""" + + # Initialize array + auto_corr = np.zeros(maxlag) + + # Get mean and variance of v + v_m = v.mean() + v_var = v.var() + n_pts = len(v) + + # Subtract the mean of v + v_nm = v - v_m + + # Compute autocovariance of v + for lag in range(maxlag): + n_sum = n_pts - lag # total number of terms in sum + for i in range(n_sum): + auto_corr[lag] += v_nm[i]*v_nm[i+lag] + auto_corr[lag] /= float(n_sum) + + # Normalize by variance + auto_corr /= v_var + + return auto_corr +################################################################################################### +def plot_auto_corr(v,vname): + """Plot autocorrelation (in v), for variable with name vname""" + + # Set up the figure + fig = plt.figure(figsize=(8,6)) + ax = fig.add_axes([0.10, 0.10, 0.85, 0.85]) + l1 = plt.plot(v,label=vname) + + ax.set_xlabel("lag") + ax.set_ylabel("autocorrelation") + plt.ylim([-0.1,1]) + + plt.legend() + plt.savefig("corr_"+vname+".pdf") + plt.close() + + return +################################################################################################### +def compute_effective_sample_size(n_sam,auto_corr): + """Computes the effective sample size for a vector of samples + by dividing the number of samples (n_sam) by the integral + of the autocorrelation (auto_corr) between the samples. (i.e. the more + correlated successive samples are, the less independent samples there are + in the chain.) + The algorithm is based on: + Markov Chain Monte Carlo in Practice: A Roundtable Discussion + Robert E. Kass, Bradley P. Carlin, Andrew Gelman and Radford M. Neal + The American Statistician, Vol. 52, No. 2 (May, 1998), pp. 93-100 + Published by: American Statistical Association + Article DOI: 10.2307/2685466 + Article Stable URL: http://www.jstor.org/stable/2685466 + """ + + # Length of autocorrelation array + n_ac = len(auto_corr) + + # Find the lag where the autocorrelation goes to zero (or below) + i_zero = 1 # start at lag 1 since the autocorrelation has value 1.0 at lag 0 by definition + done = False + while (i_zero < n_ac and not done): + if auto_corr[i_zero] > 0.0: + i_zero += 1 + else: + done = True + + if i_zero == n_ac: + print "WARNING: Autocorrelation did not go to zero within range provided" + + # Integral relies on symmetry and the fact that autocorrelation is 1 at zero lag + ESS = int(n_sam / (1.0+2.0*np.sum(auto_corr[1:i_zero]))) + + return ESS +################################################################################################### +################################################################################################### +def read_remaining_lines(samples_file,n_burnin,stride): + """Read all remaining lines in MCMC sample filename, leaving out the first n_burnin, + and only one in every stride lines after that + """ + samples_list = [] + line_no = 0 + done = 0 + while not done: + line = samples_file.readline() + if (line == ""): + done = 1 + else: + line_no += 1 + if (line_no > n_burnin and (line_no - n_burnin) % stride == 0): + records = line.split() + num_records = [float(s) for s in records] + samples_list.append(num_records) + + return samples_list + +################################################################################################### +def remove_MAP_line(samples_list,debug): + """Remove the last line if is has a value < 0 (i.e. -1) in the acceptance_prob column (next to last)""" + if(samples_list[-1][-2] < 0): + # Remove the last line + del samples_list[-1] + if (debug > 0): + print "The last sample line has been deleted as it contained the MAP values" + +################################################################################################### +def extract_vars(samples_file_name,n_burnin,v_names,debug,stride=1): + """From a file with samples in ascii format, with + the first line containing the label for each column, extract + the columns with the labels in v_names and return them + in a numpy array. Remove n_burnin samples from the top. + Only read one in every stride number of lines after that. + Assumes that the first column is the MCMC step number, the next to last column is the acceptance + probability for each step, and the last column is the posterior probability for each step. The + last line is removed if it contains -1 for the acceptance probability (which means this + line contains the MAP values)""" + + # Open text file with all samples, + samples_file = open(samples_file_name,"r") + + # Extract first line with the column labels and find the column + # numbers corresponding to the variables of interest. + labels_line = samples_file.readline().rstrip('\n') + col_labels = [lbl for lbl in labels_line.split()] + + v_indices = [] + for s_v in v_names: + try: + i_v = col_labels.index(s_v) + v_indices.append(i_v) + except ValueError: + print "Variable", s_v, "is not found in the list of labels", col_labels + sys.exit(1) + + if (debug > 0): + print "Column labels in file",samples_file_name,"are:",col_labels + for i_v in range(len(v_names)): + print "The column number of",v_names[i_v],"is:",v_indices[i_v] + + # Read subsequent lines + samples_list = read_remaining_lines(samples_file,n_burnin,stride) + + # Close the file + samples_file.close() + + # Remove MAP values, if present + remove_MAP_line(samples_list,debug) + + # Convert list to array + steady_samples = np.array(samples_list) + + + # Extract all columns of interest + samples_cols = [] + for i_v in v_indices: + samples_cols.append(steady_samples[:,i_v]) + + samples = np.array(samples_cols).T + if (debug > 0): + print "Shape of samples array:",samples.shape + + n_samples = len(samples[:,0]) + n_vars = len(samples[0,:]) + + if (debug > 0): + print "Read in", n_samples, "regular samples of", n_vars, "variables from file", samples_file_name + + return samples + +################################################################################################### +def extract_all_vars(samples_file_name,n_burnin,debug,stride=1,labels=True): + """Extract samples and labels from an MCMC chain file. + Assumes the following: + * The file is in ASCII format + * The first column contains the MCMC step number + * The next to last column contains the acceptance probability for the jump proposed in this step + * The last column contains the posterior probability of the state in this step + * The columns in between contain the sampled states + * Unless the argument labels == False, the first line contains labels for each column + * If the last line has -1 in the acceptance probability column, then this line contains + the MAP values. This line is removed before returning the samples to the calling program. + Arguments: + * samples_file_name: name of file to parse + * n_burnin: number of lines to skip from the top + * debug: higher values are more verbose in output + * stride: stride to take in parsing sample lines. [default = 1] + * labels: True if the file contains column labels in first line. False if not. [default = True] + If not column labels are present, they are manufactured as aa, ab, ac, ..., az, ba, bb, ... + Returns: + * A numpy array with samples (one sample of all parameters per row) + * A list of variable names + """ + + # Open text file with all samples + samples_file = open(samples_file_name,"r") + + + if (labels): # Column labels are present in first line + # Extract first line with the column labels + labels_line = samples_file.readline().rstrip('\n') + col_labels = [lbl for lbl in labels_line.split()] + + # Identify the MCMC vars, knowing that the first column is the step + # number and the last two columns are acceptance and posterior prob + n_cols = len(col_labels) + n_vars = n_cols - 3 + + v_names = col_labels[1:1+n_vars] + + if (debug > 0): + print "Column labels in file", samples_file_name, "are:", col_labels + print "MCMC chain variables are", v_names + else: + # Extract first line to see how many columns we have + first_line = samples_file.readline().rstrip('\n') + first_line_items = [item for item in first_line.split()] + + # Identify the MCMC vars, knowing that the first column is the step + # number and the last two columns are acceptance and posterior prob + n_cols = len(first_line_items) + n_vars = n_cols - 3 + + # Generate variable names as aa, ab, ..., az, ba, bb, ... + if (n_vars > 52*26): # only 52 entries in string.letters. If need be, could go higher by allowing aA, aB, ... , Aa, ... + print "In routine extract_all_vars: too many columns for automatic name generation" + sys.exit(1) + + v_names = [] + for i_v in range(n_vars): + name = "" + name += string.letters[i_v/26] + name += string.letters[i_v%26] + v_names.append(name) + + if (debug > 0): + print "There are",n_cols," columns in file", samples_file_name + print "MCMC chain variables have been labeled", v_names + + # Rewind file so the first line will be read just like the other sample lines + samples_file.seek(0) + + # Read subsequent lines + samples_list = read_remaining_lines(samples_file,n_burnin,stride) + + # Close the file + samples_file.close() + + # Remove MAP values, if present + remove_MAP_line(samples_list,debug) + + # Convert list to array + samples = np.array(samples_list) + + n_samples = samples.shape[0] + + if (debug > 0): + print "Read in", n_samples, "regular samples of", n_vars, "variables from file", samples_file_name + + return samples, v_names + +################################################################################################### +# def effective_sample_sizes(var_samples,par_mean,par_cov): +# """Computes the effective sample size for each column +# by dividing the number of samples by the integral +# of the autocorrelation between the samples. (i.e. the more +# correlated successive samples are, the less independent samples there are +# in the chain.) +# The algorithm is based on: +# Markov Chain Monte Carlo in Practice: A Roundtable Discussion +# Robert E. Kass, Bradley P. Carlin, Andrew Gelman and Radford M. Neal +# The American Statistician, Vol. 52, No. 2 (May, 1998), pp. 93-100 +# Published by: American Statistical Association +# Article DOI: 10.2307/2685466 +# Article Stable URL: http://www.jstor.org/stable/2685466 +# """ +# +# # Number of variable samples in set +# n_sam = var_samples.shape[0] +# # Number of variables in this sample set +# n_vars = var_samples.shape[1] +# +# # Array to store effective sample sizes in +# ess = [] +# +# # Cut-off point for autocorrelation +# # Ideally, n_a should be chosen such that the autocorrelation goes to 0 at this lag. +# # Chosing n_a too low will give inaccurate results (overpredicting ESS), but going +# # to much higher lag will create a lot of noise in ESS estimate. +# n_a = min(100,n_sam) +# for i_v in range(n_vars): +# # Subtract mean from current variable samples +# v_nm = var_samples[:,i_v] - par_mean[i_v] +# # Compute autocorrelation for this variable. np.autocorrelate returns vector with +# # lag from -n_sam to n_sam, with the 0 shift in the middle. Only retain from lag 0 to n_a. +# r_v = np.correlate(v_nm, v_nm, mode = 'full')[-n_sam:-n_sam+n_a] +# # Devide by number of samples in each sum, and normalize by variance +# # (note: 0 lag has n_sam samples in sum, lag i has (n_sam - i) samples in sum +# r_a = r_v / (par_cov[i_v,i_v]*(np.arange(n_sam, n_sam-n_a, -1))) +# # Plot autocorrelation to see if n_a is large enough +# #pl1,=plt.plot(r_a) +# #plt.show() +# # Effective Sample Size (Number of samples devided by integral of autocorrelation) +# # Integral relies on symmetry and the fact that r_a is 1 at zero lag +# ess.append(n_sam / (1.0+2.0*np.sum(r_a[1:]))) +# +# return ess + +################################################################################################### +def plot_all_posteriors(d0,vnames,np_kde,out_file_base,debug,dense=False): + """ + Given a set of samples of random variables, this script plots a lower triangular + matrix of marginalized densities. The diagonal contains the density of individual + random variables, marginalized over all other variables. Plots below the diagonal + contain the 2D density of the associated pair of random variables, marginalized over + all other variables. + For chains with many variables, the "dense" option can be selected, which plots the + triangular set of densities for the full chain with minimum spacing and labels, so that + it is less cluttered. In this mode, this function also writes out a set of plots + with the same posterior information, but just for two variables at the time, + which is easier to read. + + Arguments: + d0 : Set of samples, one column per variable (no extra columns) + vnames : Variable names + np_kde : Number of points to use to compute posterior densities with KDE + out_file_base: Base name for output files with plots + debug : >0 writes more output to screen (and even more if >1) + dense : Set to True if dense output desired [Defaults to False]. The "dense" output + format puts all plots in the triangular format up against each other, without + any axis labels or space in between them. It is useful when plotting the + posteriors of a chain with many variables. + """ + # Some settings to connect with code Cosmin gave me + nthin = 1 # take only every nthin state (for faster kde) + nskip = 0 # entries to skip + istart = 0 # number of column with first MCMC variable + cend = 0 # extra columns at end to be removed + + nvars=d0.shape[1]-istart-cend # number of variables we will actually process + print 'Number of sample lines in file',d0.shape[0] + print 'Number of vars we will process in file',nvars + + # Section 2 + # set up 2D kde objects + print "Setting up 2D KDE objects" + kern_i_j=[] + for j in range(istart+1,istart+nvars): + for i in range(istart,j): + if (debug > 2): + print i,j + kern_i_j.append(stats.kde.gaussian_kde(c_[d0[nskip::nthin,i],d0[nskip::nthin,j]].T)) + + # Section 3 + # set up 2D meshes and evaluate kde objects on those meshes + # no. of grid points is controlled with kde_idx, defaults to 100 + print "Evaluating 2D KDE objects on meshes. This may take a while ..." + kde_idx = np_kde*1j # complex number to include end points + xmesh=[]; ymesh=[]; zmesh=[]; + icount=0 + cov_idx = np.zeros((nvars,nvars),dtype=np.int) # 2D array to keep track of which index in xmesh etc. the + # the plots corresponding to vars i,j belong to + for j in range(istart+1,istart+nvars): + for i in range(istart,j): + if (debug > 0): + print "Computing 2D marginal distribution between variables:",i,",",j,":",vnames[i]," & ",vnames[j] + x,y = mgrid[d0[nskip:,i].min():d0[nskip:,i].max():kde_idx, d0[nskip:,j].min():d0[nskip:,j].max():kde_idx] + z = reshape(kern_i_j[icount](c_[x.ravel(), y.ravel()].T).T, x.T.shape) + xmesh.append(x); + ymesh.append(y); + zmesh.append(z); + cov_idx[i,j] = icount + icount = icount+1 + + # Section 4 + # evaluate 1D pdfs + print "Evaluating 1D marginal pdfs with KDE" + xlin=[]; pdflin=[]; + for i in range(istart,istart+nvars): + xlin.append(np.linspace(d0[nskip:,i].min(),d0[nskip:,i].max(),np_kde)) ; + kernlin=stats.kde.gaussian_kde(d0[nskip::nthin,i]); + pdflin.append(kernlin(xlin[i-istart])); + + # Formatting for plots + fs1=20 # Font size + lw1=2 # Line width + + if (not dense): + # Section 5 + print "Assembling lower-triangular plots in non-dense format" + + # ds is the distance between subplots + # xs,ys are the coordinates (normalized) of the subplot in the lower left corner + # xe,ye are the distances left in the uppper right corner + # fsizex, fsizey are figure sizes + # ncont are no of contours for 2D pdfs + xs=0.12; ys=0.1; ds=0.04 + xe=0.08; ye=0.05 + fsizex=12; fsizey=12; + ncont=20; + sx=(1-(nvars-1)*ds-xs-xe)/nvars; + sy=(1-(nvars-1)*ds-ys-ye)/nvars; + majorFormatter = FormatStrFormatter('%6.0e') + + figname=out_file_base+".lowertriangle.pdf" # figure name + + fig = plt.figure(figsize=(fsizex,fsizey)) + + # Section 5.1 + subs=[] + # add diagonal plots + for i in range(nvars): + subs.append(fig.add_axes([xs+i*(sx+ds),ys+(nvars-1-i)*(sy+ds),sx,sy])) + + # add lower triangular plots + for i in range(nvars-1): + for j in range(i+1): + if (debug > 2): + print j,(nvars-2-i) + subs.append(fig.add_axes([xs+j*(sx+ds),ys+(nvars-2-i)*(sy+ds),sx,sy])) + + subsnp=np.array(subs) + + # Plot 1D pdfs + for i in range(nvars): + subsnp[i].plot(xlin[i],pdflin[i]) + + # Plot 2D pdfs + for i in range(nvars*(nvars-1)/2): + subsnp[nvars+i].contour(xmesh[i],ymesh[i],zmesh[i],ncont) + + # Section 5.2 + # just a few ticks and ticklabels + for subpl in subsnp: + # subpl.set_xticks([]) + # subpl.set_yticks([]) + subpl.locator_params(tight=True, nbins=5) + + # for diagonal plots, put no ticks and lables on y-axis + # and no grid on the plots + for i in range(istart,istart+nvars): + # subsnp[i-istart].set_xticks([d0[nskip:,i].min(),d0[nskip:,i].max()]); + subsnp[i-istart].set_yticks([]) + subsnp[i-istart].grid(False) + + # Set y labels on the right for diagonal plots + for i in range(nvars): + subsnp[i].yaxis.tick_right() + subsnp[i].yaxis.set_label_position("right") + subsnp[i].set_ylabel(vnames[i], fontsize=fs1) + #subsnp[i].set_ylabel(r'$'+vnames[i]+'$', fontsize=fs1) + + plt.savefig(figname) + plt.close() + + else: + # Section 5 + # Dense plot format: print full lower-triangular matrix but w/o any white space, tick marks or labels. + print "Assembling lower-triangular plots in dense format" + + # ds is the distance between subplots + # xs,ys are the coordinates (normalized) of the subplot in the lower left corner + # xe,ye are the distances left in the uppper right corner + # fsizex, fsizey are figure sizes + # ncont are no of contours for 2D pdfs + xs=0.12; ys=0.1; ds=0.0 + xe=0.08; ye=0.05 + fsizex=12; fsizey=12; + ncont=10; + sx=(1-(nvars-1)*ds-xs-xe)/nvars; + sy=(1-(nvars-1)*ds-ys-ye)/nvars; + majorFormatter = FormatStrFormatter('%6.0e') + + figname=out_file_base+".lowertriangle-dense.pdf" # figure name + + fig_d = plt.figure(figsize=(fsizex,fsizey)) + + # Section 5.1 + subs=[] + # add diagonal plots + for i in range(nvars): + subs.append(fig_d.add_axes([xs+i*(sx+ds),ys+(nvars-1-i)*(sy+ds),sx,sy])) + + # add lower triangular plots + for i in range(nvars-1): + for j in range(i+1): + if (debug > 2): + print j,(nvars-2-i) + subs.append(fig_d.add_axes([xs+j*(sx+ds),ys+(nvars-2-i)*(sy+ds),sx,sy])) + + subsnp=np.array(subs) + + # Plot 1D pdfs along diagonals + for i in range(nvars): + subsnp[i].plot(xlin[i],pdflin[i]) + + # Plot 2D pdfs + for i in range(nvars*(nvars-1)/2): + subsnp[nvars+i].contour(xmesh[i],ymesh[i],zmesh[i],ncont) + + # Section 5.2 + # no ticks and ticklabels on most plots + for subpl in subsnp: + subpl.set_xticks([]); + subpl.set_yticks([]); + + # Set variable names as title for diagonal marginal plots + for i in range(nvars): + subsnp[i].set_title(vnames[i], fontsize=fs1) + # subsnp[i].yaxis.set_label_position("right") + # # Plot variable names along diagonal on the right. Plot them at angle + # # to make them easier to read. Hack to add some white space in front of label + # # so that it does not overlap with plot frame. + # subsnp[i].set_ylabel(" "+vnames[i], fontsize=fs1, rotation=45) + # #subsnp[i].set_ylabel(r'$'+vnames[i]+'$', fontsize=fs1) + + + plt.savefig(figname) + plt.close() + + print "Assembling marginal density plots for all pairs of MCMC variables" + + # ds is the distance between subplots + # xs,ys are the coordinates (normalized) of the subplot in the lower left corner + # xe,ye are the distances left in the uppper right corner + # fsizex, fsizey are figure sizes + # ncont are no of contours for 2D pdfs + xs=0.12; ys=0.1; ds=0.04 + xe=0.08; ye=0.05 + fsizex=12; fsizey=12; + ncont=20; + nvars_sm=2 + sx=(1-(nvars_sm-1)*ds-xs-xe)/nvars_sm; + sy=(1-(nvars_sm-1)*ds-ys-ye)/nvars_sm; + fs1=20 + majorFormatter = FormatStrFormatter('%6.0e') + + + # loop over all pairs of MCMC variables. + for j in range(istart+1,istart+nvars): + for i in range(istart,j): + + print "Plotting densities for variables",vnames[i],"and",vnames[j] + figname=out_file_base + "." + vnames[i] + "-" + vnames[j] + ".pdf" + + fig_sm = plt.figure(figsize=(fsizex,fsizey)) + + subs=[] + # add diagonal plots + subs.append(fig_sm.add_axes([xs ,ys+(sy+ds),sx,sy])) # marginal for var i + subs.append(fig_sm.add_axes([xs+(sx+ds),ys ,sx,sy])) # marginal for var j + + # add lower triangular plot + subs.append(fig_sm.add_axes([xs ,ys ,sx,sy])) # marginal for vars i,j + + subsnp=np.array(subs) + + # Plot 1D pdfs + subsnp[0].plot(xlin[i],pdflin[i]) + subsnp[1].plot(xlin[j],pdflin[j]) + + # Plot 2D pdfs + i_2D = cov_idx[i,j] + subsnp[2].contour(xmesh[i_2D],ymesh[i_2D],zmesh[i_2D],ncont) + + # set just a few ticks and ticklabels + for subpl in subsnp: + subpl.locator_params(tight=True, nbins=5) + + # no ticks and ticklabels on y axes on diagonals (first two plots in subsnp array) + # no grid on diagonal plots + for subpl in subsnp[0:2]: + subpl.set_yticks([]) + subpl.grid(False) + + # for diagonal plots only put xmin and xmax + #subsnp[0].set_xticks([d0[nskip:,i].min(),d0[nskip:,i].max()]); + #subsnp[1].set_xticks([d0[nskip:,j].min(),d0[nskip:,j].max()]); + + + # Set y labels on the right for diagonal plots + #subsnp[0].yaxis.tick_right() + subsnp[0].yaxis.set_label_position("right") + subsnp[0].set_ylabel(vnames[i], fontsize=fs1) + + #subsnp[1].yaxis.tick_right() + subsnp[1].yaxis.set_label_position("right") + subsnp[1].set_ylabel(vnames[j], fontsize=fs1) + + # Write out figure + plt.savefig(figname) + plt.close() + +################################################################################################### +def get_mcmc_stats(all_samples,v_names,out_file_base,debug): + """ + Generate statistics of the passed in MCMC samples. + Assumes that the first column of all_samples contains the step number, and the last two + columns contain the acceptance probability and the posterior probability for each sampled state. + + Inputs: + all_samples : Array with all samples (one sample set per row). Has step number in first + column and acceptance probability and posterior in last two columns + v_names : Actual variable names + out_file_base : Base for output file names + debug : Writes out more info if number is larger + + Outputs: + Various statistics written to the screen + Correlation functions written to pdf files + Returns array of map values + """ + + # Number of variables, columns, samples in the file + n_vars = len(v_names) + n_cols = all_samples.shape[1] + n_sam = all_samples.shape[0] + + # Extract all MCMC chain variables in separate array + var_samples = all_samples[:,1:1+n_vars] + if (debug > 0): + print var_samples.shape + + # Compute mean parameter values + par_mean = np.mean(var_samples,axis=0,dtype=np.float64) + + #print "\nParameter mean values:\n" + #for i_v in range(n_vars): + # print " ", v_names[i_v], ":", par_mean[i_v] + + # Compute the covariance + par_cov = np.cov(var_samples,rowvar=0) + + print "\nParameter covariances:\n" + print par_cov + + # write out covariance matrix to file + cov_file_name = out_file_base + ".covariance.dat" + np.savetxt(cov_file_name,par_cov) + + # print the square root of the diagonal entries of the covariance + #print "\nParameter standard deviations (proposal width estimates):\n" + #for i_v in range(n_vars): + # print " ", v_names[i_v], ":", math.sqrt(par_cov[i_v,i_v]) + + # + # Compute the MAP values + # (could also get this from the last line of the MCMC output file + # but this line is not always there; and it is more fun + # to do it with Python) + # + + # Sample index with max posterior prop (last column in MCMC file): + i_map = all_samples[:,-1].argmax() + + print "\n", + print '%27s' % "Parameter :", '%15s' % "Mean Value", '%15s' % "MAP values", '%15s' % "Std. Dev." + for i_v in range(n_vars): + print '%25s' % v_names[i_v], ":", '%15.8e' % par_mean[i_v], '%15.8e' % var_samples[i_map,i_v], + print '%15.8e' % math.sqrt(par_cov[i_v,i_v]) + + # Write mean and MAP to file + mean_file_name = out_file_base + ".mean.dat" + np.savetxt(mean_file_name,par_mean) + + map_file_name = out_file_base + ".map.dat" + np.savetxt(map_file_name,var_samples[i_map,:]) + + # Compute mean and standard deviation of acceptance probability + print "\nAcceptance Probability:\n" + + # In some cases, the next to last column contains the ratio of posterior + # values rather than the acceptance probability. First convert this number + # to acceptance probabilities: acc_prob = min(alpha,1) + # (This does no harm if the next to last column already contains the actual acceptance probability) + acc_prob = np.minimum(all_samples[:,-2],np.ones_like(all_samples[:,-2])) + # In some cases, a very large negative number is shown in the column for acceptance + # probability to indicate a proposed value was out of bounds. In that case, replace + # the value with 0. Again, this does no harm if the next to last column already contains + # the actual acceptance probability. + acc_prob = np.maximum(acc_prob,np.zeros_like(acc_prob)) + print "Mean :",acc_prob.mean(), + print "Std. Dev.:",acc_prob.std() + + # # + # # Compute effective sample size (ESS) + # # + # print "\nEffective Sample Sizes:\n" + # + # ess = effective_sample_sizes(var_samples,par_mean,par_cov) + # + # for i_v in range(n_vars): + # print " ",v_names[i_v],":",int(ess[i_v]),"out of",n_sam + + # + # Compute autocorrelations and effective sample size (ESS) + # + print "\nAutocorrelations and Effective Sample Sizes:\n" + + # Number of variable samples in this file + n_sam = var_samples.shape[0] + + # Cut-off point for autocorrelation + # Ideally, n_a should be chosen such that the autocorrelation goes to 0 at this lag. + # Chosing n_a too low will give inaccurate results (overpredicting ESS), but going + # to much higher lag will create a lot of noise in ESS estimate. + n_a = min(1000,n_sam) + + # Autocorrelation computation + auto_corr_vars = compute_group_auto_corr(var_samples,n_a) + + # Plotting and computation of effective sample size + for i_v in range(n_vars): + # Plot autocorrelation to see if n_a is large enough + plot_auto_corr(auto_corr_vars[:,i_v],v_names[i_v]) + # Effective Sample Size (Number of samples divided by integral of autocorrelation) + ESS = compute_effective_sample_size(n_sam,auto_corr_vars[:,i_v]) + print " ",v_names[i_v],":",ESS,"out of",n_sam," ; skip factor:",n_sam/ESS + + print "\n See plots corr-*.pdf for autocorrelations of chain samples for all variables." + + # The following operations rely on PyMC + if have_pymc: + # + # Compute Raftery-Lewis convergence test + # + print "\nComputing Raftery-Lewis criteria for all variables\n" + quant = 0.025 # Quantile level to be estimated + relacc = 0.01 # Error in quantile level (relative to the mean of the parameter) + conf = 0.95 # Confidence in the achieved accuray + print " Computing # of samples needed to compute quantile",quant + print " for an accuracy",relacc*100,"% relative to parameter mean, with confidence",conf*100,"%:\n" + print " Variable name: # initial samples to skip, # additional samples to take, thinning factor" + for i_v in range(n_vars): + output = pymc.raftery_lewis(var_samples[:,i_v], q=quant, r=relacc*par_mean[i_v], s=conf, verbose=0) + print " ",'%25s' % v_names[i_v], ":", '%8d' % output[2],",",'%8d' % output[3],",",'%8d' % output[4] + + print "\n" + + quant = 0.5 # Quantile level to be estimated + print " Computing # of samples needed to compute quantile",quant + print " for an accuracy",relacc*100,"% relative to parameter mean, with confidence",conf*100,"%:\n" + print " Variable name: # initial samples to skip, # additional samples to take, thinning factor" + for i_v in range(n_vars): + output = pymc.raftery_lewis(var_samples[:,i_v], q=quant, r=relacc*par_mean[i_v], s=conf, verbose=0) + print " ",'%25s' % v_names[i_v], ":", '%8d' % output[2],",",'%8d' % output[3],",",'%8d' % output[4] + + # + # Geweke test + # + print "\nComputing Geweke test for all variables\n" + print "Geweke Test temporarily disabled. Needs to be debugged." + # for i_v in range(n_vars): + # var_scores = pymc.geweke(var_samples[:,i_v], intervals=20) + # pymc.Matplot.geweke_plot(var_scores, v_names[i_v]) + # print " See plots *-diagnostic.png" + + # + # Autocorrelations (done above already) + # + # print "\nComputing autocorrelations for all variables\n" + # for i_v in range(n_vars): + # pymc.Matplot.autocorrelation(var_samples[:,i_v], v_names[i_v]) + # print " See plots *-acf.png" + + return var_samples[i_map,:] + +################################################################################################### + +help_string = """ +Usage: + postproc.py [-h] -i [--nb ] [-s ] [--nolabels] +What: + Compute elementary statistics of MCMC chain +Where + -h = print help info + -i = name of file containing MCMC data + -s = stride with which to read the file [defaults to 1] + --nb = number of burn-in samples to be removed from the chain [defaults to 0] + --nolabels Indicates that the MCMC data file does not contain column labels (in which case they are generated) +Assumes the following: + * The file is in ASCII format + * The first column contains the MCMC step number + * The next to last column contains the acceptance probability for the jump proposed in this step + * The last column contains the posterior probability of the state in this step + * The columns in between contain the sampled states + * Unless the argument labels == False, the first line contains labels for each column +""" + +if __name__ == "__main__": + # + # Process inputs + # + try: + opts,v_names = getopt.getopt(sys.argv[1:],"hi:s:",["nb=","nolabels"]) + except getopt.GetoptError, err: + print str(err) + print help_string + sys.exit(1) + + # Default values + samples_file_name="" + n_burnin = 0 + stride = 1 + labels_present = True + + for o,a in opts: + if o == "-h": + print help_string + sys.exit(0) + elif o == "-i": + samples_file_name = a + elif o == "-s": + stride = int(a) + elif o == "--nb": + n_burnin = int(a) + elif o == "--nolabels": + labels_present = False + else: + assert False, "Unhandled command line parsing option. Use -h flag to get usage info." + + # error checking + if(samples_file_name==""): + print "Sample file name must be specified" + print help_string + sys.exit(1) + + if (n_burnin < 0): + print "The number of burn-in samples needs to be >= 0" + print help_string + sys.exit(1) + + if (stride < 0): + print "The file read stride needs to be >= 0" + print help_string + sys.exit(1) + + # Base name of file for outputting results + out_file_base = samples_file_name + ".nb" + str(n_burnin) + ".s" + str(stride) + + # Set to 1 to get more output to screen + # Set to > 1 to get a lot of output to screen + debug = 1 + + # Set to 1 for showing plots interactively + interact = 0 + + # + # Import variables of interest from the MCMC data file + # + all_samples, v_names = extract_all_vars(samples_file_name,n_burnin,debug,stride,labels=labels_present) + + # Get statistics + get_mcmc_stats(all_samples,v_names,out_file_base,debug) diff --git a/PyUQTk/mcmc/CMakeLists.txt b/PyUQTk/mcmc/CMakeLists.txt new file mode 100644 index 00000000..a4c7ce72 --- /dev/null +++ b/PyUQTk/mcmc/CMakeLists.txt @@ -0,0 +1,67 @@ +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}/../../Extras/lib/python/numpy/core/include) + +#include source files +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/) # array classes, array input output, and array tools +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/include/) # utilities like error handlers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/) # tools like multindex, etc. +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/) # quad class +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/kle/) # kle class +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/) # PCSet and PCBasis classes +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/bcs/) # bcs +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/mcmc/) # mcmc + +# include dependencies +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/blas/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lapack/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lbfgs/) # blas library +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/dsfmt/) # dsfmt +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/figtree/) # figtree +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/slatec/) # slatec headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/cvode-2.7.0/include) # cvode +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/dep/cvode-2.7.0/include) +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/dep/cvode-2.7.0/include/nvector) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../numpy/) # numpy headers + +SET(CMAKE_SWIG_FLAGS "") +SET_SOURCE_FILES_PROPERTIES(mcmc.i PROPERTIES CPLUSPLUS ON) + +# compile swig with cpp extensions +SWIG_ADD_MODULE( + mcmc python mcmc.i + # array tools needed to compile misc tools source files + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arrayio.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arraytools.cpp + + # source code for quad and kle class + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/quad.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/kle/kle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/mcmc/mcmc.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/PCSet.cpp + + # source code for tools + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/combin.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/gq.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/minmax.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/multiindex.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/pcmaps.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/probability.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/rosenblatt.cpp +) + +# link python and 3rd party libraries, e.g., gfortran and blas +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + SWIG_LINK_LIBRARIES(mcmc deplbfgs uqtkbcs uqtkpce uqtktools uqtkquad uqtkarray depnvec deplapack depblas depslatec depdsfmt depann depfigtree depcvode gfortran ${PYTHON_LIBRARIES}) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + SWIG_LINK_LIBRARIES(mcmc deplbfgs uqtkbcs uqtkpce uqtktools uqtkquad uqtkarray depnvec deplapack depblas depslatec depdsfmt depann depfigtree depcvode ifcore ifport ${PYTHON_LIBRARIES}) +endif() + +INSTALL(TARGETS _mcmc DESTINATION PyUQTk/) +INSTALL(FILES ${CMAKE_BINARY_DIR}/${outdir}PyUQTk/mcmc/mcmc.py DESTINATION PyUQTk) diff --git a/PyUQTk/mcmc/mcmc.i b/PyUQTk/mcmc/mcmc.i new file mode 100644 index 00000000..4a886c94 --- /dev/null +++ b/PyUQTk/mcmc/mcmc.i @@ -0,0 +1,143 @@ +%module(directors="1") mcmc +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2013) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== + +%feature("autodoc", "3"); +%rename(Assign) *::operator=; +%ignore *::operator[]; + +%{ +#define SWIG_FILE_WITH_INIT +#include +#include +#include +#include +#include +#include "../../cpp/lib/array/Array1D.h" +#include "../../cpp/lib/array/Array2D.h" +// #include "../../cpp/lib/array/arrayio.h" +// #include "../../cpp/lib/array/arraytools.h" +// #include "../../cpp/lib/tools/combin.h" +// #include "../../cpp/lib/tools/gq.h" +// #include "../../cpp/lib/tools/minmax.h" +// #include "../../cpp/lib/tools/multiindex.h" +// #include "../../cpp/lib/tools/pcmaps.h" +// #include "../../cpp/lib/tools/probability.h" +// #include "../../cpp/lib/tools/rosenblatt.h" + +// #include "../../cpp/lib/quad/quad.h" +// #include "../../cpp/lib/kle/kle.h" +// #include "../../cpp/lib/pce/PCBasis.h" +// #include "../../cpp/lib/pce/PCSet.h" +#include "../../cpp/lib/mcmc/mcmc.h" + +%} + +%feature("director") LikelihoodBase; +/************************************************************* +// Standard SWIG Templates +*************************************************************/ + +// Include standard SWIG templates +// Numpy array templates and wrapping +%include "pyabc.i" +%include "../numpy/numpy.i" +%include "std_vector.i" +%include "std_string.i" +%include "cpointer.i" + +%init %{ + import_array(); +%} + +%pointer_functions(double, doublep); + +/************************************************************* +// Numpy SWIG Interface files +*************************************************************/ + +// // Basic typemap for an Arrays and its length. +// // Must come before %include statement below + +// // For Array1D setnumpyarray4py function +// %apply (long* IN_ARRAY1, int DIM1) {(long* inarray, int n)} +// %apply (double* IN_ARRAY1, int DIM1) {(double* inarray, int n)} +// // get numpy int and double array +// %apply (long* INPLACE_ARRAY1, int DIM1) {(long* outarray, int n)} +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* outarray, int n)} + +// // For Array2D numpysetarray4py function +// %apply (double* IN_FARRAY2, int DIM1, int DIM2) {(double* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (double* INPLACE_FARRAY2, int DIM1, int DIM2) {(double* outarray, int n1, int n2)} +// // For Array2D numpysetarray4py function +// %apply (long* IN_FARRAY2, int DIM1, int DIM2) {(long* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (long* INPLACE_FARRAY2, int DIM1, int DIM2) {(long* outarray, int n1, int n2)} + + +// // For mcmc test to get log probabilities +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* l, int n)} + +/************************************************************* +// Include header files +*************************************************************/ + +// // The above typemap is applied to header files below +%include "../../cpp/lib/array/Array1D.h" +%include "../../cpp/lib/array/Array2D.h" +// %include "../../cpp/lib/array/arrayio.h" +// %include "../../cpp/lib/array/arraytools.h" +// %include "../../cpp/lib/tools/combin.h" +// %include "../../cpp/lib/tools/gq.h" +// %include "../../cpp/lib/tools/minmax.h" +// %include "../../cpp/lib/tools/multiindex.h" +// %include "../../cpp/lib/tools/pcmaps.h" +// %include "../../cpp/lib/tools/probability.h" +// %include "../../cpp/lib/tools/rosenblatt.h" + +// %include "../../cpp/lib/quad/quad.h" +// %include "../../cpp/lib/kle/kle.h" +// %include "../../cpp/lib/pce/PCBasis.h" +// %include "../../cpp/lib/pce/PCSet.h" +%include "../../cpp/lib/mcmc/mcmc.h" + +// // Typemaps for standard vector +// // Needed to prevent to memory leak due to lack of destructor +// // must use namespace std +// namespace std{ +// %template(dblVector) vector; +// %template(intVector) vector; +// %template(strVector) vector; + +// } + + +// %include "swigi/arrayext.i" + + + diff --git a/PyUQTk/multirun/CMakeLists.txt b/PyUQTk/multirun/CMakeLists.txt new file mode 100644 index 00000000..717a4fa8 --- /dev/null +++ b/PyUQTk/multirun/CMakeLists.txt @@ -0,0 +1,12 @@ +project (UQTk) + +SET(copy_FILES + __init__.py + multirun.py + srun.x + ) + +INSTALL(FILES ${copy_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION PyUQTk/multirun +) diff --git a/PyUQTk/multirun/__init__.py b/PyUQTk/multirun/__init__.py new file mode 100755 index 00000000..924173a4 --- /dev/null +++ b/PyUQTk/multirun/__init__.py @@ -0,0 +1,27 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import multirun diff --git a/PyUQTk/multirun/multirun.py b/PyUQTk/multirun/multirun.py new file mode 100755 index 00000000..1713b43c --- /dev/null +++ b/PyUQTk/multirun/multirun.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +# A quick hack to submit jobs in a multi-node SMP runtime environment. +# Written in March 2006 by Helgi Adalsteinsson and modified for our +# purpose in April 2006 by Bert Debusschere. +# Modified further by Khachik Sargsyan 2008-15 + +import os +import thread +import time +import shutil +import sys +import string +import getopt + + + + +# Get an array containing names for all of the CPUs we plan on using. We assume +# that there are a given number of cpus available for us in the SMP machine. We +# give them fictitional names cpu0, cpu1, ..., cpun. The number of cpus that is +# specified determines the number of parallel threads we can have going. +def avail_cpus(ncpus = 3): + """The optional argument specified how many cpus we plan on using.""" + cpus = [] + for icpu in range(ncpus): + cpus.append('cpu' + str(icpu)) + return cpus + +# Use fork/exec to run the given command with arguments, +# returns control when the shell command completes +def run_command(cmd, *args): + """Given a command and its argument list, use fork/execvp to run the + command. Note that this is a direct wrapper for the C library function, + so the first argument in args should (by convention) be the command name""" + if len(args) == 0: + # execvp does not permit an empty tuple as an argument list + args = ("",) + # Fork off + pid = os.fork() + if pid < 0: + raise RuntimeError("run_command: Failed to fork") + elif pid == 0: + # I am the child + os.execvp(cmd, args) + else: + # I am the parent + (retid, status) = os.wait() + return status + +# Use fork/exec to run the given command with arguments in specified directory +# returns control when the shell command completes +def run_command_in_dir(dir, cmd, *args): + """Given a command and its argument list, use fork/execvp to run the + command. Note that this is a direct wrapper for the C library function, + so the first argument in args should (by convention) be the command name""" + if len(args) == 0: + # execvp does not permit an empty tuple as an argument list + args = ("",) + # Fork off + pid = os.fork() + if pid < 0: + raise RuntimeError("run_command: Failed to fork") + elif pid == 0: + # I am the child + os.chdir(dir) + os.execvp(cmd, args) + else: + # I am the parent + (retid, status) = os.wait() + return status + +# This is what each thread does. +def thread_command(running, cpu, lock, tasks): + """A task entity for each of the running threads. All arguments are + passed by reference (in Python, objects are passed by reference while + literals are passed by value).""" + while True: + lock.acquire_lock() + if len(tasks) > 0: + my_task = tasks.pop() + lock.release_lock() + #print "Running",my_task,"on cpu",cpu + else: + lock.release_lock() + #print "Task queue on cpu",cpu,"is done" + break + # This does not work... + # Need to first change to the directory where the task script is + # and then run the script without the path in it... + #run_command(my_task,my_task) + dir = my_task[0] + script = my_task[1] + #print cpu, dir, script + starttime = time.time() + run_command_in_dir(dir,script,script) + stoptime = time.time() + print "CPU",cpu,"finished task in",dir,"in",(stoptime-starttime),"seconds" + # print "==============================================================================" + lock.acquire_lock() + running[0] -= 1 + lock.release_lock() + + + + +####################################################################### +def get_tasks(list_args): + + param_file='args.in' + script='./srun.x' + tasks = [] + + #os.system('rm -rf task_*') + + #f = open(param_file,'r') + + for it in range(len(list_args)): + + dir = 'task_' + str(it+1) #str(list_args[it]) + if not os.path.exists(dir): + print "Creating directory ", dir + os.mkdir(dir,0755) + + + + fo = open(dir+os.sep+param_file,'w') + #print >>fo," ".join(f.readline().split(' ')) + print >>fo,list_args[it] + fo.close() + + + shutil.copy(os.path.dirname(os.path.realpath(__file__))+os.sep+script,dir) + + + os.popen("chmod +x " + dir + os.sep + script) + tasks.append( [dir,script] ) + +#f.close() + + tasks.reverse() # to convert 'pop()' into 'shift()' + + return tasks; + + + +# Main routine. +def main(args): + + # First argument is a file of tasks (each row is a command line task) + tasks_file=args[0] + # Second argument is number of CPUs requested + ncpus=int(args[1]) + + # Informational print + print "Running tasks in file", tasks_file,"on", ncpus,"CPUs" + + # Turn the rows in the file into a list + list_args=open(tasks_file).read().splitlines() + + # Get the tasks + tasks = get_tasks(list_args) + + # Serial mode + if (ncpus==1): + for it in range(len(list_args)): + dir = 'task_' + str(it+1) + os.chdir(dir) + os.system('./srun.x') + os.chdir('../') + # Parallel mode + else: + running = [0] # only arrays and lists are passed by reference + cpus = avail_cpus(ncpus) # can give optional argument with number of cpus available in the system + lock = thread.allocate_lock() + # Make the same number of threads as there are cpus. + for cpu in cpus: + lock.acquire_lock() + running[0] += 1 + lock.release_lock() + thread.start_new_thread(thread_command, (running, cpu, lock, tasks)) + + # Wait for threads to finish (I don't think there is a wait_threads) + while running[0] > 0: + time.sleep(2) # sleep for 10 seconds before checking if the threads have finished. + # to avoid spending too much cpu time waiting + + # All done. + print "All threads have exited" + + +# Safeguard against import +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/PyUQTk/multirun/srun.x b/PyUQTk/multirun/srun.x new file mode 100755 index 00000000..6f657f8e --- /dev/null +++ b/PyUQTk/multirun/srun.x @@ -0,0 +1,25 @@ +#!/bin/bash +#===================================================================================== + +# This script is run automatically via multirun.py + + +# Get the script name (first entry of args.in) +SCRIPT=`cut -f 1 -d" " args.in` +# Get the output file name to dump the screen-output (second entry of args.in) +OUT=`cut -f 2 -d" " args.in` +# The rest of entries in args.in are parameters of the script +ARGUM=`cut -f 3- -d" " args.in` + +# Informational print +THIS=`basename $PWD` +echo "Running $SCRIPT $ARGUM > $OUT in $THIS" + +##echo $(< args.in) + +# Running the script +cd .. +SCRIPT_ABS=`echo "$(cd "$(dirname "$SCRIPT")"; pwd)/$(basename "$SCRIPT")"` +cd - +ln -sf $SCRIPT_ABS linkToScript +./linkToScript $ARGUM > $OUT diff --git a/PyUQTk/numpy.cmake b/PyUQTk/numpy.cmake new file mode 100644 index 00000000..46f34a65 --- /dev/null +++ b/PyUQTk/numpy.cmake @@ -0,0 +1,27 @@ +IF (NUMPY_INCLUDE_DIR) + SET(NUMPY_FIND_QUIETLY TRUE) +endif (NUMPY_INCLUDE_DIR) + +# To set the variables PYTHON_EXECUTABLE +FIND_PACKAGE(PythonInterp QUIET REQUIRED) +FIND_PACKAGE(PythonLibs QUIET REQUIRED) + +# Look for the include path +# WARNING: The variable PYTHON_EXECUTABLE is defined by the script FindPythonInterp.cmake +EXECUTE_PROCESS(COMMAND "${PYTHON_EXECUTABLE}" -c "import numpy; print (numpy.get_include()); print (numpy.version.version)" + OUTPUT_VARIABLE NUMPY_OUTPUT + ERROR_VARIABLE NUMPY_ERROR) + +IF(NOT NUMPY_ERROR) + STRING(REPLACE "\n" ";" NUMPY_OUTPUT ${NUMPY_OUTPUT}) + LIST(GET NUMPY_OUTPUT 0 NUMPY_INCLUDE_DIR) + LIST(GET NUMPY_OUTPUT 1 NUMPY_VERSION) +ENDIF(NOT NUMPY_ERROR) + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(NumPy DEFAULT_MSG NUMPY_VERSION NUMPY_INCLUDE_DIR) + +MARK_AS_ADVANCED(NUMPY_INCLUDE_DIR) + +INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR}) diff --git a/PyUQTk/numpy/numpy.i b/PyUQTk/numpy/numpy.i new file mode 100644 index 00000000..18162505 --- /dev/null +++ b/PyUQTk/numpy/numpy.i @@ -0,0 +1,3083 @@ +/* -*- C -*- (not really, but good for syntax highlighting) */ +#ifdef SWIGPYTHON + +%{ +#ifndef SWIG_FILE_WITH_INIT +#define NO_IMPORT_ARRAY +#endif +#include "stdio.h" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include +%} + +/**********************************************************************/ + +%fragment("NumPy_Backward_Compatibility", "header") +{ +%#if NPY_API_VERSION < 0x00000007 +%#define NPY_ARRAY_DEFAULT NPY_DEFAULT +%#define NPY_ARRAY_FARRAY NPY_FARRAY +%#define NPY_FORTRANORDER NPY_FORTRAN +%#endif +} + +/**********************************************************************/ + +/* The following code originally appeared in + * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was + * translated from C++ to C by John Hunter. Bill Spotz has modified + * it to fix some minor bugs, upgrade from Numeric to numpy (all + * versions), add some comments and functionality, and convert from + * direct code insertion to SWIG fragments. + */ + +%fragment("NumPy_Macros", "header") +{ +/* Macros to extract array attributes. + */ +%#if NPY_API_VERSION < 0x00000007 +%#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) +%#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) +%#define array_numdims(a) (((PyArrayObject*)a)->nd) +%#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) +%#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) +%#define array_strides(a) (((PyArrayObject*)a)->strides) +%#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) +%#define array_data(a) (((PyArrayObject*)a)->data) +%#define array_descr(a) (((PyArrayObject*)a)->descr) +%#define array_flags(a) (((PyArrayObject*)a)->flags) +%#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f +%#else +%#define is_array(a) ((a) && PyArray_Check(a)) +%#define array_type(a) PyArray_TYPE((PyArrayObject*)a) +%#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) +%#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) +%#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) +%#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) +%#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) +%#define array_data(a) PyArray_DATA((PyArrayObject*)a) +%#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) +%#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) +%#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) +%#endif +%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) +%#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) +%#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) +} + +/**********************************************************************/ + +%fragment("NumPy_Utilities", + "header") +{ + /* Given a PyObject, return a string describing its type. + */ + const char* pytype_string(PyObject* py_obj) + { + if (py_obj == NULL ) return "C NULL value"; + if (py_obj == Py_None ) return "Python None" ; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyString_Check( py_obj)) return "string" ; + if (PyInt_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; +%#if PY_MAJOR_VERSION < 3 + if (PyFile_Check( py_obj)) return "file" ; + if (PyModule_Check( py_obj)) return "module" ; + if (PyInstance_Check(py_obj)) return "instance" ; +%#endif + + return "unkown type"; + } + + /* Given a NumPy typecode, return a string describing the type. + */ + const char* typecode_string(int typecode) + { + static const char* type_names[25] = {"bool", + "byte", + "unsigned byte", + "short", + "unsigned short", + "int", + "unsigned int", + "long", + "unsigned long", + "long long", + "unsigned long long", + "float", + "double", + "long double", + "complex float", + "complex double", + "complex long double", + "object", + "string", + "unicode", + "void", + "ntypes", + "notype", + "char", + "unknown"}; + return typecode < 24 ? type_names[typecode] : type_names[24]; + } + + /* Make sure input has correct numpy type. This now just calls + PyArray_EquivTypenums(). + */ + int type_match(int actual_type, + int desired_type) + { + return PyArray_EquivTypenums(actual_type, desired_type); + } + +%#ifdef SWIGPY_USE_CAPSULE + void free_cap(PyObject * cap) + { + void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); + if (array != NULL) free(array); + } +%#endif + + +} + +/**********************************************************************/ + +%fragment("NumPy_Object_to_Array", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities") +{ + /* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL. + */ + PyArrayObject* obj_to_array_no_conversion(PyObject* input, + int typecode) + { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input), typecode))) + { + ary = (PyArrayObject*) input; + } + else if is_array(input) + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A '%s' was given", + desired_type, + actual_type); + ary = NULL; + } + return ary; + } + + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ + PyArrayObject* make_contiguous(PyArrayObject* ary, + int* is_new_object, + int min_dims, + int max_dims) + { + PyArrayObject* result; + if (array_is_contiguous(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; + } + + /* Given a PyArrayObject, check to see if it is Fortran-contiguous. + * If so, return the input pointer, but do not flag it as not a new + * object. If it is not Fortran-contiguous, create a new + * PyArrayObject using the original data, flag it as a new object + * and return the pointer. + */ + PyArrayObject* make_fortran(PyArrayObject* ary, + int* is_new_object) + { + PyArrayObject* result; + if (array_is_fortran(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + Py_INCREF(array_descr(ary)); + result = (PyArrayObject*) PyArray_FromArray(ary, + array_descr(ary), + NPY_FORTRANORDER); + *is_new_object = 1; + } + return result; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } +} /* end fragment */ + +/**********************************************************************/ + +%fragment("NumPy_Array_Requirements", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros") +{ + /* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!array_is_contiguous(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous. A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Require that a numpy array is not byte-swapped. If the array is + * not byte-swapped, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_native(PyArrayObject* ary) + { + int native = 1; + if (!array_is_native(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must have native byteorder. " + "A byte-swapped array was given"); + native = 0; + } + return native; + } + + /* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ + int require_dimensions(PyArrayObject* ary, + int exact_dimensions) + { + int success = 1; + if (array_numdims(ary) != exact_dimensions) + { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, + array_numdims(ary)); + success = 0; + } + return success; + } + + /* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_dimensions_n(PyArrayObject* ary, + int* exact_dimensions, + int n) + { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) + { + if (array_numdims(ary) == exact_dimensions[i]) + { + success = 1; + } + } + if (!success) + { + for (i = 0; i < n-1; i++) + { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, + array_numdims(ary)); + } + return success; + } + + /* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ + int require_size(PyArrayObject* ary, + npy_intp* size, + int n) + { + int i; + int success = 1; + int len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) + { + if (size[i] != -1 && size[i] != array_size(ary,i)) + { + success = 0; + } + } + if (!success) + { + for (i = 0; i < n; i++) + { + if (size[i] == -1) + { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%ld,", (long int)size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) + { + sprintf(s, "%ld,", (long int)array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, + actual_dims); + } + return success; + } + + /* Require the given PyArrayObject to to be Fortran ordered. If the + * the PyArrayObject is already Fortran ordered, do nothing. Else, + * set the Fortran ordering flag and recompute the strides. + */ + int require_fortran(PyArrayObject* ary) + { + int success = 1; + int nd = array_numdims(ary); + int i; + npy_intp * strides = array_strides(ary); + if (array_is_fortran(ary)) return success; + /* Set the Fortran ordered flag */ + array_enableflags(ary,NPY_ARRAY_FARRAY); + /* Recompute the strides */ + strides[0] = strides[nd-1]; + for (i=1; i < nd; ++i) + strides[i] = strides[i-1] * array_size(ary,i-1); + return success; + } +} + +/* Combine all NumPy fragments into one for convenience */ +%fragment("NumPy_Fragments", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities", + fragment="NumPy_Object_to_Array", + fragment="NumPy_Array_Requirements") +{ +} + +/* End John Hunter translation (with modifications by Bill Spotz) + */ + +/* %numpy_typemaps() macro + * + * This macro defines a family of 74 typemaps that allow C arguments + * of the form + * + * 1. (DATA_TYPE IN_ARRAY1[ANY]) + * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + * + * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + * + * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + * + * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + * + * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) + * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + * + * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + * + * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + * + * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + * + * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + * + * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + * + * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + * + * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + * + * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + * + * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + * + * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + * + * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) + * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) + * + * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + * + * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + * + * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) + * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) + * + * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) + * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) + * + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * The difference between "ARRAY" typemaps and "FARRAY" typemaps is + * that the "FARRAY" typemaps expect Fortran ordering of + * multidimensional arrays. In python, the dimensions will not need + * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" + * typemaps). The IN_ARRAYs can be a numpy array or any sequence that + * can be converted to a numpy array of the specified type. The + * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The + * ARGOUT_ARRAYs will be returned as new numpy arrays of the + * appropriate type. + * + * These typemaps can be applied to existing functions using the + * %apply directive. For example: + * + * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; + * double prod(double* series, int length); + * + * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) + * {(int rows, int cols, double* matrix )}; + * void floor(int rows, int cols, double* matrix, double f); + * + * %apply (double IN_ARRAY3[ANY][ANY][ANY]) + * {(double tensor[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double low[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double upp[2][2][2] )}; + * void luSplit(double tensor[2][2][2], + * double low[2][2][2], + * double upp[2][2][2] ); + * + * or directly with + * + * double prod(double* IN_ARRAY1, int DIM1); + * + * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); + * + * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY]); + */ + +%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) + +/************************/ +/* Input Array Typemaps */ +/************************/ + +/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY1[ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY1[ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY1[ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = {-1}; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/***************************/ +/* In-Place Array Typemaps */ +/***************************/ + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY1[ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY1[ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + (PyArrayObject* array=NULL, int i=0) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = 1; + for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); + $2 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 2) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 3) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* INPLACE_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/*************************/ +/* Argout Array Typemaps */ +/*************************/ + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY1[ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[1] = { $1_dim0 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY1[ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $2; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyInt_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyInt_AsLong($input); + dims[0] = (npy_intp) $1; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[2] = { $1_dim0, $1_dim1 }; + array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; + array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/*****************************/ +/* Argoutview Array Typemaps */ +/*****************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/*************************************/ +/* Managed Argoutview Array Typemaps */ +/*************************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +%#ifdef SWIGPY_USE_CAPSULE + PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); +%#else + PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); +%#endif + +%#if NPY_API_VERSION < 0x00000007 + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +%enddef /* %numpy_typemaps() macro */ +/* *************************************************************** */ + +/* Concrete instances of the %numpy_typemaps() macro: Each invocation + * below applies all of the typemaps above to the specified data type. + */ +%numpy_typemaps(signed char , NPY_BYTE , int) +%numpy_typemaps(unsigned char , NPY_UBYTE , int) +%numpy_typemaps(short , NPY_SHORT , int) +%numpy_typemaps(unsigned short , NPY_USHORT , int) +%numpy_typemaps(int , NPY_INT , int) +%numpy_typemaps(unsigned int , NPY_UINT , int) +%numpy_typemaps(long , NPY_LONG , int) +%numpy_typemaps(unsigned long , NPY_ULONG , int) +%numpy_typemaps(long long , NPY_LONGLONG , int) +%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) +%numpy_typemaps(float , NPY_FLOAT , int) +%numpy_typemaps(double , NPY_DOUBLE , int) + +/* *************************************************************** + * The follow macro expansion does not work, because C++ bool is 4 + * bytes and NPY_BOOL is 1 byte + * + * %numpy_typemaps(bool, NPY_BOOL, int) + */ + +/* *************************************************************** + * On my Mac, I get the following warning for this macro expansion: + * 'swig/python detected a memory leak of type 'long double *', no destructor found.' + * + * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) + */ + +%#ifdef __cplusplus + +%include + +%numpy_typemaps(std::complex, NPY_CFLOAT , int) +%numpy_typemaps(std::complex, NPY_CDOUBLE, int) + +%#endif + +#endif /* SWIGPYTHON */ diff --git a/PyUQTk/pce/CMakeLists.txt b/PyUQTk/pce/CMakeLists.txt new file mode 100644 index 00000000..3722c39c --- /dev/null +++ b/PyUQTk/pce/CMakeLists.txt @@ -0,0 +1,67 @@ +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}/../../Extras/lib/python/numpy/core/include) + +#include source files +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/) # array classes, array input output, and array tools +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/include/) # utilities like error handlers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/) # tools like multindex, etc. +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/) # quad class +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/kle/) # kle class +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/) # PCSet and PCBasis classes + +# include dependencies +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lapack/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/blas/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/dsfmt/) # dsfmt +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/figtree/) # figtree +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/slatec/) # slatec headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/cvode-2.7.0/include) # cvode +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/dep/cvode-2.7.0/include) +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/dep/cvode-2.7.0/include/nvector) + +# INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../numpy/) # numpy headers + +SET(CMAKE_SWIG_FLAGS "") +SET_SOURCE_FILES_PROPERTIES(pce.i PROPERTIES CPLUSPLUS ON) + +# compile swig with cpp extensions +SWIG_ADD_MODULE( + pce python pce.i + # array tools needed to compile misc tools source files + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arrayio.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arraytools.cpp + + # source code for quad and kle class + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/quad.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/kle/kle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/PCBasis.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/pce/PCSet.cpp + + # source code for tools + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/combin.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/gq.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/minmax.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/multiindex.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/pcmaps.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/probability.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/rosenblatt.cpp +) + +# link python and 3rd party libraries, e.g., gfortran and blas +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + SWIG_LINK_LIBRARIES(pce uqtkquad uqtkarray uqtktools depnvec depslatec deplapack depblas depdsfmt depfigtree depann depcvode gfortran ${PYTHON_LIBRARIES}) + #SWIG_LINK_LIBRARIES(pce uqtkquad uqtkarray depnvec depslatec uqtktools deplapack depblas depdsfmt depann depfigtree depcvode gfortran ${PYTHON_LIBRARIES}) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + SWIG_LINK_LIBRARIES(pce uqtktools uqtkquad uqtkarray depnvec deplapack depblas depslatec depdsfmt depann depfigtree depcvode ifcore ${PYTHON_LIBRARIES}) +endif() + +INSTALL(TARGETS _pce DESTINATION PyUQTk/) +INSTALL(FILES ${CMAKE_BINARY_DIR}/${outdir}PyUQTk/pce/pce.py DESTINATION PyUQTk) diff --git a/PyUQTk/pce/pce.i b/PyUQTk/pce/pce.i new file mode 100644 index 00000000..b576de84 --- /dev/null +++ b/PyUQTk/pce/pce.i @@ -0,0 +1,136 @@ +%module(directors="1") pce +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== + +%{ +#define SWIG_FILE_WITH_INIT +#include +#include +#include +#include +#include +// #include "../../cpp/lib/array/Array1D.h" +// #include "../../cpp/lib/array/Array2D.h" +// #include "../../cpp/lib/array/arrayio.h" +// #include "../../cpp/lib/array/arraytools.h" +// #include "../../cpp/lib/tools/combin.h" +// #include "../../cpp/lib/tools/gq.h" +// #include "../../cpp/lib/tools/minmax.h" +// #include "../../cpp/lib/tools/multiindex.h" +// #include "../../cpp/lib/tools/pcmaps.h" +// #include "../../cpp/lib/tools/probability.h" +// #include "../../cpp/lib/tools/rosenblatt.h" + +// #include "../../cpp/lib/quad/quad.h" +// #include "../../cpp/lib/kle/kle.h" +#include "../../cpp/lib/pce/PCBasis.h" +#include "../../cpp/lib/pce/PCSet.h" + +%} + +/************************************************************* +// Standard SWIG Templates +*************************************************************/ + +// Include standard SWIG templates +// Numpy array templates and wrapping +%include "pyabc.i" +%include "../numpy/numpy.i" +%include "std_vector.i" +%include "std_string.i" +%include "cpointer.i" + +%init %{ + import_array(); +%} + +%pointer_functions(double, doublep); + +/************************************************************* +// Numpy SWIG Interface files +*************************************************************/ + +// // Basic typemap for an Arrays and its length. +// // Must come before %include statement below + +// // For Array1D setnumpyarray4py function +// %apply (long* IN_ARRAY1, int DIM1) {(long* inarray, int n)} +// %apply (double* IN_ARRAY1, int DIM1) {(double* inarray, int n)} +// // get numpy int and double array +// %apply (long* INPLACE_ARRAY1, int DIM1) {(long* outarray, int n)} +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* outarray, int n)} + +// // For Array2D numpysetarray4py function +// %apply (double* IN_FARRAY2, int DIM1, int DIM2) {(double* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (double* INPLACE_FARRAY2, int DIM1, int DIM2) {(double* outarray, int n1, int n2)} +// // For Array2D numpysetarray4py function +// %apply (long* IN_FARRAY2, int DIM1, int DIM2) {(long* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (long* INPLACE_FARRAY2, int DIM1, int DIM2) {(long* outarray, int n1, int n2)} + + +// // For mcmc test to get log probabilities +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* l, int n)} + +/************************************************************* +// Include header files +*************************************************************/ + +// // The above typemap is applied to header files below +// %include "../../cpp/lib/array/Array1D.h" +// %include "../../cpp/lib/array/Array2D.h" +// %include "../../cpp/lib/array/arrayio.h" +// %include "../../cpp/lib/array/arraytools.h" +// %include "../../cpp/lib/tools/combin.h" +// %include "../../cpp/lib/tools/gq.h" +// %include "../../cpp/lib/tools/minmax.h" +// %include "../../cpp/lib/tools/multiindex.h" +// %include "../../cpp/lib/tools/pcmaps.h" +// %include "../../cpp/lib/tools/probability.h" +// %include "../../cpp/lib/tools/rosenblatt.h" + +// %include "../../cpp/lib/quad/quad.h" +// %include "../../cpp/lib/kle/kle.h" +%include "../../cpp/lib/pce/PCBasis.h" +%include "../../cpp/lib/pce/PCSet.h" + +// Typemaps for standard vector +// Needed to prevent to memory leak due to lack of destructor +// must use namespace std +// namespace std{ +// %template(dblVector) vector; +// %template(intVector) vector; +// %template(strVector) vector; + +// } + + +// %include "swigi/arrayext.i" + + + diff --git a/PyUQTk/plotting/CMakeLists.txt b/PyUQTk/plotting/CMakeLists.txt new file mode 100644 index 00000000..6c97882a --- /dev/null +++ b/PyUQTk/plotting/CMakeLists.txt @@ -0,0 +1,11 @@ +project (UQTk) + +SET(copy_FILES + __init__.py + surrogate.py + inout.py + ) + +INSTALL(FILES ${copy_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION PyUQTk/plotting) diff --git a/PyUQTk/plotting/__init__.py b/PyUQTk/plotting/__init__.py new file mode 100755 index 00000000..ed35c1cd --- /dev/null +++ b/PyUQTk/plotting/__init__.py @@ -0,0 +1,28 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import surrogate +import inout diff --git a/PyUQTk/plotting/inout.py b/PyUQTk/plotting/inout.py new file mode 100644 index 00000000..0b7823c5 --- /dev/null +++ b/PyUQTk/plotting/inout.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import os +import shutil +import sys + +try: + import numpy as np +except ImportError: + print "Numpy was not found. " + +try: + import matplotlib +except ImportError: + print "Matplotlib was not found. " + +try: + from scipy import stats, mgrid, reshape, random +except ImportError: + print "Scipy was not found. " + +import math +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +from pylab import * + +sys.path.append(os.environ['UQTK_INS']) +import PyUQTk.utils.colors as ut + +rc('legend',loc='upper left', fontsize=12) +rc('lines', linewidth=1, color='r') +rc('axes',linewidth=3,grid=True,labelsize=22) +rc('xtick',labelsize=20) +rc('ytick',labelsize=20) + +############################################################# +def parallel_coordinates(parnames, values, labels, savefig=[]): + """ + Plots parallel coordinates. + Arguments: + * parnames : list of d parameter names + * values : (d,N) array of N data points with d parameters + * labels : list of N labels/categories, one per point + * savefig : figure name to save. If [], then show the plot + """ + + # Start the figure + fig=figure(figsize=(14,7)) + fig.add_axes([0.1,0.15,0.8,0.8]) + ax = gca() + + # Categorize + ulabels = np.unique(labels) + n_labels = len(ulabels) + + # Set colors + cmap = plt.get_cmap('prism') + colors = cmap(np.arange(n_labels)*cmap.N/(n_labels+1)) + + # Plot + class_id = np.searchsorted(ulabels, labels) + lines = plt.plot(values[:,:], 'ko-',ms=6,linewidth=0.7) + [ l.set_color(colors[c]) for c,l in zip(class_id, lines) ] + + # Gridification + ax.spines['top'].set_visible(False) + ax.spines['bottom'].set_position(('outward', 5)) + ax.spines['bottom'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.spines['left'].set_visible(False) + ax.yaxis.set_ticks_position('both') + ax.xaxis.set_ticks_position('none') + + plt.xticks(np.arange(len(parnames)), parnames) + plt.grid(axis='x', ls='-') + + leg_handlers = [ lines[np.where(class_id==id)[0][0]] + for id in range(n_labels)] + ax.legend(leg_handlers, ulabels, frameon=False, loc='upper left', + ncol=len(labels), + bbox_to_anchor=(0, -0.03, 1, 0)) + + # Show or save + if (savefig==[]): + plt.show() + else: + plt.savefig(savefig) + plt.clf() + + +############################################################# + +def plot_xx(d1,d2,parnames, values, labels, savefig=[]): #(x1,x2,inputs,labels,pnames,outfigdir='.'): + """ + Plots one-dimension versus another with various labels. + Arguments: + * d1 : first dimension to plot + * d2 : second dimension to plot + * parnames : list of d parameter names + * values : (d,N) array of N data points with d parameters + * labels : list of N labels/categories, one per point + * savefig : figure name to save. If [], then show the plot + """ + + # Start the figure + fig=figure(figsize=(12,12)) + fig.add_axes([0.1,0.15,0.8,0.8]) + ax = gca() + + # Categorize + ulabels = np.unique(labels) + n_labels = len(ulabels) + + # Set colors + cmap = plt.get_cmap('prism') + colors = cmap(np.arange(n_labels)*cmap.N/(n_labels+1)) + + # Plot + class_id = np.searchsorted(ulabels, labels) + for id in range(n_labels): + plt.plot(values[class_id==id,d1],values[class_id==id,d2], 'o',color=colors[id],ms=7,label=ulabels[id]) + + + + ax.legend(frameon=False, loc='upper left', + ncol=len(labels), + bbox_to_anchor=(0, -0.06, 1, 0)) + + ax.set_xlabel(parnames[d1]) + ax.set_ylabel(parnames[d2]) + + # Show or save + if (savefig==[]): + plt.show() + else: + plt.savefig(savefig) + + return fig + +############################################################# + +def plot_xy(x,y,pname, outname, label='', savefig=[]): + """ + Plots one array versus another. + Arguments: + * x : array for x-axis + * y : array for y-axis + * pname : xlabel + * outname : ylabel + * label : legend + * savefig : figure name to save. If [], then show the plot + """ + + # Start the figure + fig=figure(figsize=(12,8)) + ax = gca() + + # Plot + plt.plot(x,y,'o',label=label) + + # Set labels + ax.set_xlabel(pname) + ax.set_ylabel(outname) + + # Show or save + if (savefig==[]): + plt.show() + else: + plt.savefig(savefig) + #plt.clf() + + + return fig + +############################################################# + +def plot_xxy(x1,x2,y,pnames, outname, label='', savefig=[]): + """ + Plots one array versus another. + Arguments: + * x1 : array for x1-axis + * x2 : array for x2-axis + * y : array for y-axis + * pnames : list of xlabels + * outname : ylabel (vertical axis) + * label : legend + * savefig : figure name to save. If [], then show the plot + """ + + # Start the figure + fig=figure(figsize=(12,8)) + ax = fig.add_subplot(111, projection='3d') + ax.scatter(x1,x2,y,c='k',label=label) + + # Set labels + ax.set_xlabel(pnames[0]) + ax.set_ylabel(pnames[1]) + ax.set_zlabel(outname) + + # Show or save + if (savefig==[]): + plt.show() + else: + plt.savefig(savefig) + #plt.clf() + + + return fig + + + + + + diff --git a/PyUQTk/plotting/surrogate.py b/PyUQTk/plotting/surrogate.py new file mode 100644 index 00000000..694a9969 --- /dev/null +++ b/PyUQTk/plotting/surrogate.py @@ -0,0 +1,673 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import os +import shutil +import sys + +try: + import numpy as np +except ImportError: + print "Numpy was not found. " + +try: + import matplotlib +except ImportError: + print "Matplotlib was not found. " + +try: + from scipy import stats, mgrid, reshape, random +except ImportError: + print "Scipy was not found. " +import math +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.patches import Circle, Wedge, Polygon +from itertools import combinations + +from pylab import * + +sys.path.append(os.environ['UQTK_SRC']) +import PyUQTk.utils.colors as ut + +uqtkbin=os.environ['UQTK_INS']+"/bin/" + + +rc('legend',loc='upper left', fontsize=12) +rc('lines', linewidth=1, color='r') +rc('axes',linewidth=3,grid=True,labelsize=22) +rc('xtick',labelsize=20) +rc('ytick',labelsize=20) + +############################################################# +def saveplot(figname): + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + savefig(figname) + gcf().clf() + +############################################################# +def plot_pcpdf(pctype,mindex,cfs,nsam,custom_xlabel,figname='pcdens.eps',showplot=False): + + np.savetxt('mi',mindex,fmt='%d') + np.savetxt('cfs',cfs) + dim=mindex.shape[1] + cmd=uqtkbin+"pce_rv -w'PCmi' -n"+str(nsam)+" -p"+str(dim)+" -f'cfs' -m'mi' -x"+pctype+" > pcrv.log" + os.system(cmd) + + cmd=uqtkbin+"pdf_cl -i rvar.dat -g 1000 > pdfcl.log" + os.system(cmd) + xtarget=np.loadtxt('dens.dat')[:,:-1] + dens=np.loadtxt('dens.dat')[:,-1:] + + + #rv=np.loadtxt('rvar.dat') + #xtarget=np.linspace(rv.min(),rv.max(),100) + #kernlin=stats.kde.gaussian_kde(rv) + #dens=kernlin.evaluate(xtarget) + + np.savetxt('pcdens.dat',np.vstack((xtarget,dens)).T) + + figure(figsize=(12,8)) + plot(xtarget,dens) + xlabel(custom_xlabel) + ylabel('PDF') + + saveplot(figname) + if showplot: + show() + + #cleanup + os.system('rm mi cfs rvar.dat') + +############################################################# + +def plot_mindex(mindex,varfrac,varname,figname='mindex.eps',showplot=False): + + custom_xlabel='Param i' + custom_ylabel='Param j' + + npc=mindex.shape[0] + ndim=mindex.shape[1] + plt.figure(figsize=(14,10)) + ij=[] + acfs=[] + k=0 + for basis in mindex: + nzeros=np.nonzero(basis)[0] + if nzeros.shape[0]==0: + ij.append((0,0)) + acfs.append(varfrac[k]) + elif nzeros.shape[0]==1: + ijcur=(0,nzeros[0]+1) + if ijcur in ij: + acfs[ij.index(ijcur)]+=varfrac[k] + else: + ij.append(ijcur) + acfs.append(varfrac[k]) + elif nzeros.shape[0]==2: + ijcur=(nzeros[0]+1,nzeros[1]+1) + if ijcur in ij: + acfs[ij.index(ijcur)]+=varfrac[k] + else: + ij.append(ijcur) + acfs.append(varfrac[k]) + else: + #print "More than a couple detected!", nzeros+1 + for cc in combinations(nzeros, 2): + ijcur=(cc[0]+1,cc[1]+1) #[ic+1 for ic in cc] + #print "adding to ",ijcur + if ijcur in ij: + acfs[ij.index(ijcur)]+=varfrac[k] + else: + ij.append(ijcur) + acfs.append(varfrac[k]) + k+=1 + ija=np.array(ij) + #print "ija",ija,acfs + + pad=0.1 + plt.fill_between(range(ndim+2),-pad,range(ndim+2),color='lightgrey') + plt.plot([-pad,ndim+pad],[-pad,ndim+pad],'k-',lw=1) + if varfrac==[]: + #plot(mindex[:,0],mindex[:,1],'bo',markersize=13) + plt.scatter(ija[:,0],ija[:,1],s=320, marker = 'o',cmap = cm.jet ) + else: + #print cfs + plt.scatter(ija[:,0],ija[:,1],s=320, c=acfs, marker = 'o',vmin=0.0,vmax=max(acfs)) + + #cp=get_cp() + #cs=plt.gva().pcolor(abs(cfs),cmap=cp); + plt.colorbar(pad=0.05,shrink=0.9) + plt.gca().set_aspect('equal') + #cbar=plt.colorbar(ticks=[0.,0.6,1.0]) + #cbar.ax.set_ylim([0.0,1.0]) + #cbar.set_ticklabels(['0.0', '0.6','1.0']) + #plt.tight_layout() + + + #plt.gca().xaxis.set_label_position('top') + #plt.gca().xaxis.tick_top() + plt.gca().set_xticks(range(ndim+1), minor=False) + plt.gca().set_yticks(range(ndim+1), minor=False) + plt.gca().xaxis.grid(True, which='major') + plt.gca().yaxis.grid(True, which='major') + + plt.xlabel(custom_xlabel) + plt.ylabel(custom_ylabel) + plt.xlim([-pad, ndim+pad]) + plt.ylim([ndim+pad,-pad]) + + plt.gca().spines["top"].set_visible(False) + plt.gca().spines["right"].set_visible(False) + + plt.text(int(ndim/2),int(ndim/3),varname,fontsize=37) + + + saveplot(figname) + if showplot: + show() + + +def plot_micf(mindex,cfs=[],figname='micf.eps',showplot=False): + """Plots 2d or 3d multiindices""" + + custom_xlabel='Dim 1' + custom_ylabel='Dim 2' + custom_zlabel='Dim 3' + + npc=mindex.shape[0] + ndim=mindex.shape[1] + + if (ndim==2): + if cfs==[]: + #plot(mindex[:,0],mindex[:,1],'bo',markersize=13) + scatter(mindex[:,0],mindex[:,1],s=150, marker = 'o',cmap = cm.jet ) + else: + scatter(mindex[:,0],mindex[:,1],s=150, c=cfs, marker = 'o',cmap = cm.jet ) + elif (ndim==3): + ax = figure().add_subplot(111, projection='3d') + if cfs==[]: + ax.scatter(mindex[:,0],mindex[:,1],mindex[:,2],s=50) + else: + ax.scatter(mindex[:,0],mindex[:,1],mindex[:,2],c=cfs,s=50) + + ax.set_zlabel(custom_zlabel) + ax.set_zlim([-.5, max(mindex[:,2])+.5]) + + else: + raise NameError("Multi-index should be 2d or 3d") + + xlabel(custom_xlabel) + ylabel(custom_ylabel) + xlim([-.5, max(mindex[:,0])+.5]) + ylim([-.5, max(mindex[:,1])+.5]) + + saveplot(figname) + if showplot: + show() + + + +############################################################# +def plot_idm(data,model,errbar,sort='none',figname='idm.eps',showplot=False): + """Plots data and model on the same axis""" + erb=True + + axes_labels=['Run Id','Model / Surrogate'] + + custom_xlabel=axes_labels[0] + custom_ylabel=axes_labels[1] + + figure(figsize=(12,8)) + + npts=data.shape[0] + neach=1 + if (data.ndim>1): + neach=data.shape[1] + + erbl,erbh=errbar + + if (sort=='model'): + ind=argsort(model) + elif (sort=='data'): + ind=argsort(data) + elif (sort=='none'): + ind=range(npts) + + + ddata=data.reshape(npts,neach) + + if (erb): + errorbar(range(1,npts+1),model[ind],yerr=[erbl,erbh],fmt='o', markersize=2,ecolor='grey') + + if (sort!='model'): + plot(range(1,npts+1),model[ind], 'bo', label='Surrogate') + for j in range(neach): + plot(range(1,npts+1),ddata[ind,j], 'ro',label='Model') + if (sort=='model'): + plot(range(1,npts+1),model[ind], 'bo', label='Surrogate') + + xlabel(custom_xlabel) + ylabel(custom_ylabel) + #title('Data vs Model') + legend() + + + saveplot(figname) + if showplot: + show() + +############################################################# +def plot_dm(datas,models,errorbars=[],labels=[],axes_labels=['Model','Apprx'],figname='dm.eps',showplot=False): + """Plots data-vs-model and overlays y=x""" + if errorbars==[]: + erb=False + else: + erb=True + + + custom_xlabel=axes_labels[0] + custom_ylabel=axes_labels[1] + + figure(figsize=(10,10)) + + ncase=len(datas) + if labels==[]: + labels=['']*ncase + + + # Create colors list + colors=ut.set_colors(ncase) + yy=np.empty((0,1)) + for i in range(ncase): + data=datas[i] + model=models[i] + if erb: + erbl,erbh=errorbars[i] + npts=data.shape[0] + neach=1 + if (data.ndim>1): + neach=data.shape[1] + + #neb=model.shape[1]-1# errbars not implemented yet + + + + ddata=data.reshape(npts,neach) + + + for j in range(neach): + yy=np.append(yy,ddata[:,j]) + if (erb): + errorbar(ddata[:,j],model,yerr=[erbl,erbh],fmt='o', markersize=2,ecolor='grey') + plot(ddata[:,j],model, 'o',color=colors[i],label=labels[i]) + + delt=0.1*(yy.max()-yy.min()) + minmax=[yy.min()-delt, yy.max()+delt] + plot(minmax,minmax,'k--',linewidth=1.5,label='y=x') + + xlabel(custom_xlabel) + ylabel(custom_ylabel) + #title('Data vs Model') + legend() + + #xscale('log') + #yscale('log') + + #gca().set_aspect('equal', adjustable='box') + plt.axis('scaled') + # Trying to make sure both axis have the same number of ticks + gca().xaxis.set_major_locator(MaxNLocator(7)) + gca().yaxis.set_major_locator(MaxNLocator(7)) + if showplot: + show() + + saveplot(figname) + + +############################################################# + +def plot_sens(sensdata,pars,cases,vis="bar",reverse=False,par_labels=[],case_labels=[],colors=[],ncol=4,grid_show=True,xlbl='',legend_show=2,xdatatick=None,figname='sens.eps',showplot=False): + """Plots sensitivity for multiple observables""" + + ncases=sensdata.shape[0] + npar=sensdata.shape[1] + + wd=0.6 + ylbl='Sensitivity' + + + assert set(pars) <= set(range(npar)) + assert set(cases) <= set(range(ncases)) + + # Set up the figure + # TODO need to scale figure size according to the expected amount of legends + xticklabel_size=25 + if ncases>20: + xticklabel_size=1000/ncases + fig = plt.figure(figsize=(20,12)) + #fig = plt.figure(figsize=(18,12)) + fig.add_axes([0.1,0.3,0.8,0.65]) + ######### + + # Default parameter names + if (par_labels==[]): + for i in range(npar): + par_labels.append(('par_'+str(i+1))) + # Default case names + if (case_labels==[]): + for i in range(ncases): + case_labels.append(('case_'+str(i+1))) + + + if(reverse): + tmp=par_labels + par_labels=case_labels + case_labels=tmp + tmp=pars + pars=cases + cases=tmp + sensdata=sensdata.transpose() + ############################################################################## + + npar_=len(pars) + ncases_=len(cases) + + # Create colors list + if colors==[]: + colors=ut.set_colors(npar_) + + + case_labels_=[] + for i in range(ncases_): + case_labels_.append(case_labels[cases[i]]) + + if xdatatick==None: + xflag=False + xdatatick=np.array(range(1,ncases_+1)) + sc=1. + else: + xflag=True + sc=(xdatatick[-1]-xdatatick[0])/ncases_ + + if (vis=="graph"): + for i in range(npar_): + plot(xdatatick_,sensdata[cases,i], '-o',color=colors[pars[i]], label=par_labels[pars[i]]) + elif (vis=="bar"): + curr=np.zeros((ncases_)) + #print pars,colors + for i in range(npar_): + bar(xdatatick,sensdata[cases,i], width=wd*sc,color=colors[pars[i]], bottom=curr, label=par_labels[pars[i]]) + curr=sensdata[cases,i]+curr + if not xflag: + if ncases>20: + xticks(np.array(range(1,ncases_+1))+wd/2.,case_labels_,rotation='vertical') + else: + xticks(np.array(range(1,ncases_+1))+wd/2.,case_labels_) + xlim(xdatatick[0]-wd*sc/2.,xdatatick[-1]+wd*sc/2.) + + #else: + # xticks(xdatatick) + + ylabel(ylbl) + xlabel(xlbl) + + + + maxsens=max(max(curr),1.0) + ylim([0,maxsens]) + if legend_show==1: + legend() + elif (legend_show==2): + legend(bbox_to_anchor=(1.0, -0.05),fancybox=True, shadow=True,ncol=ncol,labelspacing=-0.1) + #legend(bbox_to_anchor=(0.0, -0.05),fancybox=True, shadow=True,ncol=5,labelspacing=-0.1) + + if not xflag: + zed = [tick.label.set_fontsize(xticklabel_size) for tick in gca().xaxis.get_major_ticks()] + + grid(grid_show) + + saveplot(figname) + if showplot: + show() + +################################################################################################## + + +def plot_senscirc(varname, msens,jsens,inpar_names,figname='senscirc.eps',showplot=False): + + Nmain=min(len(np.nonzero(msens)[0]),6) + Nsec=Nmain-1 + lwMax=10 + lwCut=0.2 + radMain=50 + radOut=15 + lext=0.4 + verbose=1 + + nx,ny=jsens.shape + + + #jsens=np.log10(jsens); + #print msens + ind=msens.argsort()[::-1]; + msensShort=msens[ind[0:Nmain]] + if verbose > 0: + for i in range(Nmain): + print "Variable ",ind[i],", main sensitivity ",msens[ind[i]] + fig = plt.figure(figsize=(10,8)) + ax=fig.add_axes([0.05, 0.05, 0.9, 0.9],aspect='equal') + #circ=pylab.Circle((0,0),radius=0.5,color='r') + circ=Wedge((0.0,0.0),1.01, 0, 360, width=0.02,color='r') + ax.add_patch(circ) + maxJfr=-1.e10; + for i in range(Nmain): + jfr_i=np.array(np.zeros(nx)) + iord=ind[i] + for j in range(iord): + jfr_i[j]=jsens[j,iord] + for j in range(iord+1,nx): + jfr_i[j]=jsens[iord,j] + ind_j=jfr_i.argsort()[::-1]; + if jfr_i[ind_j[0]] > maxJfr: maxJfr = jfr_i[ind_j[0]]; + if verbose > 1: + for j in range(Nsec): + print iord," ",ind_j[j],jfr_i[ind_j[j]] + if verbose > 1: + print "Maximum joint sensitivity :",maxJfr + gopar=[] + for i in range(Nmain): + jfr_i=np.array(np.zeros(nx)) + iord=ind[i] + for j in range(iord): + jfr_i[j]=jsens[j,iord] + for j in range(iord+1,nx): + jfr_i[j]=jsens[iord,j] + ind_j=jfr_i.argsort()[::-1]; + elst=[] + for j in range(Nsec): + if maxJfr>1.e-16 and jfr_i[ind_j[j]]/maxJfr >= lwCut: + posj=[k for k,x in enumerate(ind[:Nmain]) if x == ind_j[j]] + if verbose > 2: + print j," ",posj + if len(posj) > 0 : + x1=np.cos(0.5*np.pi+(2.0*np.pi*posj[0])/Nmain) + x2=np.cos(0.5*np.pi+(2.0*np.pi*i )/Nmain) + y1=np.sin(0.5*np.pi+(2.0*np.pi*posj[0])/Nmain) + y2=np.sin(0.5*np.pi+(2.0*np.pi*i )/Nmain) + lw=lwMax*jfr_i[ind_j[j]]/maxJfr + plt.plot([x1,x2],[y1,y2],'g-',linewidth=lw) + if ( verbose > 2 ): + print iord," ",ind[posj[0]] + else: + elst.append(j) + if len(elst) > 0: + asft=[0,-1,1] + for k in range(min(len(elst),3)): + ang=0.5*np.pi+(2.0*np.pi*i)/Nmain+2*np.pi/12*asft[k] + x2=np.cos(0.5*np.pi+(2.0*np.pi*i)/Nmain) + y2=np.sin(0.5*np.pi+(2.0*np.pi*i)/Nmain) + x1=x2+lext*np.cos(ang) + y1=y2+lext*np.sin(ang) + lw=lwMax*jfr_i[ind_j[elst[k]]]/maxJfr + plt.plot([x1,x2],[y1,y2],'g-',linewidth=lw) + plt.plot([x1],[y1],"wo",markersize=radOut,markeredgecolor='k', + markeredgewidth=2) + if ( ind_j[elst[k]] > 32 ): + ltext=str(ind_j[elst[k]]+3) + elif ( ind_j[elst[k]] > 30 ): + ltext=str(ind_j[elst[k]]+2) + else: + ltext=str(ind_j[elst[k]]+1) + plt.text(x1+(0.15)*np.cos(ang),y1+(0.15)*np.sin(ang),ltext, + ha='center',va='center',fontsize=16) + posj=[k1 for k1,x in enumerate(gopar) if x == ind_j[elst[k]]] + if len(posj)==0: + gopar.append(ind_j[elst[k]]) + if ( verbose > 2 ): + print "------------------------" + for i in range(Nmain): + angl=0.5*np.pi+(2.0*np.pi*i)/Nmain + xc=np.cos(angl); + yc=np.sin(angl); + msize=radMain*msens[ind[i]]/msens[ind[0]] + plt.plot([xc],[yc],"bo",markersize=msize,markeredgecolor='k',markeredgewidth=2) + da=1.0 + lab=0.2 + llab=lab*msens[ind[i]]/msens[ind[0]] + + ltext=str(ind[i]+1) + lleg=ltext+" - "+inpar_names[ind[i]] + plt.text(xc+(0.08+llab)*np.cos(angl+da),yc+(0.08+llab)*np.sin(angl+da),ltext, + ha='center',va='center',fontsize=16) + plt.text(1.6,1.2-0.15*i,lleg,fontsize=16) + for k in range(len(gopar)): + lleg=str(gopar[k]+1)+" - "+inpar_names[gopar[k]] + plt.text(1.6,1.2-0.15*Nmain-0.15*k,lleg,fontsize=16) + + plt.text(0.9,-1.2,varname,fontsize=27) + + ax.set_xlim([-1-1.6*lext,1.8+1.6*lext]) + ax.set_ylim([-1-1.6*lext,1+1.6*lext]) + ax.set_xticks([]) + ax.set_yticks([]) + + saveplot(figname) + if showplot: + show() + + +################################################################################################## + + +def plot_sensmat(sensdata,pars,cases,vis="bar",reverse=False,par_labels=[],case_labels=[],figname='sensmat.eps',showplot=False): + + cdict = cm.jet._segmentdata.copy() + cdict['red']=tuple([tuple([0.0, 1, 1 ]), + tuple([0.01, 0, 0 ]), + tuple([0.35, 0, 0 ]), + tuple([0.66, 1, 1 ]), + tuple([0.89, 1, 1 ]), + tuple([1, 0.5, 0.5]) + ] + ) + cdict['green']=tuple([tuple([0.0, 1, 1]), + tuple([0.01, 0, 0]), + tuple([0.125, 0, 0]), + tuple([0.375, 1, 1]), + tuple([0.64, 1, 1]), + tuple([0.91, 0, 0]), + tuple([1, 0, 0]) + ] + ) + cdict['blue']=tuple([tuple([0, 1.0,1.0]), + tuple([0.01, 0.5,0.5]), + tuple([0.11, 1, 1 ]), + tuple([0.34, 1, 1 ]), + tuple([0.65, 0, 0 ]), + tuple([1, 0, 0 ]) + ] + ) + + cp=matplotlib.colors.LinearSegmentedColormap('colormap',cdict,64) + + # Read varfrac files and retain indices of important params + vlst=[] + allSens=[] + for nm in range(len(cases)): + #vfr=np.array(column(readfile("varfrac."+nm+".dat")[0],0)) + vfr=sensdata[nm,:] #np.array(column(readfile(nm+".vf.dat")[0],0)) + allSens.append(vfr) + vlst.append([ n for n,i in enumerate(vfr) if i>0.1 ]) + # Get union + allV=[] + for i in range(len(vlst)): + allV=list(set(allV) | set(vlst[i])) + allV=np.sort(allV) + # Create matrix, populate, and rescale + nobs=len(cases); + npar=len(allV); + print "Number of observables plotted = ", nobs + print "Number of parameters plotted = ", npar + jsens=np.array(np.zeros([nobs,npar])); + for i in range(nobs): + for j in range(npar): + jsens[i,j]=allSens[i][allV[j]]; + #for i in range(nobs): + # jsens[i]=jsens[i]/jsens[i].max(); + jsens[np.where(jsens==0)]=0.5*jsens[np.where(jsens>0)].min(); + #for i in range(nobs): + # for j in range(npar): + # jsens[i,j]=np.log10(jsens[i,j]); + + par_labels_sorted=[]; + for i in allV: + par_labels_sorted.append(par_labels[i]); + # make fig + fs1=13; + fig = plt.figure(figsize=(10,3.9)); + ax=fig.add_axes([0.12, 0.27, 0.88, 0.68]); + cs=ax.pcolor(jsens,cmap=cp); + #cs=ax.pcolor(jsens,cmap=cm.jet) + ax.set_xlim([0,npar]); + ax.set_ylim([0,nobs]); + ax.set_xticks([0.5+i for i in range(npar)]); + ax.set_yticks([0.4+i for i in range(nobs)]); + ax.set_yticklabels([case_labels[i] for i in range(nobs)],fontsize=fs1); + ax.set_xticklabels([par_labels_sorted[i] for i in range(npar)],rotation=45,fontsize=fs1); + ax.tick_params(length=0.0) + cbar=plt.colorbar(cs) + #cbar.set_ticks(range(-13,1,1)) + #cbar.set_ticklabels(['$10^{'+str(i)+'}$' for i in range(-13,1,1)]) + + + saveplot(figname) + if showplot: + show() + + diff --git a/PyUQTk/pytests/.!99843!quadpnts.pdf b/PyUQTk/pytests/.!99843!quadpnts.pdf new file mode 100644 index 00000000..9ab49ee0 Binary files /dev/null and b/PyUQTk/pytests/.!99843!quadpnts.pdf differ diff --git a/PyUQTk/pytests/.!99844!quadpnts.pdf b/PyUQTk/pytests/.!99844!quadpnts.pdf new file mode 100644 index 00000000..9ab49ee0 Binary files /dev/null and b/PyUQTk/pytests/.!99844!quadpnts.pdf differ diff --git a/PyUQTk/pytests/.!99845!quadweights.pdf b/PyUQTk/pytests/.!99845!quadweights.pdf new file mode 100644 index 00000000..9ab49ee0 Binary files /dev/null and b/PyUQTk/pytests/.!99845!quadweights.pdf differ diff --git a/PyUQTk/pytests/.!99846!quadweights.pdf b/PyUQTk/pytests/.!99846!quadweights.pdf new file mode 100644 index 00000000..9ab49ee0 Binary files /dev/null and b/PyUQTk/pytests/.!99846!quadweights.pdf differ diff --git a/PyUQTk/pytests/CMakeLists.txt b/PyUQTk/pytests/CMakeLists.txt new file mode 100644 index 00000000..dfdbca7e --- /dev/null +++ b/PyUQTk/pytests/CMakeLists.txt @@ -0,0 +1,22 @@ +project (UQTk) + +set(PYTHON_EXECUTABLE python) + +SET( CMAKE_SWIG_OUTDIR "${PROJECT_BINARY_DIR}" ) + +# Add python tests and run without "make install" +configure_file( PyModTest.py "${CMAKE_SWIG_OUTDIR}/PyModTest.py" COPYONLY ) +add_test( NAME PyModTest COMMAND ${PYTHON_EXECUTABLE} PyModTest.py WORKING_DIRECTORY ${CMAKE_SWIG_OUTDIR} ) + +configure_file( PyArrayTest.py "${CMAKE_SWIG_OUTDIR}/PyArrayTest.py" COPYONLY ) +add_test( NAME PyArrayTest COMMAND ${PYTHON_EXECUTABLE} PyArrayTest.py WORKING_DIRECTORY ${CMAKE_SWIG_OUTDIR} ) + +configure_file( PyArrayTest2.py "${CMAKE_SWIG_OUTDIR}/PyArrayTest2.py" COPYONLY ) +add_test( NAME PyArrayTest2 COMMAND ${PYTHON_EXECUTABLE} PyArrayTest2.py WORKING_DIRECTORY ${CMAKE_SWIG_OUTDIR} ) + +configure_file( PyQuadTest.py "${CMAKE_SWIG_OUTDIR}/PyQuadTest.py" COPYONLY ) +add_test( NAME PyQuadTest COMMAND ${PYTHON_EXECUTABLE} PyQuadTest.py WORKING_DIRECTORY ${CMAKE_SWIG_OUTDIR} ) + +configure_file( PyBCSTest.py "${CMAKE_SWIG_OUTDIR}/PyBCSTest.py" COPYONLY ) +add_test( NAME PyBCSTest COMMAND ${PYTHON_EXECUTABLE} PyBCSTest.py WORKING_DIRECTORY ${CMAKE_SWIG_OUTDIR} ) + diff --git a/PyUQTk/pytests/PyArrayTest.py b/PyUQTk/pytests/PyArrayTest.py new file mode 100644 index 00000000..c98cc7de --- /dev/null +++ b/PyUQTk/pytests/PyArrayTest.py @@ -0,0 +1,109 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +# only necessary for cmake tests, so that user doesn have to "make install" to run +# python tests +import sys +sys.path.append('../uqtkarray/') + +# try to import numpy and matplotlib +try: + from numpy import * + from matplotlib.pyplot import * +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +# try to import uqtk array library and +# functions to convert between uqtk and numpy arrays +try: + import uqtkarray + from uqtkarray import numpy2uqtk + from uqtkarray import uqtk2numpy +except ImportError: + print "PyUQTk array module not found" + print "If installing in a directory other than the build directory, make sure PYTHONPATH includes the install directory" + +import unittest + +''' Test converting 1d numpy array to 1d uqtk array ''' +# create 1d array +N = 35 +x = uqtkarray.dblArray1D(N,0) + +# create 1d numpy array +x_np = random.randn(N) + +# set uqtk array to numpy array +x.setnpdblArray(x_np) + +# test to make sure array elements are the same +for i in range(N): + assert x[i] == x_np[i] + +''' Test converting 2d numpy array to 2d uqtk array ''' +# create 2d array in uqtk +m = 100 +n = 3 +y = uqtkarray.dblArray2D(m,n,1) + +# set 2d array to numpy array +# make sure to pass asfortranarray +y_np = random.randn(m,n) +y.setnpdblArray(asfortranarray(y_np)) + +for i in range(m): + for j in range(n): + assert y[i,j] == y_np[i,j] + +''' alternative using uqtk2numpy and numpy2uqtk ''' + +# test conversion from 1d numpy array to 1d uqtk array +nn = 10 +x1 = random.rand(nn) +y1 = numpy2uqtk(x1) +z1 = uqtk2numpy(y1) +for i in range(nn): + assert x1[i] == y1[i] + +# test conversion from 1d uqtk array to numpy +for i in range(nn): + assert z1[i] == x1[i] + +# test for conversion from 2d numpy to 2d uqtk +nn = 10 +mm = 5 +X1 = random.rand(mm,nn) +Y1 = numpy2uqtk(X1) +Z1 = uqtk2numpy(Y1) +for i in range(mm): + for j in range(nn): + assert X1[i,j] == Y1[i,j] + +# test for conversion from 2d uqtk array to numpy array +for i in range(mm): + for j in range(nn): + assert Z1[i,j] == X1[i,j] diff --git a/PyUQTk/pytests/PyArrayTest2.py b/PyUQTk/pytests/PyArrayTest2.py new file mode 100644 index 00000000..610f15ef --- /dev/null +++ b/PyUQTk/pytests/PyArrayTest2.py @@ -0,0 +1,74 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +import sys +sys.path.append('../uqtkarray/') + +try: + import numpy as np +except ImportError: + "Need numpy to test PyUQTk" + +try: + import uqtkarray + from uqtkarray import numpy2uqtk + from uqtkarray import uqtk2numpy +except ImportError: + print "PyUQTk array module not found" + print "If installing in a directory other than the build directory, make sure PYTHONPATH includes the install directory" + +''' +This file tests to make sure conversion from numpy -> uqtkarray does +not change the row-major (C contiguous) format of the original numpy array + +Also, when converting form uqtkarray-> numpy we want to make sure that the +resulting numpy array is *only* row major (C contiguous) + +''' + +# create numpy matrix and show flags +a_np = np.array([[0, 2.00],[0.1, 1],[1, 5.0]]) +print "flags for a_np to show whether C or F contiguous" +print a_np.flags + +# get a uqtk array from a numpy array (memory is copied, not shared) +a_uqtk = numpy2uqtk(a_np) +print "\nflags for original numpy array to make sure it hasn't changed to F continguous after converting" +# verify that the original numpy array is only C contiguous +assert a_np.flags['F_CONTIGUOUS'] == False +assert a_np.flags['C_CONTIGUOUS'] == True + +print "\nConvert uqtk array back to numpy array and make sure C contiguous" +b_np = uqtk2numpy(a_uqtk) +# test to make sure new numpy array is *only* C contiguous (row - major) +assert b_np.flags['F_CONTIGUOUS'] == False +assert b_np.flags['C_CONTIGUOUS'] == True + +# test for the dot product +print "\ncompute dot product which should be [2,1.1,6] (Note that if F contigous, the dot product would be [.1,3,6]:" +dp = np.dot(b_np,np.ones(2)) +assert np.alltrue( dp == np.array([2.,1.1,6.])) diff --git a/PyUQTk/pytests/PyBCSTest.py b/PyUQTk/pytests/PyBCSTest.py new file mode 100644 index 00000000..13c05a70 --- /dev/null +++ b/PyUQTk/pytests/PyBCSTest.py @@ -0,0 +1,104 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path for PyUQTk. +import sys +sys.path.append('../bcs/') # imports as build lib so installing not needed +sys.path.append('../uqtkarray/') +sys.path.append('../tools/') +sys.path.append('../pce/') + +import os +dir_path = os.path.dirname(os.path.realpath(__file__)) +print dir_path + +try: + import numpy as np + import matplotlib.pyplot as mpl + import pdb +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import uqtkarray as uqtkarray + import pce as uqtkpce + import tools as uqtktools + from bcs import bcsreg +except ImportError: + print "PyUQTk array and quad module not found" + +''' +This example uses BCS to fit + +f(x,y) = 1 + x + .5(3y^2-1) + +using 100 randomly generating training data points +and 20 test data points. Sensitivity analysis is also +performed post fitting. + +''' + +# set dimension +ndim = 2 + +# Create training data +rn = np.random.RandomState(145) +X = 2*rn.rand(100,ndim) - 1 +x1,x2 = X.T[0],X.T[1] +f = lambda x1,x2: 1 + x1 + .5*(3*x2**2-1) +y = f(x1,x2) + +# create test data +Xtest = 2*rn.rand(20,ndim) - 1 +ytest = f(Xtest.T[0],Xtest.T[1]) +testdata = {'X': Xtest, 'y': ytest} + +# BCS hyperparameter definitions +sigsq=None +pcorder = 2 +pctype = "LU" +tol=1e-12 +upit=1 + +# setup, git and predict bcs model +regmodel = bcsreg(ndim=2,pcorder=pcorder,pctype="LU") +c, mindex = regmodel.fit(X,y,upit=upit,tol=tol) +ypred = regmodel.predict(Xtest) + +# print mean squared prediction error +mse = np.mean((ypred - ytest)**2) +nmse = np.mean((ypred - ytest)**2)/np.mean(ytest) +print "\nMSE is %.5g" %mse +print "NMSE is %.5g" %nmse + +# print sensitivities +print "\nSensitivities are ", regmodel.getsens() + +prec = 1e-7 +assert mse < prec, "BCS failed to recover the coefficients to desired precision :-(" + + + diff --git a/PyUQTk/pytests/PyHMCMCTest.py b/PyUQTk/pytests/PyHMCMCTest.py new file mode 100644 index 00000000..b17333e9 --- /dev/null +++ b/PyUQTk/pytests/PyHMCMCTest.py @@ -0,0 +1,192 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +try: + from numpy import * + from matplotlib.pyplot import * + from acor import * +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import PyUQTk.array as uqtkarray + import PyUQTk.mcmc as uqtkmcmc + from PyUQTk.inference.mcmc import * + from PyUQTk.inference.postproc import * +except ImportError: + print "PyUQTk array module not found" + print "If installing in a directory other than the build directory, make sure PYTHONPATH includes the install directory" + +import time + +''' +Use HMCMC to get samples from banana shaped function +''' + +def U(q,a=1.0,b=100.0): + ''' + U(q) = -log(prior(q)*Likelihood(q|data)) + ''' + q = copy(atleast_2d(q)) + return b*(q[:,1] - q[:,0]**2)**2 + (a - q[:,0])**2 + +def grad_U(q): + ''' + grad_U(q) = gradient vector of U at q + ''' + q = copy(atleast_2d(q)) + dUdx = (-400*q[:,0]*(q[:,1] - q[:,0]**2) - 2*(1 - q[:,0]))[0] + dUdy = (200*(q[:,1] - q[:,0]**2))[0] + return array([dUdx,dUdy]) + +# def HMCMC(U,grad_U,eps,L,q): +# current_q = copy(q) # save current + +# # generate current p +# # propcov = 4*array([[ 0.01175383, 0.02065261],[ 0.02065261, 0.04296117]]) +# p = random.randn(len(current_q)) +# # p = random.multivariate_normal([0,0],propcov) +# current_p = copy(p) # save current p + +# # make half step for momentum used for leap frog step +# p = p - eps * grad_U(q)/2.0 + +# for i in range(L): +# # p = p - eps * grad_U(q)/2.0 +# q = q + eps*p +# # p = p - eps * grad_U(q)/2.0 +# if (i != L-1): p = p - eps*grad_U(q) + +# # make a half step for momentum at the end +# p = p - eps * grad_U(q)/2.0 + +# # negate the momentum to make a symmetric proposal +# p = -p + +# # Evaluate potential and kinetic energy +# current_U = U(current_q)[0] +# current_K = sum(current_p**2)/2.0 +# proposed_U = U(q)[0] +# proposed_K = sum(p**2)/2.0 + +# # Accept or reject the state at end of trajectory, returning either +# # the position at the end of the trajectory or the initial position + +# if (log(random.rand()) < current_U-proposed_U+current_K-proposed_K): +# return q +# else: +# alpha = 0 +# return current_q + +fig = figure() +ax1 = fig.add_subplot(2,2,1) +ax2 = fig.add_subplot(2,2,2) +ax3 = fig.add_subplot(2,2,3) +ax4 = fig.add_subplot(2,2,4) + +# Test U(q) +N = 80 +qx = linspace(-1.5,2.5,N) +qy = linspace(-.5,5,N) +qx,qy = meshgrid(qx,qy) +qz = exp(-U(array(zip(qx.flatten(),qy.flatten())))) +qz.shape = (N,N) + +# Test grad_U +dUdx = zeros((N,N)) +dUdy = zeros((N,N)) +for i in range(N): + for j in range(N): + dU = grad_U([qx[i,j],qy[i,j]]) + dUdx[i,j] = dU[0] + dUdy[i,j] = dU[1] + +# Test HMCMC +print '\n*****************\nTesting HMCMC\n*****************\n' +samples1 = [] +qstart = array([1.0,1.0]) +q = copy(qstart) +samples1.append(copy(q)) +eps = .01 +L = 150 +M = 500 +nburn = 300 +thin1 = 1 +for i in range(M): + q = HMCMC(U,grad_U,eps,L,q) + if i > 0: + samples1.append(copy(q)) +samples1 = array(samples1) + +# ax1.plot(qstart[0],qstart[0],'ok') +# ax1.quiver(qx,qy,-dUdx,-dUdy,alpha=.1) +# ax1.contour(qx,qy,qz,20,alpha=.4) +# ax1.plot(samples1[nburn::thin1,0],samples1[nburn::thin1,1],'*k',alpha=.1) + +''' +Use AMCMC for banana shaped function +''' +class pyLikelihood(uqtkmcmc.LikelihoodBase): + def eval(self,x): + x0 = x[0] + x1 = x[1] + return -(1-x0)*(1-x0) - 100*(x1 - x0*x0)*(x1 - x0*x0) + +# testing MCMC library +print '\n*****************\nTesting AMCMC\n*****************\n' +Like = pyLikelihood() +xstart = uqtkarray.dblArray1D(2,1.0) +mchain = uqtkmcmc.MCMC(Like) +dim = 2 +mchain.setChainDim(dim) +mchain.initMethod("am") +g = uqtkarray.dblArray1D(dim,.1) +mchain.initChainPropCovDiag(g) +nCalls = L*M +thin2 = thin1*L +mchain.setWriteFlag(0) +mchain.setOutputInfo("txt","chain.dat",M,nCalls); +mchain.runChain(nCalls,xstart); +mchain.getSamples() +samples = mchain.samples +samples2 = zeros((dim,nCalls)) +samples.getnpdblArray(samples2) +samples2 = samples2.T +propcov = uqtkarray.dblArray2D(2,2,0) +mchain.getChainPropCov(propcov) +m1 = propcov[0,0]; m2 = propcov[1,1] + +# ax2.contour(qx,qy,qz,250,alpha=.4) +# ax2.plot(samples2[L*nburn::thin2,0],samples2[L*nburn::thin2,1],'*g',alpha=.1) + +# plot mixing of samples +ax3.plot(samples1[nburn::thin1,0],'k',alpha=.4) +ax3.plot(samples2[L*nburn::thin2,0],'g',alpha=.4) +ax4.plot(samples1[nburn::thin1,1],'k',alpha=.4) +ax4.plot(samples2[L*nburn::thin2,1],'g',alpha=.4) + +print 'acor using HMCMC', acor(samples1[nburn::thin1,0]) +print 'acor using MCMC', acor(samples2[L*nburn::thin2,0]) diff --git a/PyUQTk/pytests/PyMCMC2dTest.py b/PyUQTk/pytests/PyMCMC2dTest.py new file mode 100644 index 00000000..f66ed8a5 --- /dev/null +++ b/PyUQTk/pytests/PyMCMC2dTest.py @@ -0,0 +1,101 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +import sys +sys.path.append('../../') + +try: + from numpy import * + from matplotlib.pyplot import * +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import PyUQTk.array as uqtkarray + import PyUQTk.mcmc as uqtkmcmc +except ImportError: + print "PyUQTk array module not found" + print "If installing in a directory other than the build directory, make sure PYTHONPATH includes the install directory" + +import time + +# temp = random.randn(1000.) +# a = uqtkarray.dblArray1D(1000,101.0) + +class pyLikelihood(uqtkmcmc.LikelihoodBase): + def eval(self,x): + # a.getnpdblarray(temp) + # temp = array(a.pint4py()) + x0 = x[0] + x1 = x[1] + return -(1-x0)*(1-x0) - 100*(x1 - x0*x0)*(x1 - x0*x0) + +start = time.time() +# testing MCMC library +print '\n*****************\nTesting MCMC\n*****************\n' +print 'Setting LogPosterior function, L' +print 'L is defined in uqtk.cpp (Rosenbrock function)' +L = pyLikelihood() +print 'Testing logposterior function' +xstart = uqtkarray.dblArray1D(2,0) +print xstart +print 'L.eval(x) = ', L.eval(xstart) + +print 'Setting up the sampler' +mchain = uqtkmcmc.MCMC(L) +print 'Setting chain dim, type (ss), initial proposal covariance' +dim = 2 +mchain.setChainDim(dim) +mchain.initMethod("ss") +g = uqtkarray.dblArray1D(dim,.1) +mchain.initChainPropCovDiag(g) +print 'Chain Setup:' +mchain.printChainSetup(); +print 'Running chain to chain.dat ...' +nCalls = 100000 +mchain.setOutputInfo("txt","chain.dat",nCalls,nCalls); +mchain.runChain(nCalls,xstart); +print 'loading samples and plotting' +thin = 25 +samples = loadtxt('chain.dat')[3001:-1:thin,1:3] +figure() +plot(samples[:,0],samples[:,1],'.') + +# get the likelihood information +print 'Getting samples into numpy array...' +# logprobs = zeros(nCalls); +mchain.getSamples() +samples = mchain.samples +npsamples = zeros((dim,nCalls)) +samples.getnpdblArray(npsamples) +figure() +plot(npsamples[0][::thin],npsamples[1][::thin],'.g') + +end = time.time() +print end - start + +# show() diff --git a/PyUQTk/pytests/PyMCMCTest.py b/PyUQTk/pytests/PyMCMCTest.py new file mode 100644 index 00000000..c57aa567 --- /dev/null +++ b/PyUQTk/pytests/PyMCMCTest.py @@ -0,0 +1,142 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +import sys +sys.path.append('../../') + +try: + from numpy import * + from matplotlib.pyplot import * + import time +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import PyUQTk.array as uqtkarray + import PyUQTk.quad as uqtkquad + import PyUQTk.mcmc as uqtkmcmc +except ImportError: + print "PyUQTk array and quad module not found" + +# class pyLikelihood(uqtkmcmc.LikelihoodBase): +# def eval(self,x): +# x0 = x[0] +# x1 = x[1] +# return -(1-x0)*(1-x0) - 100*(x1 - x0*x0)*(x1 - x0*x0) +# class pyLikelihood(uqtkmcmc.LikelihoodBase): +# def eval(self,x): +# ''' +# sample from 1./(abs(1-x**2)) +# ''' +# y1 = x[0] +# y2 = x[1] +# if sqrt(y1**2 + y2**2) > 1: +# return -1e16 +# else: +# return -.0001*log(1 - y2**2 - y1**2) +class pyLikelihood(uqtkmcmc.LikelihoodBase): + def eval(self,x): + ''' + sample from exp(-.5*(x**2/.1**2 - y**2/.8**2)) + ''' + y1 = x[0] + y2 = x[1] + return -.5*(y1**2/.1**2 + y2**2/.8**2) + +start = time.time() +# testing MCMC library +print '\n*****************\nTesting MCMC\n*****************\n' +print 'Setting LogPosterior function, L' +print 'L is defined in uqtk.cpp (Rosenbrock function)' +L = pyLikelihood() +print 'Testing logposterior function' +xstart = uqtkarray.dblArray1D(2,0) +print xstart +print 'L.eval(x) = ', L.eval(xstart) + +print 'Setting up the sampler' +mchain = uqtkmcmc.MCMC(L) + +print 'Setting chain dim, type (ss), initial proposal covariance' +dim = 2 +mchain.setChainDim(dim) +mchain.initMethod("am") +g = uqtkarray.dblArray1D(dim,.5) +mchain.initChainPropCovDiag(g) + +print 'Running chain to chain.dat ...' +nCalls = 100000 +# mchain.setOutputInfo("txt","chain.dat",nCalls,nCalls); +mchain.setWriteFlag(0) +mchain.runChain(nCalls,xstart); + +print 'Getting samples into numpy array...' +mchain.getSamples() +samples = array(mchain.samples).T[3000::5,:] +print std(samples,0) - array([.1,.8]) + +# print 'loading samples and plotting' +# thin = 25 +# samples = loadtxt('chain.dat')[3001:-1:thin,1:3] +# figure() +# plot(samples[:,0],samples[:,1],'.') + + +# # get quad points and weights +# x = uqtkarray.dblArray2D() +# w = uqtkarray.dblArray1D() + +# print 'Create an instance of Quad class' +# ndim = 2 +# level = 5 +# q = uqtkquad.Quad('LU','sparse',ndim,level,0,1) +# print 'Now set and get the quadrature rule...' +# q.SetRule() +# q.GetRule(x,w) + +# # print out x and w +# print 'Displaying the quadrature points and weights:\n' +# # print x +# # print w +# n = len(x) +# print 'Number of quad points is ', n, '\n' + +# # now we plot the points +# print 'Plotting the points (get points in column major order as a flattened vector)' +# print 'need to use reshape with fortran ordering' +# xpnts = zeros((n,ndim)) +# x.getnpdblArray(xpnts) +# plot(xpnts[:,0], xpnts[:,1],'ob',ms=10,alpha=.25) +# savefig('quadpnts.pdf') + +# # get quad weights +# w_np = zeros(n) +# w.getnpdblArray(w_np) +# clf() +# plot(w,'ro-',lw=4) +# savefig('quadweights.pdf') + diff --git a/PyUQTk/pytests/PyModTest.py b/PyUQTk/pytests/PyModTest.py new file mode 100644 index 00000000..91020377 --- /dev/null +++ b/PyUQTk/pytests/PyModTest.py @@ -0,0 +1,54 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +""" Test to make sure all Python modules load. """ +import sys + +print "Loading array module:" +sys.path.append('../uqtkarray/') +import uqtkarray + +print "Loading quadrature module:" +sys.path.append('../quad/') +import quad + +print "Loading bayesian compressed sensing module:" +# sys.path.append('../bcs/') +# import bcs + +print "Loading polynomial chaos module:" +sys.path.append('../pce/') +import pce + +print "Loading tools module:" +sys.path.append('../tools') +import tools + +#print "Loading dfi module:" +#sys.path.append('../dfi/') +#import dfi + diff --git a/PyUQTk/pytests/PyPCE1dTest.py b/PyUQTk/pytests/PyPCE1dTest.py new file mode 100644 index 00000000..e6871c2b --- /dev/null +++ b/PyUQTk/pytests/PyPCE1dTest.py @@ -0,0 +1,131 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +import sys +sys.path.append('../../') + +try: + from numpy import * + from matplotlib.pyplot import * +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import PyUQTk.array as uqtkarray + import PyUQTk.quad as uqtkquad + import PyUQTk.pce as uqtkpce +except ImportError: + print "PyUQTk array and quad module not found" + + +# get quad points and weights +x = uqtkarray.dblArray2D() +w = uqtkarray.dblArray1D() + +print 'Create an instance of Quad class' +ndim = 1 +level = 8 +q = uqtkquad.Quad('LU','full',ndim,level) +print 'Now set and get the quadrature rule...' +q.SetRule() +q.GetRule(x,w) + +# print out x and w +print 'Displaying the quadrature points and weights:\n' +# print x +# print w +n = len(x) +print 'Number of quad points is ', n, '\n' + +# conver to numpy arrays +x_np = zeros((len(x),1)) +w_np = zeros(len(x)) +x.getnpdblArray(x_np) +w.getnpdblArray(w_np) + +# define function for evaluation over [-1,1] +f = lambda x: 1./(1 + x**2) +y = f(x_np) +y.shape = (len(y),) # make 1d array + +# convert numpy y to 1d array +ydata = uqtkarray.dblArray1D(len(y),0) +ydata.setnpdblArray(y) + +''' +Define PCSet object +''' +# Instantiate object +nord = 8 +chaos_type = "LEG" +pcmodel = uqtkpce.PCSet('NISPnoq',nord,ndim,'LEG') + +# set quad rule for pc model +pcmodel.SetQuadRule(q) +nup = pcmodel.GetNumberPCTerms()-1 +totquad = pcmodel.GetNQuadPoints() + +# Get the multiindex for postprocessing +mindex = uqtkarray.intArray2D(); +pcmodel.GetMultiIndex(mindex); + +# get the coefficients using the quadrature rule +# to calculate the projections +ck = uqtkarray.dblArray1D(nup+1,0.0) +pcmodel.GalerkProjection(ydata,ck); +c_np = zeros(len(ck)) +ck.getnpdblArray(c_np) + +''' +Evaluate PC Model at random points +''' +xall = linspace(-1,1,1000); xall.shape = (len(xall),1) +yeval = uqtkarray.dblArray1D(len(xall),0.0) +xeval = uqtkarray.dblArray2D(len(xall),1,0.0) +xeval.setnpdblArray(asfortranarray(xall)) +pcmodel.EvalPCAtCustPoints(yeval,xeval,ck) + +y_exact = f(xall) +y_pce = array(yeval.flatten()) +plot(xall,y_exact,'k',lw=2,alpha=.4) +plot(xeval,y_pce,'--r',lw=1) + +''' +Evaluate PC Model at quad points +''' +yevalq = uqtkarray.dblArray1D(len(x),0.0) +pcmodel.EvalPCAtCustPoints(yevalq,x,ck) +y_pceq = array(yevalq.flatten()) +plot(x,y_pceq,'or',lw=1) + +''' +Plot the ImportError +''' +figure() +plot(xeval,abs(y_pce - y_exact[:,0]),'k') + + diff --git a/PyUQTk/pytests/PyPCE2dTest.py b/PyUQTk/pytests/PyPCE2dTest.py new file mode 100644 index 00000000..8da37cb7 --- /dev/null +++ b/PyUQTk/pytests/PyPCE2dTest.py @@ -0,0 +1,148 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +import sys +sys.path.append('../../') + +try: + from numpy import * + from matplotlib.pyplot import * +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import PyUQTk.array as uqtkarray + import PyUQTk.quad as uqtkquad + import PyUQTk.pce as uqtkpce +except ImportError: + print "PyUQTk array and quad module not found" + + +# get quad points and weights +x = uqtkarray.dblArray2D() +w = uqtkarray.dblArray1D() + +print 'Create an instance of Quad class' +ndim = 2 +level = 8 +q = uqtkquad.Quad('LU','full',ndim,level) +print 'Now set and get the quadrature rule...' +q.SetRule() +q.GetRule(x,w) + +# print out x and w +print 'Displaying the quadrature points and weights:\n' +print x +print w +n = len(x) +print 'Number of quad points is ', n, '\n' + +# conver to numpy arrays +x_np = zeros((n,2)) +w_np = zeros(len(x)) +x.getnpdblArray(x_np) +w.getnpdblArray(w_np) + +# define function for evaluation over [-1,1] +f = lambda x: x[:,0]*x[:,1] + x[:,0]**2 + sqrt(abs(x[:,1])) +y = f(x_np) +y.shape = (len(y),) # make 1d array + +# convert numpy y to 1d array +ydata = uqtkarray.dblArray1D(len(y),0) +ydata.setnpdblArray(y) + +''' +Define PCSet object +''' +# Instantiate object +nord = 4 +chaos_type = "LEG" +pcmodel = uqtkpce.PCSet('NISPnoq',nord,ndim,'LEG') + +# set quad rule for pc model +pcmodel.SetQuadRule(q) +nup = pcmodel.GetNumberPCTerms()-1 +totquad = pcmodel.GetNQuadPoints() + +# Get the multiindex for postprocessing +mindex = uqtkarray.intArray2D(); +pcmodel.GetMultiIndex(mindex); + +# get the coefficients using the quadrature rule +# to calculate the projections +ck = uqtkarray.dblArray1D(nup+1,0.0) +pcmodel.GalerkProjection(ydata,ck); +c_np = zeros(len(ck)) +ck.getnpdblArray(c_np) + +# compute main sensitivities +mainsens = uqtkarray.dblArray1D(ndim,0) +pcmodel.ComputeMainSens(ck,mainsens) + +# compute total sensitivity +totsens = uqtkarray.dblArray1D(ndim,0) +pcmodel.ComputeTotSens(ck,totsens) + +#compute joint sensitivity +jointsens = uqtkarray.dblArray2D(ndim,ndim,0) +pcmodel.ComputeJointSens(ck,jointsens) + +print mainsens, totsens, jointsens + +# ''' +# Evaluate PC Model at random points +# ''' +# xall = linspace(-1,1,1000); xall.shape = (len(xall),1) +# yeval = uqtkarray.dblArray1D(len(xall),0.0) +# xeval = uqtkarray.dblArray2D(len(xall),1,0.0) +# xeval.setnpdblArray(asfortranarray(xall)) +# pcmodel.EvalPCAtCustPoints(yeval,xeval,ck) + +# y_exact = f(xall) +# y_pce = array(yeval.flatten()) +# plot(xall,y_exact,'k',lw=2,alpha=.4) +# plot(xeval,y_pce,'--r',lw=1) + +# ''' +# Evaluate PC Model at quad points +# ''' +# yevalq = uqtkarray.dblArray1D(len(x),0.0) +# pcmodel.EvalPCAtCustPoints(yevalq,x,ck) +# y_pceq = array(yevalq.flatten()) +# plot(x,y_pceq,'or',lw=1) + +# ''' +# Plot the ImportError +# ''' +# figure() +# plot(xeval,abs(y_pce - y_exact[:,0]),'k') + + + + + diff --git a/PyUQTk/pytests/PyQuadTest.py b/PyUQTk/pytests/PyQuadTest.py new file mode 100644 index 00000000..b69977c9 --- /dev/null +++ b/PyUQTk/pytests/PyQuadTest.py @@ -0,0 +1,139 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +# include path to include PyUQTk +import sys +sys.path.append('../uqtkarray/') +sys.path.append('../quad/') + +try: + from numpy import * + from matplotlib.pyplot import * +except ImportError: + "Need numpy and matplotlib to test PyUQTk" + +try: + import uqtkarray + from uqtkarray import numpy2uqtk + from uqtkarray import uqtk2numpy + import quad as uqtkquad +except ImportError: + print "PyUQTk array and quad module not found" + +''' +This file tests the quadrature pyqutk routine +''' + +# true quad points for sparse LU with ndim = 2 and level = 3 +qpnts_ref = array([[-9.681602395076263079e-01, 0.000000000000000000e+00], +[-9.061798459386638527e-01, -7.745966692414832933e-01], +[-9.061798459386638527e-01, 0.000000000000000000e+00], +[-9.061798459386638527e-01, 7.745966692414834043e-01], +[-8.360311073266358806e-01, 0.000000000000000000e+00], +[-7.745966692414832933e-01, -9.061798459386638527e-01], +[-7.745966692414832933e-01, -7.745966692414832933e-01], +[-7.745966692414832933e-01, -5.384693101056832187e-01], +[-7.745966692414832933e-01, 0.000000000000000000e+00], +[-7.745966692414832933e-01, 5.384693101056829967e-01], +[-7.745966692414832933e-01, 7.745966692414834043e-01], +[-7.745966692414832933e-01, 9.061798459386638527e-01], +[-6.133714327005902467e-01, 0.000000000000000000e+00], +[-5.384693101056832187e-01, -7.745966692414832933e-01], +[-5.384693101056832187e-01, 0.000000000000000000e+00], +[-5.384693101056832187e-01, 7.745966692414834043e-01], +[-3.242534234038090268e-01, 0.000000000000000000e+00], +[0.000000000000000000e+00, -9.681602395076263079e-01], +[0.000000000000000000e+00, -9.061798459386638527e-01], +[0.000000000000000000e+00, -8.360311073266358806e-01], +[0.000000000000000000e+00, -7.745966692414832933e-01], +[0.000000000000000000e+00, -6.133714327005902467e-01], +[0.000000000000000000e+00, -5.384693101056832187e-01], +[0.000000000000000000e+00, -3.242534234038090268e-01], +[0.000000000000000000e+00, 0.000000000000000000e+00], +[0.000000000000000000e+00, 3.242534234038088048e-01], +[0.000000000000000000e+00, 5.384693101056829967e-01], +[0.000000000000000000e+00, 6.133714327005905798e-01], +[0.000000000000000000e+00, 7.745966692414834043e-01], +[0.000000000000000000e+00, 8.360311073266353254e-01], +[0.000000000000000000e+00, 9.061798459386638527e-01], +[0.000000000000000000e+00, 9.681602395076263079e-01], +[3.242534234038088048e-01, 0.000000000000000000e+00], +[5.384693101056829967e-01, -7.745966692414832933e-01], +[5.384693101056829967e-01, 0.000000000000000000e+00], +[5.384693101056829967e-01, 7.745966692414834043e-01], +[6.133714327005905798e-01, 0.000000000000000000e+00], +[7.745966692414834043e-01, -9.061798459386638527e-01], +[7.745966692414834043e-01, -7.745966692414832933e-01], +[7.745966692414834043e-01, -5.384693101056832187e-01], +[7.745966692414834043e-01, 0.000000000000000000e+00], +[7.745966692414834043e-01, 5.384693101056829967e-01], +[7.745966692414834043e-01, 7.745966692414834043e-01], +[7.745966692414834043e-01, 9.061798459386638527e-01], +[8.360311073266353254e-01, 0.000000000000000000e+00], +[9.061798459386638527e-01, -7.745966692414832933e-01], +[9.061798459386638527e-01, 0.000000000000000000e+00], +[9.061798459386638527e-01, 7.745966692414834043e-01], +[9.681602395076263079e-01, 0.000000000000000000e+00]]) + +# initiate uqtk arrays for quad points and weights +x = uqtkarray.dblArray2D() +w = uqtkarray.dblArray1D() + +# create instance of quad class and output +# points and weights +print 'Create an instance of Quad class' +ndim = 2 +level = 3 +q = uqtkquad.Quad('LU','sparse',ndim,level,0,1) +print 'Now set and get the quadrature rule...' +q.SetRule() +q.GetRule(x,w) + +# print out x and w +print 'Displaying the quadrature points and weights:\n' +x_np = uqtk2numpy(x) +print x_np +n = len(x) +print 'Number of quad points is ', n, '\n' + +# plot the quadrature points +print 'Plotting the points (get points in column major order as a flattened vector)' +print 'need to use reshape with fortran ordering' +xpnts = zeros((n,ndim)) +x.getnpdblArray(xpnts) +# plot(xpnts[:,0], xpnts[:,1],'ob',ms=10,alpha=.25) +# show() + +# convert the quad weights to numpy arrays +w_np = zeros(n) +w.getnpdblArray(w_np) + +# asserting the quadrature points are correct +m,n = x_np.shape +for i in range(m): + for j in range(n): + assert x_np[i,j] == qpnts_ref[i,j] + diff --git a/PyUQTk/pytests/quadpnts.pdf b/PyUQTk/pytests/quadpnts.pdf new file mode 100644 index 00000000..92663dd7 Binary files /dev/null and b/PyUQTk/pytests/quadpnts.pdf differ diff --git a/PyUQTk/pytests/quadweights.pdf b/PyUQTk/pytests/quadweights.pdf new file mode 100644 index 00000000..be8fdb05 Binary files /dev/null and b/PyUQTk/pytests/quadweights.pdf differ diff --git a/PyUQTk/quad/CMakeLists.txt b/PyUQTk/quad/CMakeLists.txt new file mode 100644 index 00000000..931965f1 --- /dev/null +++ b/PyUQTk/quad/CMakeLists.txt @@ -0,0 +1,57 @@ +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}/../../Extras/lib/python/numpy/core/include) + +#include source files +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/) # array classes, array input output, and array tools +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/include/) # utilities like error handlers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/) # tools like multindex, etc. +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/) # quad class + +# include dependencies +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/blas/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lapack/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/dsfmt/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/figtree/) # blas library headers +# INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../numpy/) # numpy headers + +SET(CMAKE_SWIG_FLAGS "") +SET_SOURCE_FILES_PROPERTIES(quad.i PROPERTIES CPLUSPLUS ON) + +# compile swig with cpp extensions +SWIG_ADD_MODULE( + quad python quad.i + # # array tools needed to compile misc tools source files + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arrayio.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arraytools.cpp + + # source code for quad class + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/quad/quad.cpp + + # # source code for tools + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/combin.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/gq.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/minmax.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/multiindex.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/pcmaps.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/probability.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/rosenblatt.cpp +) + +# link python and 3rd party libraries, e.g., fortran and blas +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + SWIG_LINK_LIBRARIES(quad uqtkarray uqtktools deplapack depdsfmt depblas depfigtree depann gfortran ${PYTHON_LIBRARIES}) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + SWIG_LINK_LIBRARIES(quad uqtkarray uqtktools deplapack depdsfmt depblas depfigtree depann ifcore ${PYTHON_LIBRARIES}) +endif() + + +INSTALL(TARGETS _quad DESTINATION PyUQTk/) +INSTALL(FILES ${CMAKE_BINARY_DIR}/${outdir}PyUQTk/quad/quad.py DESTINATION PyUQTk) diff --git a/PyUQTk/quad/quad.i b/PyUQTk/quad/quad.i new file mode 100644 index 00000000..65bb7dc7 --- /dev/null +++ b/PyUQTk/quad/quad.i @@ -0,0 +1,130 @@ +%module(directors="1") quad +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2013) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== + +%{ +#define SWIG_FILE_WITH_INIT +#include +#include +#include +#include +#include +// #include "../../cpp/lib/array/Array1D.h" +// #include "../../cpp/lib/array/Array2D.h" +// #include "../../cpp/lib/array/arrayio.h" +// #include "../../cpp/lib/array/arraytools.h" +// #include "../../cpp/lib/tools/combin.h" +// #include "../../cpp/lib/tools/gq.h" +// #include "../../cpp/lib/tools/minmax.h" +// #include "../../cpp/lib/tools/multiindex.h" +// #include "../../cpp/lib/tools/pcmaps.h" +// #include "../../cpp/lib/tools/probability.h" +// #include "../../cpp/lib/tools/rosenblatt.h" + +#include "../../cpp/lib/quad/quad.h" + +%} + +/************************************************************* +// Standard SWIG Templates +*************************************************************/ + +// Include standard SWIG templates +// Numpy array templates and wrapping +%include "pyabc.i" +%include "../numpy/numpy.i" +%include "std_vector.i" +%include "std_string.i" +%include "cpointer.i" + +%init %{ + import_array(); +%} + +%pointer_functions(double, doublep); + +/************************************************************* +// Numpy SWIG Interface files +*************************************************************/ + +// // Basic typemap for an Arrays and its length. +// // Must come before %include statement below + +// // For Array1D setnumpyarray4py function +// %apply (long* IN_ARRAY1, int DIM1) {(long* inarray, int n)} +// %apply (double* IN_ARRAY1, int DIM1) {(double* inarray, int n)} +// // get numpy int and double array +// %apply (long* INPLACE_ARRAY1, int DIM1) {(long* outarray, int n)} +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* outarray, int n)} + +// // For Array2D numpysetarray4py function +// %apply (double* IN_FARRAY2, int DIM1, int DIM2) {(double* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (double* INPLACE_FARRAY2, int DIM1, int DIM2) {(double* outarray, int n1, int n2)} +// // For Array2D numpysetarray4py function +// %apply (long* IN_FARRAY2, int DIM1, int DIM2) {(long* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (long* INPLACE_FARRAY2, int DIM1, int DIM2) {(long* outarray, int n1, int n2)} + + +// // For mcmc test to get log probabilities +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* l, int n)} + +/************************************************************* +// Include header files +*************************************************************/ + +// // The above typemap is applied to header files below +// %include "../../cpp/lib/array/Array1D.h" +// %include "../../cpp/lib/array/Array2D.h" +// %include "../../cpp/lib/array/arrayio.h" +// %include "../../cpp/lib/array/arraytools.h" +// %include "../../cpp/lib/tools/combin.h" +// %include "../../cpp/lib/tools/gq.h" +// %include "../../cpp/lib/tools/minmax.h" +// %include "../../cpp/lib/tools/multiindex.h" +// %include "../../cpp/lib/tools/pcmaps.h" +// %include "../../cpp/lib/tools/probability.h" +// %include "../../cpp/lib/tools/rosenblatt.h" + +%include "../../cpp/lib/quad/quad.h" + +// // Typemaps for standard vector +// // Needed to prevent to memory leak due to lack of destructor +// // must use namespace std +// namespace std{ +// %template(dblVector) vector; +// %template(intVector) vector; +// %template(strVector) vector; + +// } + + +// %include "arrayext.i" + + + diff --git a/PyUQTk/sens/CMakeLists.txt b/PyUQTk/sens/CMakeLists.txt new file mode 100644 index 00000000..5a186774 --- /dev/null +++ b/PyUQTk/sens/CMakeLists.txt @@ -0,0 +1,10 @@ +project (UQTk) + +SET(copy_FILES + __init__.py + gsalib.py + ) + +INSTALL(FILES ${copy_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION PyUQTk/sens) diff --git a/PyUQTk/sens/__init__.py b/PyUQTk/sens/__init__.py new file mode 100755 index 00000000..f34768cb --- /dev/null +++ b/PyUQTk/sens/__init__.py @@ -0,0 +1,27 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import gsalib diff --git a/PyUQTk/sens/gsalib.py b/PyUQTk/sens/gsalib.py new file mode 100644 index 00000000..c66cb4ee --- /dev/null +++ b/PyUQTk/sens/gsalib.py @@ -0,0 +1,284 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +try: + import numpy as npy +except ImportError: + print "gsalib requires numpy package -> Exit" + quit() + +import os.path + +def genSpl_Si(nspl,ndim,abrng,**kwargs): + # get default values for optional arguments + splout = kwargs.get('splout', "gsaSplSi.dat") # samples file + matfile = kwargs.get('matfile',"mat12.npz") # intermediary matrices + verb = kwargs.get('verb', 0) # verbosity + nd = kwargs.get('nd', 18) # no. of significant digits in samples output + # Test nd values + if (nd<6) or (nd>18): + raise ValueError("Number of digits should be between 6 and 18") + #------------------------------------------------------------------------------------ + # create nspl uniform samples in [a_i,b_i], i=1,ndim + #------------------------------------------------------------------------------------ + if verb>0: + print "Create ensemble of input parameters" + mat1=npy.random.random_sample((nspl,ndim)) + mat2=npy.random.random_sample((nspl,ndim)) + for i in range(ndim): + mat1[:,i] = mat1[:,i]*(abrng[i,1]-abrng[i,0])+abrng[i,0] + mat2[:,i] = mat2[:,i]*(abrng[i,1]-abrng[i,0])+abrng[i,0] + # save temporary matrices + npy.savez(matfile, mat1=mat1, mat2=mat2) + # assemble the big matrix for main sensitivities directly to a file + if os.path.isfile(splout): + os.remove(splout) + f_handle = file(splout, 'a') + npy.savetxt(f_handle, mat1, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + for idim in range(ndim): + if verb>0: + print " - working on parameter %d"%idim + matj=mat2.copy(); + matj[:,idim]=mat1[:,idim] + npy.savetxt(f_handle, matj, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + npy.savetxt(f_handle, mat2, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + f_handle.close() + +def genSens_Si(modeval,ndim,**kwargs): + # get optional arguments + verb = kwargs.get('verb', 0) # verbosity + #------------------------------------------------------------------------------------ + # load model evaluations and compute main sensitivities + #------------------------------------------------------------------------------------ + ymod = npy.genfromtxt(modeval) + nspl = ymod.shape[0]/(ndim+2) + if verb > 0: + print "Compute sensitivities, no. of samples:",nspl + sobolSi = npy.zeros(ndim) + yMat1 = ymod[:nspl] + yMat2 = ymod[nspl*(ndim+1):] + mean12 = npy.mean(yMat1*yMat2) + vv1 = npy.var(yMat1,ddof=1) + for idim in range(1,ndim+1): + vari = npy.sum(yMat1*ymod[idim*nspl:(idim+1)*nspl]) + sobolSi[idim-1] = (vari/(nspl-1.0)-mean12)/vv1 + if verb > 1: + print " - parameter ",idim,": ",sobolSi[idim-1] + if verb > 0: + print " - total first order sensitivity: ",npy.sum(sobolSi) + return sobolSi + +def genSpl_SiT(nspl,ndim,abrng,**kwargs): + # get optional arguments + splout = kwargs.get('splout', "gsaSplSiT.dat") # samples file + matfile = kwargs.get('matfile', "mat12.npz") # intermediary matrices + verb = kwargs.get('verb', 0) # verbosity + nd = kwargs.get('nd', 18) # no. of significant digits in samples output + # Test nd values + if (nd<6) or (nd>18): + raise ValueError("Number of digits should be between 6 and 18") + #------------------------------------------------------------------------------------ + # create nspl uniform samples in [a_i,b_i], i=1,ndim + #------------------------------------------------------------------------------------ + if verb>0: + print "Create ensemble of input parameters" + mat1=npy.random.random_sample((nspl,ndim)) + mat2=npy.random.random_sample((nspl,ndim)) + for i in range(ndim): + mat1[:,i] = mat1[:,i]*(abrng[i,1]-abrng[i,0])+abrng[i,0] + mat2[:,i] = mat2[:,i]*(abrng[i,1]-abrng[i,0])+abrng[i,0] + # save temporary matrices + npy.savez(matfile, mat1=mat1, mat2=mat2) + # assemble the big matrix for main sensitivities + if os.path.isfile(splout): + os.remove(splout) + f_handle = file(splout, 'a') + npy.savetxt(f_handle, mat1, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + for idim in range(ndim): + if verb>0: + print " - working on parameter %d"%idim + matj=mat1.copy(); + matj[:,idim]=mat2[:,idim] + npy.savetxt(f_handle, matj, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + npy.savetxt(f_handle, mat2, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + f_handle.close() + return + +def genSens_SiT(modeval,ndim,**kwargs): + # get optional arguments + verb = kwargs.get('verb', 0) # verbosity + siTmethod = kwargs.get('type', 'type1') # sampling method + #------------------------------------------------------------------------------------ + # load model evaluations and compute main sensitivities + #------------------------------------------------------------------------------------ + ymod = npy.genfromtxt(modeval) + nspl = ymod.shape[0]/(ndim+2) + if verb > 0: + print "Compute sensitivities, no. of samples:",nspl + sobolSiT = npy.zeros(ndim) + yMat1 = ymod[:nspl] + vv1 = npy.var(yMat1,ddof=1) + Ey = npy.average(yMat1) + for idim in range(1,ndim+1): + if (siTmethod == "type1"): + ssqrs=0.0 + for i in range(nspl): + ssqrs = ssqrs+yMat1[i]*ymod[idim*nspl+i] + vari = ssqrs/(nspl-1.0) + sobolSiT[idim-1] = 1-(vari-Ey**2)/(vv1); + else: + vari = npy.sum(npy.power(yMat1-ymod[idim*nspl:(idim+1)*nspl],2))/nspl + sobolSiT[idim-1] = vari/(2.0*vv1); + if verb > 1: + print " - parameter ",idim,": ",sobolSiT[idim-1] + if verb > 0: + print " - total main sensitivity: ",npy.sum(sobolSiT) + return sobolSiT + +def genSpl_SiTcust(nspl,ndim,abrng,collst,**kwargs): + # get optional arguments + splout = kwargs.get('splout', "gsaSplSiT.dat") # samples file + verb = kwargs.get('verb', 0) # verbosity + nd = kwargs.get('nd', 18) # no. of significant digits in samples output + if (nd<6) or (nd>18): + raise ValueError("Number of digits should be between 6 and 18") + #------------------------------------------------------------------------------------ + # create nspl uniform samples in [a_i,b_i], i=1,ndim + #------------------------------------------------------------------------------------ + if verb>0: + print "Create ensemble of input parameters" + mat1=npy.random.random_sample((nspl,ndim)) + mat2=npy.random.random_sample((nspl,ndim)) + for i in range(ndim): + mat1[:,i] = mat1[:,i]*(abrng[i,1]-abrng[i,0])+abrng[i,0] + mat2[:,i] = mat2[:,i]*(abrng[i,1]-abrng[i,0])+abrng[i,0] + # assemble the big matrix for main sensitivities + if os.path.isfile(splout): + os.remove(splout) + f_handle = file(splout, 'a') + npy.savetxt(f_handle, mat1, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + for j in collst: + print j + matj = mat1.copy() + matj[:,j] = mat2[:,j].copy() + npy.savetxt(f_handle, matj, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + f_handle.close() + return + +def genSens_SiTcust(modeval,ndim,collst,**kwargs): + # get optional arguments + verb = kwargs.get('verb', 0) # verbosity + siTmethod = kwargs.get('type', 'type1') # sampling method + #------------------------------------------------------------------------------------ + # load model evaluations and compute main sensitivities + #------------------------------------------------------------------------------------ + ymod = npy.genfromtxt(modeval) + nspl = ymod.shape[0]/(1+len(collst)) + print nspl + if verb > 0: + print "Compute sensitivities, no. of samples:",nspl + sobolSiT = npy.zeros(len(collst)) + yMat1 = ymod[:nspl] + Ey = npy.average(yMat1) + vv1 = npy.var(yMat1,ddof=1) + for j in range(len(collst)): + print j,collst[j] + if (siTmethod == "type1"): + ssqrs=0.0 + for i in range(nspl): + ssqrs = ssqrs+yMat1[i]*ymod[(j+1)*nspl+i] + vari = ssqrs/(nspl-1.0) + sobolSiT[j] = 1.0-(vari-Ey**2)/(vv1); + else: + vari = npy.sum(npy.power(yMat1-ymod[(j+1)*nspl:(j+2)*nspl],2))/nspl + sobolSiT[j] = vari/(2.0*vv1); + if verb > 0: + print " - total sensitivities: ",sobolSiT + return sobolSiT + +def genSpl_Sij(ndim,**kwargs): + # get optional arguments + splout = kwargs.get('splout', "gsaSplSij.dat") # samples file + matfile = kwargs.get('matfile', "mat12.npz") # intermediary matrices + verb = kwargs.get('verb', 0) # verbosity + nd = kwargs.get('nd', 18) # no. of significant digits in samples output + if verb > 0: + print "Load intermediary matrices of input parameters" + if os.path.isfile(matfile): + m12=npy.load(matfile) + else: + raise IOError("Could not load samples") + quit() + mat1=m12["mat1"] + mat2=m12["mat2"] + # assemble the big matrix for main sensitivities + if os.path.isfile(splout): + os.remove(splout) + f_handle = file(splout, 'a') + npy.savetxt(f_handle, mat1, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + for idim in range(ndim-1): + for jdim in range(idim+1,ndim): + if verb>1: + print " - working on pair ",idim,jdim + matj=mat2.copy(); + matj[:,idim]=mat1[:,idim] + matj[:,jdim]=mat1[:,jdim] + npy.savetxt(f_handle, matj, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + npy.savetxt(f_handle, mat2, fmt="%."+str(nd)+"e", delimiter=' ', newline='\n') + f_handle.close() + return + +def genSens_Sij(sobolSi,modeval,**kwargs): + # get optional arguments + verb = kwargs.get('verb', 0) # verbosity + #------------------------------------------------------------------------------------ + # joint sensitivities + #------------------------------------------------------------------------------------ + ndim = len(sobolSi) + ymod = npy.genfromtxt(modeval) + nspl = ymod.shape[0]/(ndim*(ndim-1)/2+2) + if verb > 0: + print "No. of samples, no. of dimensions:",nspl,ndim + sobolSij = npy.array(npy.zeros((ndim,ndim))) + yMat1 = ymod[:nspl] + yMat2 = ymod[nspl*(ndim*(ndim-1)/2+1):] + mean12 = npy.mean(yMat1*yMat2) + vv1 = npy.var(yMat1,ddof=1) + ijd = 0 + for idim in range(1,ndim): + for jdim in range(idim+1,ndim+1): + ijd += 1; + vari = npy.sum(yMat1*ymod[ijd*nspl:(ijd+1)*nspl]) + sobolSij[idim-1,jdim-1] = (vari/(nspl-1.0)-mean12)/vv1-sobolSi[idim-1]-sobolSi[jdim-1] + if verb > 1: + print " - pair ",idim,jdim,": ",sobolSij[idim-1,jdim-1] + if verb > 0: + print " - total Sij: ",npy.sum(sobolSij[:,:]) + return sobolSij + + + + diff --git a/PyUQTk/sens/gsatest.py b/PyUQTk/sens/gsatest.py new file mode 100644 index 00000000..81b850ff --- /dev/null +++ b/PyUQTk/sens/gsatest.py @@ -0,0 +1,194 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +try: + import numpy as npy +except ImportError: + print "gsalib requires numpy package -> Exit" + quit() + +try: + import matplotlib + foundMPL = True +except ImportError: + foundMPL = False + +import os +from gsalib import genSpl_Si, genSens_Si, genSpl_Sij, genSens_Sij, genSpl_SiT, genSens_SiT +if foundMPL: + import matplotlib.pyplot as plt + +def func1(x): + return npy.sum(x) + +def func2(x): + f = npy.sum(x) + for i in range(len(x)-1): + f = f+(i+1)*(i+1)*x[i]*x[i+1] + return f + +#-------------------------------------------------------------------------------- +# Setup +#-------------------------------------------------------------------------------- +nruns= 10 +ndim = 4 +nspl = 10000 +abr = npy.zeros((ndim,2)) +abr[:,1]=1.0; abr[0,1]=3.0 + +#-------------------------------------------------------------------------------- +# Theoretical values for Sobol indices +#-------------------------------------------------------------------------------- +Simath=npy.array([0.14908, 0.14908, 0.41411, 0.222699]) +Sijmath=npy.array([0.00552147, 0.00981595, 0.04969339]) +SiTmath=Simath.copy() +for i in range(ndim-1): + SiTmath[i] = SiTmath[i] +Sijmath[i] + SiTmath[i+1] = SiTmath[i+1]+Sijmath[i] + + +#-------------------------------------------------------------------------------- +# First-order and joint Sobol indices +#-------------------------------------------------------------------------------- +runSi=[] +runSij=[] +print "Computing first-order and joint Sobol indices" +for irun in range(nruns): + print " run",irun+1," out of",nruns + # Generate samples for Si + genSpl_Si(nspl,ndim,abr,nd=12) + # Load samples, run model, save model evaluations + gsaens=npy.genfromtxt('gsaSplSi.dat') + modelRuns=npy.array([func2(gsaens[i]) for i in range(gsaens.shape[0])]) + npy.savetxt('modelSi.dat', modelRuns, fmt="%.12e", delimiter=' ', newline='\n') + # Compute first order sensitivity indices + Si=genSens_Si('modelSi.dat',ndim,verb=0) + # Generate samples for Sij + genSpl_Sij(ndim,matfile='mat12.npz',nd=12) + # Load samples, run model, save model evaluations + gsaens=npy.genfromtxt('gsaSplSij.dat') + modelRuns=npy.array([func2(gsaens[i]) for i in range(gsaens.shape[0])]) + npy.savetxt('modelSij.dat', modelRuns, fmt="%.12e", delimiter=' ', newline='\n') + # Compute joint sensitivity indices + Sij=genSens_Sij(Si,'modelSij.dat',verb=0) + runSi.append(Si) + runSij.append(Sij) + + +runSi=npy.array(runSi) +runSij=npy.array(runSij) + +if foundMPL: + width = 0.4 + ind = npy.arange(ndim)+0.5-width/2.0 + fs1 = 24 + # Si + fig=plt.figure(figsize=(8,6)) + ax=fig.add_axes([0.15,0.10,0.8,0.85]) + Simean = npy.array([npy.average(runSi[:,i]) for i in range(ndim)]) + Sistd = npy.array([npy.std(runSi[:,i]) for i in range(ndim)]) + rects1 = ax.bar(ind, Simean, width, color='r', yerr=Sistd,error_kw=dict(linewidth=3, color='b',capsize=5) ) + plt.plot(ind+width/2.0,Simath,'o',ms=8,mfc='k') + ax.set_xlim([0,ndim]) + ax.set_ylim([0,0.5]) + ax.set_ylabel(r'$S_i$',fontsize=fs1) + ax.set_xticks(ind+width/2) + ax.set_yticks([0,0.1,0.2,0.3,0.4,0.5]) + ax.set_yticklabels( ('$0$', '$0.1$', '$0.2$', '$0.3$', '$0.4$', '$0.5$') ,fontsize=fs1-6) + ax.set_xticklabels( ('$x_1$', '$x_2$', '$x_3$', '$x_4$') ,fontsize=fs1) + plt.savefig('gsaspl_Si.pdf') + #plt.show() + # Sij + width = 0.4 + ind = npy.arange(ndim-1)+0.5-width/2.0 + fs1 = 24 + fig=plt.figure(figsize=(8,6)) + ax=fig.add_axes([0.15,0.10,0.8,0.85]) + Simean = npy.array([npy.average(runSij[:,i,i+1]) for i in range(ndim-1)]) + Sistd = npy.array([npy.std(runSij[:,i,i+1]) for i in range(ndim-1)]) + rects1 = ax.bar(ind, Simean, width, color='r', yerr=Sistd,error_kw=dict(linewidth=3, color='b',capsize=5) ) + plt.plot(ind+width/2.0,Sijmath,'o',ms=8,mfc='k') + ax.set_xlim([0,ndim-1]) + ax.set_ylim([0,0.07]) + ax.set_ylabel(r'$S_{ij}$',fontsize=fs1) + ax.set_xticks(ind+width/2) + ax.set_yticks([0,0.02,0.04,0.06]) + ax.set_yticklabels( ('$0$', '$0.02$', '$0.04$', '$0.06$') ,fontsize=fs1-6) + ax.set_xticklabels( ('$(x_1,x_2)$', '$(x_2,x_3)$', '$(x_3,x_4)$') ,fontsize=fs1) + plt.savefig('gsaspl_Sij.pdf') + #plt.show() +else: + # could not find matplotlib, saving Sobol indices to file + npy.savez("gsaSi_Sij.npz",Si=runSi,Sij=runSij) + +#-------------------------------------------------------------------------------- +# Total-order Sobol indices +#-------------------------------------------------------------------------------- +runSiT_1=[] +runSiT_2=[] +print "Computing total-order Sobol indices" +for irun in range(nruns): + print " run",irun+1," out of",nruns + # Generate samples for SiT + genSpl_SiT(nspl,ndim,abr,nd=12) + # Load samples, run model, save model evaluations + gsaens=npy.genfromtxt('gsaSplSiT.dat') + modelRuns=npy.array([func2(gsaens[i]) for i in range(gsaens.shape[0])]) + npy.savetxt('modelSiT.dat', modelRuns, fmt="%.12e", delimiter=' ', newline='\n') + # Compute total sensitivity indices + runSiT_1.append(genSens_SiT('modelSiT.dat',ndim,type='type1',verb=0)) + runSiT_2.append(genSens_SiT('modelSiT.dat',ndim,type='type2',verb=0)) + +runSiT_1=npy.array(runSiT_1) +runSiT_2=npy.array(runSiT_2) + +if foundMPL: + width = 0.4 + ind = npy.arange(ndim)+0.5-width/2.0 + fs1 = 24 + # SiT + fig=plt.figure(figsize=(8,6)) + ax=fig.add_axes([0.15,0.10,0.8,0.85]) + SiT1mn = npy.array([npy.average(runSiT_1[:,i]) for i in range(ndim)]) + SiT1std = npy.array([npy.std(runSiT_1[:,i]) for i in range(ndim)]) + rects1 = ax.bar(ind, SiT1mn, width/2.0, color='r', yerr=SiT1std,error_kw=dict(linewidth=3, color='b',capsize=5),label="Est.1") + SiT2mn = npy.array([npy.average(runSiT_2[:,i]) for i in range(ndim)]) + SiT2std = npy.array([npy.std(runSiT_2[:,i]) for i in range(ndim)]) + rects2 = ax.bar(ind+width/2.0, SiT2mn, width/2.0, color='y', yerr=SiT2std,error_kw=dict(linewidth=3, color='b',capsize=5),label="Est.2") + plt.plot(ind+width/2.0,SiTmath,'o',ms=8,mfc='k',label="Exact") + ax.set_xlim([0,ndim]) + ax.set_ylim([0,0.55]) + ax.set_ylabel(r'$S_i^T$',fontsize=fs1) + ax.set_xticks(ind+width/2) + ax.set_yticks([0,0.1,0.2,0.3,0.4,0.5]) + ax.set_yticklabels( ('$0$', '$0.1$', '$0.2$', '$0.3$', '$0.4$', '$0.5$') ,fontsize=fs1-6) + ax.set_xticklabels( ('$x_1$', '$x_2$', '$x_3$', '$x_4$'),fontsize=fs1) + plt.legend(loc=2,prop={'size':fs1}) + plt.savefig('gsaspl_SiT.pdf') + #plt.show() +else: + # could not find matplotlib, saving Sobol indices to file + npy.savez("gsaSiT.npz",SiT1=runSiT_1,SiT2=runSiT_2) diff --git a/PyUQTk/tools/CMakeLists.txt b/PyUQTk/tools/CMakeLists.txt new file mode 100644 index 00000000..75bb4056 --- /dev/null +++ b/PyUQTk/tools/CMakeLists.txt @@ -0,0 +1,57 @@ +enable_language(Fortran) + +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}/../../Extras/lib/python/numpy/core/include) + +#include source files +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/) # array classes, array input output, and array tools +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/include/) # utilities like error handlers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/) # tools like multindex, etc. + +# include dependencies +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/blas/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lapack/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/dsfmt/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/figtree/) # blas library headers +# INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../numpy/) # numpy headers + +SET(CMAKE_SWIG_FLAGS "") +SET_SOURCE_FILES_PROPERTIES(tools.i PROPERTIES CPLUSPLUS ON) + +# compile swig with cpp extensions +SWIG_ADD_MODULE( + tools python tools.i + # array tools needed to compile misc tools source files + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arrayio.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arraytools.cpp + + # source code for tools + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/combin.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/gq.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/minmax.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/multiindex.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/pcmaps.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/probability.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/rosenblatt.cpp + + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/tools/toolsf.f +) + +# link python and 3rd party libraries, e.g., gfortran and blas +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + SWIG_LINK_LIBRARIES(tools uqtkarray deplapack depdsfmt depblas depfigtree depann gfortran ${PYTHON_LIBRARIES}) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + SWIG_LINK_LIBRARIES(tools uqtkarray deplapack depdsfmt depblas depfigtree depann ifcore ${PYTHON_LIBRARIES}) +endif() + + +INSTALL(TARGETS _tools DESTINATION PyUQTk/) +INSTALL(FILES ${CMAKE_BINARY_DIR}/${outdir}PyUQTk/tools/tools.py DESTINATION PyUQTk) diff --git a/PyUQTk/tools/tools.i b/PyUQTk/tools/tools.i new file mode 100644 index 00000000..1dc3dc0d --- /dev/null +++ b/PyUQTk/tools/tools.i @@ -0,0 +1,125 @@ +%module(directors="1") tools +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== + +%{ +#define SWIG_FILE_WITH_INIT +#include +#include +#include +#include +#include +// #include "../../cpp/lib/array/Array1D.h" +// #include "../../cpp/lib/array/Array2D.h" +// #include "../../cpp/lib/array/arrayio.h" +// #include "../../cpp/lib/array/arraytools.h" +#include "../../cpp/lib/tools/combin.h" +#include "../../cpp/lib/tools/gq.h" +#include "../../cpp/lib/tools/minmax.h" +#include "../../cpp/lib/tools/multiindex.h" +#include "../../cpp/lib/tools/pcmaps.h" +#include "../../cpp/lib/tools/probability.h" +#include "../../cpp/lib/tools/rosenblatt.h" +%} + +/************************************************************* +// Standard SWIG Templates +*************************************************************/ + +// Include standard SWIG templates +// Numpy array templates and wrapping +%include "pyabc.i" +%include "../numpy/numpy.i" +%include "std_vector.i" +%include "std_string.i" +%include "cpointer.i" + +%init %{ + import_array(); +%} + +%pointer_functions(double, doublep); + +/************************************************************* +// Numpy SWIG Interface files +*************************************************************/ + +// // Basic typemap for an Arrays and its length. +// // Must come before %include statement below + +// // For Array1D setnumpyarray4py function +// %apply (long* IN_ARRAY1, int DIM1) {(long* inarray, int n)} +// %apply (double* IN_ARRAY1, int DIM1) {(double* inarray, int n)} +// // get numpy int and double array +// %apply (long* INPLACE_ARRAY1, int DIM1) {(long* outarray, int n)} +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* outarray, int n)} + +// // For Array2D numpysetarray4py function +// %apply (double* IN_FARRAY2, int DIM1, int DIM2) {(double* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (double* INPLACE_FARRAY2, int DIM1, int DIM2) {(double* outarray, int n1, int n2)} +// // For Array2D numpysetarray4py function +// %apply (long* IN_FARRAY2, int DIM1, int DIM2) {(long* inarray, int n1, int n2)} +// // get numpy array (must be FARRAY) +// %apply (long* INPLACE_FARRAY2, int DIM1, int DIM2) {(long* outarray, int n1, int n2)} + + +// // For mcmc test to get log probabilities +// %apply (double* INPLACE_ARRAY1, int DIM1) {(double* l, int n)} + +/************************************************************* +// Include header files +*************************************************************/ + +// // The above typemap is applied to header files below +// %include "../../cpp/lib/array/Array1D.h" +// %include "../../cpp/lib/array/Array2D.h" +// %include "../../cpp/lib/array/arrayio.h" +// %include "../../cpp/lib/array/arraytools.h" +%include "../../cpp/lib/tools/combin.h" +%include "../../cpp/lib/tools/gq.h" +%include "../../cpp/lib/tools/minmax.h" +%include "../../cpp/lib/tools/multiindex.h" +%include "../../cpp/lib/tools/pcmaps.h" +%include "../../cpp/lib/tools/probability.h" +%include "../../cpp/lib/tools/rosenblatt.h" + +// // Typemaps for standard vector +// // Needed to prevent to memory leak due to lack of destructor +// // must use namespace std +// namespace std{ +// %template(dblVector) vector; +// %template(intVector) vector; +// %template(strVector) vector; + +// } + + +// %include "swigi/arrayext.i" + + + diff --git a/PyUQTk/uqtkarray/CMakeLists.txt b/PyUQTk/uqtkarray/CMakeLists.txt new file mode 100644 index 00000000..f9c6495a --- /dev/null +++ b/PyUQTk/uqtkarray/CMakeLists.txt @@ -0,0 +1,39 @@ +FIND_PACKAGE(SWIG REQUIRED) +INCLUDE(${SWIG_USE_FILE}) + +FIND_PACKAGE(PythonLibs) +INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIR}/../../Extras/lib/python/numpy/core/include) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/) # array classes, array input output, and array tools +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/include/) # utilities like error handlers + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/blas/) # blas library headers +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../dep/lapack/) # blas library headers +# INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../numpy/) # numpy headers + +SET(CMAKE_SWIG_FLAGS "") +SET_SOURCE_FILES_PROPERTIES(uqtkarray.i PROPERTIES CPLUSPLUS ON) + +# compile swig with cpp extensions +SWIG_ADD_MODULE(uqtkarray python uqtkarray.i + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arrayio.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp/lib/array/arraytools.cpp +) + +# link python and 3rd party libraries, e.g., gfortran and blas +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + SWIG_LINK_LIBRARIES(uqtkarray deplapack depblas gfortran ${PYTHON_LIBRARIES}) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + SWIG_LINK_LIBRARIES(uqtkarray deplapack depblas ifcore ${PYTHON_LIBRARIES}) +endif() + + +INSTALL(TARGETS _uqtkarray DESTINATION PyUQTk/) +INSTALL(FILES ${CMAKE_BINARY_DIR}/${outdir}PyUQTk/uqtkarray/uqtkarray.py + DESTINATION PyUQTk) diff --git a/PyUQTk/uqtkarray/arrayext.i b/PyUQTk/uqtkarray/arrayext.i new file mode 100644 index 00000000..44143e8b --- /dev/null +++ b/PyUQTk/uqtkarray/arrayext.i @@ -0,0 +1,409 @@ +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== +/************************************************************* +// Templates for Array1D and 2D types +*************************************************************/ +%template(intArray1D) Array1D; +%template(dblArray1D) Array1D; +%template(strArray1D) Array1D; +%template(intArray2D) Array2D; +%template(dblArray2D) Array2D; + +/************************************************************* +// Extend Array1D class for easy python use +*************************************************************/ + +// Array 1D +%define Array1DExtend(name, T) +%extend name{ + T __getitem__(int index) { + return (*self)[index]; + } + Array1D __getitem__(PyObject *slice) { + Py_ssize_t start, stop, step; + Py_ssize_t length = (*self).Length(); + Py_ssize_t slicelength; + PySlice_GetIndicesEx((PySliceObject*)slice,length,&start,&stop,&step,&slicelength); + + Array1D vnew(slicelength); + int place = 0; + for (int i = start; i < stop; i=i+step){ + vnew(place) = (*self)[i]; + place += 1; + } + return vnew; + } + int __len__(){ + return (*self).Length(); + } + void __setitem__(int i, T j){ + (*self)[i] = j; + } + void __setitem__(vector index, vector vin){ + // multiple index items to in vector at one time + // In python, both index and in must be lists + for (int i = 0; i < index.size(); i++){ + (*self)[index[i]] = vin[i]; + } + } + Array1D __mul__(T a){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = a*(*self)[i]; + } + return newArray; + } + Array1D __rmul__(T a){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = a*(*self)[i]; + } + return newArray; + } + Array1D __add__(Array1D y){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = (*self)[i] + y[i]; + } + return newArray; + } + Array1D __add__(T y){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = (*self)[i] + y; + } + return newArray; + } + Array1D __sub__(Array1D y){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = (*self)[i] - y[i]; + } + return newArray; + } + Array1D __div__(Array1D y){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = (*self)[i]/y[i]; + } + return newArray; + } + Array1D __pow__(double p){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = pow((*self)[i],p); + } + return newArray; + } + Array1D copy(){ + int l = (*self).Length(); + Array1D newArray(l,0); + for (int i = 0; i < l; i++){ + newArray[i] = (*self)[i]; + } + return newArray; + } + string __repr__(){ + stringstream ss; + // print contents of array as strings + int l = (*self).Length(); + ss << "Array1D<" << (*self).type() << ">("; + ss << (*self).Length() << ")" << endl; + int imax = 10; + + ss << "["; + for (int i = 0; i < l-1; i++){ + // ss << setw(8) << (*self)[i] << ", "; + ss << (*self)[i] << ", "; + if (i == imax){ + ss << "..., "; + break; + } + } + int m = min(4,l-imax); + if (l >= imax){ + for (int i = l-m+1; i < l-1; i++){ + ss << (*self)[i] << ", "; + } + } + if (l > 0){ss << (*self)[l-1];} + ss << "]"; + + return ss.str(); + } + vector shape(){ + vector s(1,0); + s[0] = (*self).XSize(); + return s; + } + + +} +%enddef + +// Array 1D +%define Array1DStrExtend(name, T) +%extend name{ + T __getitem__(int index) { + return (*self)[index]; + } + int __len__(){ + return (*self).Length(); + } + void __setitem__(int i, T j){ + (*self)[i] = j; + } + void __setitem__(vector index, vector vin){ + // multiple index items to in vector at one time + // In python, both index and in must be lists + for (int i = 0; i < index.size(); i++){ + (*self)[index[i]] = vin[i]; + } + } + Array1D copy(){ + int l = (*self).Length(); + Array1D newArray(l); + for (int i = 0; i < l; i++){ + newArray[i] = (*self)[i]; + } + return newArray; + } + string __repr__(){ + stringstream ss; + // print contents of array as strings + int l = (*self).Length(); + ss << "Array1D<" << (*self).type() << ">("; + ss << (*self).Length() << ")" << endl; + int imax = 10; + + ss << "["; + for (int i = 0; i < l-1; i++){ + ss << (*self)[i] << ", "; + if (i == imax){ + ss << "..., "; + break; + } + } + int m = min(4,l-imax); + if (l >= imax){ + for (int i = l-m+1; i < l-1; i++){ + ss << (*self)[i] << ", "; + } + } + if (l > 0){ss << (*self)[l-1];} + ss << "]"; + + return ss.str(); + } + vector shape(){ + vector s(1,0); + s[0] = (*self).XSize(); + return s; + } +} +%enddef + +Array1DExtend(Array1D, int); +Array1DExtend(Array1D, double); +Array1DStrExtend(Array1D, string); + +/************************************************************* +// Extend Array2D classes for easy python use +*************************************************************/ + +// Array2D +%define Array2DExtend(name, T) +%extend name{ + T __getitem__(vector v) { + return (*self)[v[0]][v[1]]; + } + Array2D __getitem__(PyObject *slices){ + PyObject* slice1; + PyObject* slice2; + slice1 = PyTuple_GetItem(slices, 0); + slice2 = PyTuple_GetItem(slices, 1); + PySliceObject *s1 = (PySliceObject*)slice1; // recast pointer to proper type + PySliceObject *s2 = (PySliceObject*)slice2; // recast pointer to proper type + + Py_ssize_t start1 = 0, stop1 = 0, step1 = 0, slicelength1 = 0; + Py_ssize_t start2 = 0, stop2 = 0, step2 = 0, slicelength2 = 0; + Py_ssize_t len1 = (*self).XSize(); + Py_ssize_t len2 = (*self).YSize(); + PySlice_GetIndicesEx(s1,len1,&start1,&stop1,&step1,&slicelength1); + PySlice_GetIndicesEx(s2,len2,&start2,&stop2,&step2,&slicelength2); + + Array2D vnew(slicelength1,slicelength2); + int p1 = 0, p2 = 0; + for (int i=start1; i __getitem__(int row) { + (*self).getRow(row); + return (*self).arraycopy; + } + int __len__(){ + return (*self).XSize(); + } + void __setitem__(vector v, T j){ + (*self)(v[0],v[1]) = j; + } + vector shape(){ + vector s(2,0); + s[0] = (*self).XSize(); + s[1] = (*self).YSize(); + return s; + } + string __repr__(){ + stringstream ss; + stringstream sstemp; + // print contents of array as strings + int lx = (*self).XSize(); + int ly = (*self).YSize(); + ss << "Array2D<" << (*self).type() << ">("; + ss << lx << ", "; + ss << ly << ")" << endl; + + //find # digits for number of rows, lx + int digits = 1, pten=10; + while ( pten <= lx ) { digits++; pten*=10; } + + // find max width (number of digits) for printing + double test = 0.0; + int w0 = 1, w1 = 1; + for (int k = 0; k < lx*ly; k++){ + test = (*self).data_[k]; + sstemp.str(""); + sstemp << test; + w1 = sstemp.str().length(); + w0 = max(w0,w1); + } + int w = w0; + + // size of columns for printing, dependent on width + int imax, jmax; + if (w >= 8){ + imax = 10; + jmax = 8-1; + } + else if (w < 8){ + imax = 10; + jmax = 12-1; + } + + // print array + for (int i = 0; i < lx; i++){ + // print row number + ss << "[" << setw(digits) << i; + ss << "] "; + ss << setw(2) << "["; + for (int j=0; j= jmax){ + for (int j=ly-m+1; j 1){ + ss << setw(w) << (*self)[i][ly-1] << "]"; + } + //print only if # of columns is 1 + else if (ly == 1){ + ss << setw(w) << (*self)[i][ly-1] << "]"; + } + if (i == imax){ + ss << "\n"; + ss << setw(w) << "...," << endl; + break; + } + ss << "\n"; + } + + // print last 4 rows + int mx = min(4,lx-imax); + if (lx >= imax){ + for (int i = lx-mx+1; i < lx; i++){ + ss << "[" << setw(digits) << i; + ss << "] "; + ss << setw(2) << "["; + for (int j=0; j= jmax){ + for (int j=ly-m+1; j 1){ + ss << setw(w) << (*self)[i][ly-1] << "]"; + } + else if (ly == 1){ + ss << setw(w) << (*self)[i][ly-1] << "]"; + } + ss << "\n"; + } + } + + return ss.str(); + } +} +%enddef + +Array2DExtend(Array2D, int); +Array2DExtend(Array2D, double); + diff --git a/PyUQTk/uqtkarray/uqtkarray.i b/PyUQTk/uqtkarray/uqtkarray.i new file mode 100644 index 00000000..bb735105 --- /dev/null +++ b/PyUQTk/uqtkarray/uqtkarray.i @@ -0,0 +1,163 @@ +%module(directors="1") uqtkarray +//===================================================================================== +// The UQ Toolkit (UQTk) version 3.0.4 +// Copyright (2017) Sandia Corporation +// http://www.sandia.gov/UQToolkit/ +// +// Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +// with Sandia Corporation, the U.S. Government retains certain rights in this software. +// +// This file is part of The UQ Toolkit (UQTk) +// +// UQTk 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 3 of the License, or +// (at your option) any later version. +// +// UQTk 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 UQTk. If not, see . +// +// Questions? Contact Bert Debusschere +// Sandia National Laboratories, Livermore, CA, USA +//===================================================================================== + +%feature("autodoc", "3"); +%rename(Assign) *::operator=; +%ignore *::operator[]; + +%{ +#define SWIG_FILE_WITH_INIT +#include +#include +#include +#include +#include +#include "../../cpp/lib/array/Array1D.h" +#include "../../cpp/lib/array/Array2D.h" +#include "../../cpp/lib/array/arrayio.h" +#include "../../cpp/lib/array/arraytools.h" +%} + +/************************************************************* +// Standard SWIG Templates +*************************************************************/ + +// Include standard SWIG templates +// Numpy array templates and wrapping +%include "pyabc.i" +%include "../numpy/numpy.i" +%include "std_vector.i" +%include "std_string.i" +%include "cpointer.i" + +%init %{ + import_array(); +%} + +%pointer_functions(double, doublep); + + +/************************************************************* +// Numpy SWIG Interface files +*************************************************************/ + +// Basic typemap for an Arrays and its length. +// Must come before %include statement below + +// For Array1D setnumpyarray4py function +%apply (long* IN_ARRAY1, int DIM1) {(long* inarray, int n)} +%apply (double* IN_ARRAY1, int DIM1) {(double* inarray, int n)} +// get numpy int and double array +%apply (long* INPLACE_ARRAY1, int DIM1) {(long* outarray, int n)} +%apply (double* INPLACE_ARRAY1, int DIM1) {(double* outarray, int n)} + +// For Array2D numpysetarray4py function +%apply (double* IN_FARRAY2, int DIM1, int DIM2) {(double* inarray, int n1, int n2)} +// get numpy array (must be FARRAY) +%apply (double* INPLACE_FARRAY2, int DIM1, int DIM2) {(double* outarray, int n1, int n2)} +// For Array2D numpysetarray4py function +%apply (long* IN_FARRAY2, int DIM1, int DIM2) {(long* inarray, int n1, int n2)} +// get numpy array (must be FARRAY) +%apply (long* INPLACE_FARRAY2, int DIM1, int DIM2) {(long* outarray, int n1, int n2)} + + +// For mcmc test to get log probabilities +%apply (double* INPLACE_ARRAY1, int DIM1) {(double* l, int n)} + +/************************************************************* +// Include header files +*************************************************************/ + +// // The above typemap is applied to header files below +%include "../../cpp/lib/array/Array1D.h" +%include "../../cpp/lib/array/Array2D.h" +%include "../../cpp/lib/array/arrayio.h" +%include "../../cpp/lib/array/arraytools.h" + +// Typemaps for standard vector +// Needed to prevent to memory leak due to lack of destructor +// must use namespace std +namespace std{ + %template(dblVector) vector; + %template(intVector) vector; + %template(strVector) vector; + +} + +%template(subMatrix_row_int) subMatrix_row; +%template(subMatrix_row_dbl) subMatrix_row; + +%include "arrayext.i" + +%pythoncode %{ +import numpy as np +def uqtk2numpy(x): + if x.type() == 'int': + s = x.shape() + imin = np.argmin(s) + if len(s) == 1: + n = s[0] + y = np.zeros(n,dtype='int64') + x.getnpintArray(y) + if len(s) == 2 and np.amin(s) > 1: + n = s[0] + m = s[1] + y = np.zeros((n,m),dtype='int64') + x.getnpintArray(y) + if len(s) == 2 and np.amin(s) == 1: + y = np.array(x.flatten()) + return y.copy() + else: + s = x.shape() + imin = np.argmin(s) + if len(s) == 1: + n = s[0] + y = np.zeros(n) + x.getnpdblArray(y) + if len(s) == 2 and np.amin(s) > 1: + n = s[0] + m = s[1] + y = np.zeros((n,m)) + x.getnpdblArray(y) + if len(s) == 2 and np.amin(s) == 1: + y = np.array(x.flatten()) + return y.copy() + +def numpy2uqtk(y): + s = np.shape(y) + if len(s) == 1: + n = s[0] + x = dblArray1D(n) + if len(s) == 2: + n = s[0] + m = s[1] + x = dblArray2D(n,m) + x.setnpdblArray(np.asfortranarray(y.copy())) + return x +%} + diff --git a/PyUQTk/utils/CMakeLists.txt b/PyUQTk/utils/CMakeLists.txt new file mode 100644 index 00000000..7e771573 --- /dev/null +++ b/PyUQTk/utils/CMakeLists.txt @@ -0,0 +1,15 @@ +project (UQTk) + +SET(copy_FILES + __init__.py + colors.py + crps.py + pdf_kde.py + multiindex.py + regr.py + func.py + ) + +INSTALL(FILES ${copy_FILES} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + DESTINATION PyUQTk/utils) diff --git a/PyUQTk/utils/__init__.py b/PyUQTk/utils/__init__.py new file mode 100755 index 00000000..3da35896 --- /dev/null +++ b/PyUQTk/utils/__init__.py @@ -0,0 +1,32 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== +import colors +import crps +import pdf_kde +import multiindex +import regr +import func diff --git a/PyUQTk/utils/colors.py b/PyUQTk/utils/colors.py new file mode 100644 index 00000000..0434bd50 --- /dev/null +++ b/PyUQTk/utils/colors.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +""" +Utilities for defining color lists. +Note that Python has standards as well; this is an alternative +that often produces enough variability in colors for eye-pleasing results. +""" + +try: + import numpy as np +except ImportError: + print "Numpy was not found. " + + + +def set_colors(npar): + """ Sets a list of different colors of requested length, as rgb triples""" + colors = [] + pp=1+npar/6 + for i in range(npar): + c=1-(float) (i/6)/pp + b=np.empty((3)) + for jj in range(3): + b[jj]=c*int(i%3==jj) + a=int(i%6)/3 + colors.append(((1-a)*b[2]+a*(c-b[2]),(1-a)*b[1]+a*(c-b[1]),(1-a)*b[0]+a*(c-b[0]))) + + return colors + diff --git a/PyUQTk/utils/crps.py b/PyUQTk/utils/crps.py new file mode 100644 index 00000000..7848449a --- /dev/null +++ b/PyUQTk/utils/crps.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +try: + import numpy as npy +except ImportError: + print "Numpy was not found. " + +def CRPSinteg(s1,s2): + """ Computes integral of squared difference between two CDFs """ + Ns1 = s1.shape[0]; + Ns2 = s2.shape[0]; + ds1 = 1.0/Ns1; + ds2 = 1.0/Ns2; + # Combine samples and sort + s12=npy.sort(npy.concatenate((s1,s2))); + CRPS = 0.0; + j1 = 0; + j2 = 0; + for i in range(Ns1+Ns2-1): + if s12[i+1] <= s1[0]: + fs1 = 0.0; + elif s12[i] >= s1[Ns1-1]: + fs1 = 1.0; + else: + j1 = j1+npy.argmax(s1[j1:]>s12[i])-1 + fs1 = (j1+1)*ds1; + if s12[i+1] <= s2[0]: + fs2 = 0.0; + elif s12[i] >= s2[Ns2-1]: + fs2 = 1.0; + else: + j2 = j2+npy.argmax(s2[j2:]>s12[i])-1 + fs2 = (j2+1)*ds2; + CRPS = CRPS + (s12[i+1]-s12[i])*(fs1-fs2)**2; + return CRPS + +def CRPS(s1,s2): + """ Computes CRPS score """ + nsamples = s1.shape[0] + if nsamples != s2.shape[0]: + print "The number of realizations in s1 and s2 is not the same:",nsamples,s2.shape[0] + return (-1.0); + crps = npy.zeros(nsamples) + for i in range(nsamples): + crps[i] = CRPSinteg(s1[i],s2[i]) + return crps.mean() diff --git a/PyUQTk/utils/func.py b/PyUQTk/utils/func.py new file mode 100755 index 00000000..172f5698 --- /dev/null +++ b/PyUQTk/utils/func.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +""" +Generic tools for evaluation of standard functions +and their integrals +""" + +try: + import numpy as np +except ImportError: + "Need numpy" + +import sys +from math import * +import random as rnd +import itertools + +################################################################################################### + + +def func(xdata,model,func_params): + """Generic function evaluator. + Note: + * Currently only genz functions are implemented. + * Note that conventional Genz arguments are in [0,1], here the expected input is on [-1,1] + Arguments: + * xdata : Nxd numpy array of input, should be in [-1,1]^d + * model : Model name, options are 'genz_osc', 'genz_exp', 'genz_cont', 'genz_gaus', 'genz_cpeak', 'genz_ppeak' + * func_params : Auxiliary parameters + : For genz functions, an array of size d+1, the first entry being the shift, and the rest of the entries are the weights. + : See UQTk Manual for Genz formulae. + Returns: + * ydata : An array of outputs of size N. + """ + + # Get the input size + sam=xdata.shape[0] + dim=xdata.shape[1] + + # Check the function types and evaluate + if model == 'genz_osc': + xdata=0.5*(xdata+1.) + ydata=np.empty((sam,)) + gcf=func_params[1:] + xtmp=np.dot(xdata,gcf) + for j in range(sam): + ydata[j]=cos(2.*pi*func_params[0]+xtmp[j]) + + elif model == 'genz_exp': + xdata=0.5*(xdata+1.) + ydata=np.empty((sam,)) + ww=func_params[0] + gcf=func_params[1:] + + xtmp=np.dot(xdata-ww,gcf) + for j in range(sam): + ydata[j]=exp(xtmp[j]) + + elif model == 'genz_cont': + xdata=0.5*(xdata+1.) + ydata=np.empty((sam,)) + ww=func_params[0] + gcf=func_params[1:] + + xtmp=np.dot(abs(xdata-ww),gcf) + for j in range(sam): + ydata[j]=exp(-xtmp[j]) + + elif model == 'genz_gaus': + xdata=0.5*(xdata+1.) + ydata=np.empty((sam,)) + ww=func_params[0] + gcf=func_params[1:] + + xtmp=np.dot((xdata-ww)*(xdata-ww),gcf*gcf) + for j in range(sam): + ydata[j]=exp(-xtmp[j]) + + elif model == 'genz_cpeak': + xdata=0.5*(xdata+1.) + ydata=np.empty((sam,)) + #ww=param[0] + gcf=func_params[1:] + + xtmp=1.+(np.dot(xdata,gcf)) #use abs if defined on [-1,1] + for j in range(sam): + ydata[j]=exp(-(dim+1.)*log(xtmp[j])) + + elif model == 'genz_ppeak': + xdata=0.5*(xdata+1.) + ydata=np.empty((sam,)) + ww=func_params[0] + gcf=func_params[1:] + + for j in range(sam): + prod=1. + for i in range(dim): + prod = prod / (1./(gcf[i]**2.)+(xdata[j,i]-ww)**2.) + ydata[j]=prod + + elif model == 'ishigami': + assert(dim==3) + a=func_params[0] + b=func_params[1] + ydata=np.empty((sam,)) + + for j in range(sam): + ydata[j]=np.sin(xdata[j,0])+a*np.sin(xdata[j,1])**2+b*np.sin(xdata[j,0])*xdata[j,2]**4 + + elif model == 'sobol': + assert(dim==func_params.shape[0]) + ydata=np.empty((sam,)) + for j in range(sam): + val=1. + for k in range(dim): + val *= ( (abs(2*xdata[j,k])+func_params[k])/(1.+func_params[k]) ) + ydata[j]=val + + elif model == 'poly_exsens': + assert(dim==func_params[0]) + ydata=np.empty((sam,)) + for j in range(sam): + val=1. + for k in range(dim): + val *= ( (3./4.)*(xdata[j,k]+1.)**2+1. )/2. + ydata[j]=val + + return ydata + +################################################################################## + +def integ_exact(model,func_params): + """Analytically available function integrals. + Note: + * Currently only genz functions are implemented. + * Note that conventional Genz arguments are in [0,1], here the expected input is on [-1,1] + Arguments: + * model : Model name, options are 'genz_osc', 'genz_exp', 'genz_cont', 'genz_gaus', 'genz_cpeak', 'genz_ppeak' + * func_params : Auxiliary parameters + : For genz functions, an array of size d+1, the first entry being the shift, and the rest of the entries are the weights. + : See UQTk Manual for Genz integral formulae. + Returns: + * integ_ex : A real number that is the integral over [-1,1]^d + """ + + + if (model=='genz_osc'): + gcf=func_params + dim=gcf.shape[0]-1 + integ_ex=cos(2.*pi*gcf[0]+0.5*sum(gcf[1:])) + for i in range(1,dim+1): + integ_ex*=(2.*sin(gcf[i]/2.)/gcf[i]) + elif (model=='genz_exp'): + gcf=func_params + dim=gcf.shape[0]-1 + integ_ex=1. + for i in range(1,dim+1): + at1=exp(-gcf[i]*gcf[0]) + at2=exp(gcf[i]*(1.-gcf[0])) + integ_ex*=((at2-at1)/(gcf[i])) + elif (model=='genz_cont'): + gcf=func_params + dim=gcf.shape[0]-1 + integ_ex=1. + for i in range(1,dim+1): + integ_ex*= ((2.-exp(gcf[i]*(-gcf[0]))-exp(gcf[i]*(gcf[0]-1.)))/gcf[i]) + elif (model=='genz_gaus'): + gcf=func_params + dim=gcf.shape[0]-1 + integ_ex=1. + for i in range(1,dim+1): + at1=erf(-gcf[i]*gcf[0]) + at2=erf(gcf[i]*(1.-gcf[0])) + integ_ex*=((at2-at1)*sqrt(pi)/(2.*gcf[i])) + elif (model=='genz_cpeak'): + gcf=func_params + dim=gcf.shape[0]-1 + numer=0.0 + count=1 + denom=1. + for i in range(1,dim+1): + comb=list(itertools.combinations(range(1,dim+1),i)) + for j in range(len(comb)): + assert(i==len(comb[j])) + #print i,j,pow(-1,i) + numer+=(pow(-1,i)/(1.+sum(gcf[list(comb[j])]))) + count+=1 + denom*=(i*gcf[i]) + #print count, numer + integ_ex=(1.+numer)/denom + elif (model=='genz_ppeak'): + gcf=func_params + dim=gcf.shape[0]-1 + integ_ex=1. + for i in range(1,dim+1): + at1=np.arctan(-gcf[i]*gcf[0]) + at2=np.arctan(gcf[i]*(1.-gcf[0])) + integ_ex*=(gcf[i]*(at2-at1)) + + return integ_ex + +################################################################################ +################################################################################ + +def mainsens_exact(model,func_params): + """Analytically available main sensitivities for some functions. + Note: + * Currently only sobol, ishigami and poly_exsens functions are implemented. + * Note that conventional sobol arguments are in [0,1], here the expected input is on [-1,1] + Arguments: + * model : Model name, options are 'sobol', 'ishigami', 'poly_exsens' + * func_params : Auxiliary parameters + Returns: + * mainsens : Main effect Sobol sensitivity index + """ + if (model=='sobol'): + dim=func_params.shape[0] + mainsens=np.empty((dim,)) + var=1.0 + for i in range(dim): + mainsens[i]=1./(3.*(1.+func_params[i])**2) + var*=(mainsens[i]+1.) + var-=1.0 + mainsens/=var + + elif (model=='ishigami'): + a=func_params[0] + b=func_params[1] + var=a**2/8.+b*np.pi**4/5.+b**2*np.pi**8/18.+0.5 + mainsens=np.empty((3,)) + mainsens[0]=b*np.pi**4/5.+b**2*np.pi**8/50.+0.5 + mainsens[1]=a**2/8. + mainsens[2]=0.0 + mainsens/=var + + elif (model=='poly_exsens'): + dim=func_params[0] + mainsens=(0.2/(1.2**dim-1))*np.ones((dim,)) + + else: + print "No exact sensitivity available for this function. Exiting." + sys.exit(1) + + + return mainsens + +################################################################################## +################################################################################## + +def main(arg): + modelname=arg[0] + input_file=arg[1] + output_file=arg[2] + auxparam=[] + if len(arg)>3: + auxparam_file=arg[3] + auxparam=np.loadtxt(auxparam_file,ndmin=1) + + input=np.loadtxt(input_file,ndmin=2) + + output=func(input,modelname,auxparam) + np.savetxt(output_file,output) + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/PyUQTk/utils/mindex_order.py b/PyUQTk/utils/mindex_order.py new file mode 100644 index 00000000..3f9944e1 --- /dev/null +++ b/PyUQTk/utils/mindex_order.py @@ -0,0 +1,173 @@ +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +""" +Proof-of-concept functions to play around with several ordering +sequences, e.g. + 1. lexicographical order (lex) + 2. colexicographic order (colex) + 3. reverse lexicographical order (revlex) + 4. reverse colexicographical order (revcolex) +""" + +import os +import sys + +try: + import numpy as npy +except ImportError: + print "Numpy was not found. " + +def sort_lex(a,b): +""" + Indicator function for lexicographical order +""" + n=a.shape[0] + for i in range(n): + if (a[i]>b[i]): + return (1) + elif (b[i]>a[i]): + return (-1) + return(0); + +def sort_colex(a,b): +""" + Indicator function for colexicographical order +""" + n=a.shape[0] + for i in range(n-1,0,-1): + if (a[i]>b[i]): + return (1) + elif (b[i]>a[i]): + return (-1) + return(0); + +def sort_revlex(a,b): +""" + Indicator function for reverse lexicographical order +""" + n=a.shape[0] + for i in range(n): + if (a[i] 0): + #-----------first order terms--------------------------- + for idim in range(ndim): + iup+=1 + mi[iup,idim] = 1; + if (norder > 1): + #-----------higher order terms-------------------------- + for iord in range(2,norder+1): + lessiord = iup; + for idim in range(ndim): + for ii in range(idim+1,ndim): + ic[idim] += ic[ii]; + for idimm in range(ndim): + for ii in range(lessiord-ic[idimm]+1,lessiord+1): + iup+=1 + mi[iup]=mi[ii].copy() + mi[iup,idimm] += 1 + if type == 'lex': + return npc,graded_sorted(mi,sort_lex) + elif type == 'colex': + return npc,graded_sorted(mi,sort_colex) + elif type == 'colex': + return npc,graded_sorted(mi,sort_colex) + elif type == 'colex': + return npc,graded_sorted(mi,sort_colex) + else: + print 'Unknown multi-index order type: ',type + return -1,mi + + + + diff --git a/PyUQTk/utils/multiindex.py b/PyUQTk/utils/multiindex.py new file mode 100755 index 00000000..1513e3a8 --- /dev/null +++ b/PyUQTk/utils/multiindex.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +""" +Scripts for managing multiindices. +""" + +import os +import sys + +try: + import numpy as np +except ImportError: + print "Numpy was not found. " + +############################################################# +############################################################# + +def gen_mi(mi_type,params): + """ + Wrapper around the app gen_mi for generating multiindex sets + Arguments: + * mi_type : Multiindex tpye, options are 'TO', 'TP', 'HDMR' + * params : Parameters, a two-element tuple + : First element is the order ('TO'), list of orders per dimension ('TP'), or list of HDMR orders ('HDMR') + : Second element is dimensionality + Returns: + * mindex : A 2d array of multiindices. + """ + + # Total-Order truncation + if mi_type=='TO': + # Order + nord=params[0] + # Dimensionality + dim=params[1] + # Command for the app + cmd='gen_mi -x' + mi_type + ' -p' + str(nord) + ' -q' + str(dim) + + # Tensor-product truncation + elif mi_type=='TP': + # A list of orders per dimension + orders=params[0] + # Dimensionality + dim=params[1] + assert(dim==len(orders)) + # Save the per-dimension orders in a file + np.savetxt('orders.dat',np.array(orders),fmt='%d') + # Command for the app + cmd='gen_mi -x' + mi_type + ' -f orders.dat -q'+str(dim) + + # HDMR trunction + elif mi_type=='HDMR': + # A list of per-variate orders + hdmr_dims=params[0] + # Dimensionality + dim=params[1] + # Save the HDMR dimensions in a file + np.savetxt('hdmr_dims.dat',np.array(hdmr_dims),fmt='%d') + # Command for the app + cmd='gen_mi -x' + mi_type + ' -f hdmr_dims.dat -q'+str(dim) + + else: + print "Multiindex type is not recognized. Use 'TO', 'TP' or 'HDMR'. Exiting." + sys.exit(1) + + # Run the app + os.system(cmd + ' > gen_mi.out') + + # Load the generated multtindex file + mindex=np.loadtxt('mindex.dat',dtype=int).reshape(-1,dim) + return mindex + + +############################################################# +############################################################# + +def mi_addfront_cons(mindex): + """ + Adding a front to multiindex in a conservative way, i.e. + a multiindex is added only if *all* parents are in the current set + """ + + print "Adding multiindex front (conservative)" + + npc=mindex.shape[0] + ndim=mindex.shape[1] + mindex_f=np.zeros((1,ndim),dtype=int) + mindex_add=np.zeros((1,ndim),dtype=int) + mindex_new=np.zeros((1,ndim),dtype=int) + for i in range(npc): + cur_mi=mindex[i,:] + + fflag=True + for j in range(ndim): + test_mi=np.copy(cur_mi) + test_mi[j] += 1 + #print "Trying test_mi", test_mi + fl=True + + + if not any(np.equal(mindex,test_mi).all(1)): + for k in range(ndim): + if(test_mi[k]!=0): + subt_mi=np.copy(test_mi) + subt_mi[k] -= 1 + + if any(np.equal(mindex,subt_mi).all(1)): + cfl=True + fl=cfl*fl + + else: + fl=False + break + + + if (fl): + if not any(np.equal(mindex_add,test_mi).all(1)): + mindex_add=np.vstack((mindex_add,test_mi)) + if fflag: + mindex_f=np.vstack((mindex_f,cur_mi)) + fflag=False + + mindex_f=mindex_f[1:] + mindex_add=mindex_add[1:] + mindex_new=np.vstack((mindex,mindex_add)) + + print "Multiindex resized from %d to %d." % (mindex.shape[0],mindex_new.shape[0]) + + # Returns the new muliindex, the added new multiindices, + # and the 'front', i.e. multiindices whose children are added + return [mindex_new,mindex_add,mindex_f] + +############################################################# +############################################################# +############################################################# + +def mi_addfront(mindex): + """ + Adding a front to multiindex in a non-conservative way, i.e. + a multiindex is added only if *any* of the parents is in the current set + """ + + print "Adding multiindex front (non-conservative)" + + npc=mindex.shape[0] + ndim=mindex.shape[1] + + mindex_f=np.zeros((1,ndim),dtype=int) + mindex_add=np.zeros((1,ndim),dtype=int) + mindex_new=np.zeros((1,ndim),dtype=int) + for i in range(npc): + cur_mi=mindex[i,:] + + fflag=True + for j in range(ndim): + test_mi=np.copy(cur_mi) + test_mi[j] += 1 + if not any(np.equal(mindex,test_mi).all(1)): + if not any(np.equal(mindex_add,test_mi).all(1)): + mindex_add=np.vstack((mindex_add,test_mi)) + if fflag: + mindex_f=np.vstack((mindex_f,cur_mi)) + fflag=False + + mindex_f=mindex_f[1:] + mindex_add=mindex_add[1:] + mindex_new=np.vstack((mindex,mindex_add)) + + + print "Multiindex resized from %d to %d." % (mindex.shape[0],mindex_new.shape[0]) + + # Returns the new muliindex, the added new multiindices, + # and the 'front', i.e. multiindices whose children are added + return [mindex_new,mindex_add,mindex_f] + + + +##################################################################### diff --git a/PyUQTk/utils/pdf_kde.py b/PyUQTk/utils/pdf_kde.py new file mode 100755 index 00000000..4fac5e3b --- /dev/null +++ b/PyUQTk/utils/pdf_kde.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +""" +KDE PDF computation routines. +""" + +import os +try: + from scipy import stats +except ImportError: + print "Scipy was not found. " + +try: + import numpy as np +except ImportError: + print "Numpy was not found. " + + +############################################################# + +def get_pdf(data,target, method='UQTk',verbose=1): + """ + Compute PDF given data at target points + with Python built-in method or with the UQTk app + + Arguments: + * data : an N x d array of N samples in d dimensions + * target : an M x d array of target points + : can be an integer in method-UQTk case; and is interpreted as + : the number of grid points per dimension for a target grid + * method : 'UQTk' or 'Python' + * verbose: verbosity on the screen, 0,1, or 2 + + Returns: + * xtarget : target points (same as target, or a grid, if target is an integer) + * dens : PDF values at xtarget + """ + np.savetxt('data',data) + + # Wrapper around the UQTk app + if (method=='UQTk'): + + if (verbose>1): + outstr='' + else: + outstr=' > pdfcl.log' + + if(type(target)==int): + cmd='pdf_cl -i data -g '+str(target)+outstr + if (verbose>0): + print "Running ", cmd + os.system(cmd) + + else: + np.savetxt('target',target) + cmd='pdf_cl -i data -x target'+outstr + if (verbose>0): + print "Running ", cmd + + os.system(cmd) + + xtarget=np.loadtxt('dens.dat')[:,:-1] + dens=np.loadtxt('dens.dat')[:,-1] + + # Python Scipy built-in method of KDE + elif (method=='Python'): + assert (type(target)!=int) + np.savetxt('target',target) + + kde_py=stats.kde.gaussian_kde(data.T) + dens=kde_py(target.T) + xtarget=target + + else: + print "KDE computation method is not recognized (choose 'Python' or 'UQTk'). Exiting." + sys.exit() + + # Return the target points and the probability density + return xtarget,dens + diff --git a/PyUQTk/utils/regr.py b/PyUQTk/utils/regr.py new file mode 100755 index 00000000..0413a733 --- /dev/null +++ b/PyUQTk/utils/regr.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +""" +Regression-related tools +""" + +import os +import sys + +try: + import numpy as np +except ImportError: + print "Numpy was not found. " + + +from multiindex import mi_addfront + +############################################################# +############################################################# +############################################################# + +def regression(xdata,ydata,mode,basisparams,regparams): + """ + Polynomial regression given x- and y-data. A wrapper around the regression app + + Arguments: + * xdata : N x d array of x-data + * ydata : N x e array of y-data + * mode : m (only mean), ms (mean and stdev) or msc (mean,stdev and cov) + * basisparams : tuple of two elements, (pctype,mindex) + : pctype - PC type + : mindex - multiindex array + * regparams : tuple of two elements, (method, methodpars) + : method - regression method, 'lsq' or 'wbcs' + : methodpars - parameters of the regression (regularization weights for wbcs) + : Note: regparams=np.array(methodpars) on output + + Returns: + * cfs : Coefficient vector + * mindex : Multiindex array + * Sig : Coefficient covariance matrix + * used : Indices of retained multiindices + """ + + # Read input settings + pctype,mindex=basisparams + method,methodpars=regparams + + # Turn regparams tuple into an array + regparams=np.array(methodpars).reshape(-1,1) + + # Get the dimensionality + dim=mindex.shape[1] + + # Save the appropriate files for the regression app + np.savetxt('xdata.dat',xdata) + np.savetxt('ydata.dat',ydata) + np.savetxt('mindex.dat',mindex,fmt='%d') + np.savetxt('regparams.dat',regparams,fmt='%24.16f') + + # Regularization + lamstr='' + regstr='' + if method=='lsq': + lamstr='-l 0.0' + if method=='wbcs': + regstr='-w regparams.dat' + + # Run the regression app + cmd='regression -c 1.e-5 -x xdata.dat -y ydata.dat -b PC_MI -s '+pctype+' -p mindex.dat -m '+mode+' -r '+method + ' '+regstr+' '+lamstr +' > regr.log' + print "Running "+cmd + os.system(cmd) + + # Read the resulting files + cfs=np.loadtxt('coeff.dat') + used=np.loadtxt('selected.dat',dtype=int) + mindex=np.loadtxt('mindex.dat',dtype=int).reshape(-1,dim) + mindex=mindex[used] + if (mode=='msc'): + Sig=np.loadtxt('Sig.dat') + else: + Sig=[] + + # Return coefficient, multiindex, coef. covariance matrix, and indices of used basis terms + return (cfs,mindex,Sig,used) + +############################################################# +############################################################# +############################################################# + +def regression_iter(xdata,ydata,mode,basisparams,regparams,iterparams): + """ + Iterative regression involving multiindex growth. + See inputs and outputs of regression(), with additional argument + + iterparams : a tuple (niter,eps,update_weights,update_mindex) + * niter : Number of iterations + * eps : Nugget for iterative reweighting + * update_weights : boolean flag whether to recompute the weights or not + * update_mindex : boolean flag whether to update multiindex or not + + """ + + # Read the inputs + pctype,mindex=basisparams + method,methodpars=regparams + niter,eps,update_weights,update_mindex=iterparams + + # Set the current parameters + basisparams_cur=[pctype,mindex] + regparams_cur=[method,methodpars] + + + nrange=np.arange(mindex.shape[0]) + cur_used=nrange + npc=mindex.shape[0] + for i in range(niter): + print "Iteration %d / %d " % (i+1,niter) + print "Initial mindex size ", basisparams_cur[1].shape[0] + cfs_cur,mindex_cur,Sig,used=regression(xdata,ydata,mode,basisparams_cur,regparams_cur) + print "New mindex size ", mindex_cur.shape[0] + + + #tmp=cur_used[used] + #cur_used=tmp.copy() + + npc_cur=mindex_cur.shape[0] + + # Update weights or not + if (update_weights==True): + regparams_cur[1]=1./(abs(cfs_cur)+eps) + else: + tmp=regparams_cur[1] + regparams_cur[1]=tmp[list(used)] #read used.dat and replace it here + + # Update multiindex or not + if (update_mindex==True and i. +# +# Need help with UQTk? Check out the resources on http://www.sandia.gov/UQToolkit/ +# or e-mail uqtk-users@software.sandia.gov +# (subscription details listed at http://www.sandia.gov/UQToolkit/) +# Other questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +usage () +{ + echo "No command-line parameters, execute as is" + exit +} + +while getopts ":h" opt; do + case $opt in + h) usage + ;; + \?) echo "Invalid option -$OPTARG" >&2; usage + ;; + esac +done + + +# Run this command from within a build directory. +# Customize the macros below to your specfic directory preferences +UQTK_SRC_DIR=$PWD/../UQTk +UQTK_INSTALL_DIR=$UQTK_SRC_DIR-install + +echo "This script assumes the UQTk source code is in $UQTK_SRC_DIR" +echo "and will be installed in $UQTK_INSTALL_DIR" + +# Specficy compiler and library paths as needed +cmake -DCMAKE_INSTALL_PREFIX:PATH=$UQTK_INSTALL_DIR \ + -DCMAKE_Fortran_COMPILER=gfortran \ + -DCMAKE_C_COMPILER=gcc \ + -DCMAKE_CXX_COMPILER=g++ \ + -DPYTHON_EXECUTABLE:FILEPATH=/opt/local/bin/python \ + -DPYTHON_LIBRARY:FILEPATH=/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib \ + -DPyUQTk=ON \ + $UQTK_SRC_DIR diff --git a/config/config-gcc-base.sh b/config/config-gcc-base.sh new file mode 100755 index 00000000..38d964c7 --- /dev/null +++ b/config/config-gcc-base.sh @@ -0,0 +1,60 @@ +#!/bin/bash +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Need help with UQTk? Check out the resources on http://www.sandia.gov/UQToolkit/ +# or e-mail uqtk-users@software.sandia.gov +# (subscription details listed at http://www.sandia.gov/UQToolkit/) +# Other questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +usage () +{ + echo "No command-line parameters, execute as is" + exit +} + +while getopts ":h" opt; do + case $opt in + h) usage + ;; + \?) echo "Invalid option -$OPTARG" >&2; usage + ;; + esac +done + +# Run this script from a build directory +# Customize the paths below to reflect your directory preferences +UQTK_SRC_DIR=$PWD/../UQTk +UQTK_INSTALL_DIR=$UQTK_SRC_DIR-install + +echo "This script assumes the UQTk source code is in $UQTK_SRC_DIR" +echo "and will be installed in $UQTK_INSTALL_DIR" + +# Specify compiler and library paths as needed +cmake -DCMAKE_INSTALL_PREFIX:PATH=$UQTK_INSTALL_DIR \ + -DCMAKE_Fortran_COMPILER=gfortran \ + -DCMAKE_C_COMPILER=gcc \ + -DCMAKE_CXX_COMPILER=g++ \ + $UQTK_SRC_DIR diff --git a/config/config-grover-intel.sh b/config/config-grover-intel.sh new file mode 100755 index 00000000..6250da77 --- /dev/null +++ b/config/config-grover-intel.sh @@ -0,0 +1,50 @@ +#!/bin/bash +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0.4 +# Copyright (2017) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +usage () +{ + echo "No command-line parameters, execute as is" + exit +} + +while getopts ":h" opt; do + case $opt in + h) usage + ;; + \?) echo "Invalid option -$OPTARG" >&2; usage + ;; + esac +done + +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../UQTk-install \ + -DCMAKE_Fortran_COMPILER=/opt/intel/fc/Compiler/11.1/080/bin/ia64/ifort \ + -DCMAKE_C_COMPILER=/opt/intel/cc/Compiler/11.1/080/bin/ia64/icc \ + -DCMAKE_CXX_COMPILER=/opt/intel/cc/Compiler/11.1/080/bin/ia64/icpc \ + -DIntelLibPath=/opt/intel/fc/Compiler/11.1/080/lib/ia64 \ + -DPyUQTk=OFF \ + ../UQTk diff --git a/config/config-teton.sh b/config/config-teton.sh new file mode 100755 index 00000000..c0b25d97 --- /dev/null +++ b/config/config-teton.sh @@ -0,0 +1,112 @@ +#!/bin/bash +#===================================================================================== +# The UQ Toolkit (UQTk) version 3.0 +# Copyright (2015) Sandia Corporation +# http://www.sandia.gov/UQToolkit/ +# +# Copyright (2015) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +# with Sandia Corporation, the U.S. Government retains certain rights in this software. +# +# This file is part of The UQ Toolkit (UQTk) +# +# UQTk 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 3 of the License, or +# (at your option) any later version. +# +# UQTk 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 UQTk. If not, see . +# +# Questions? Contact Bert Debusschere +# Sandia National Laboratories, Livermore, CA, USA +#===================================================================================== + +usage () +{ + echo "Usage : $0 -d -c -p -h" + exit +} + +uqtksrc="${HOME}/Projects/UQTk/3.0/gitdir" +pyintf="OFF" +ctype="gnu" + +while getopts ":p:c:d:h" opt; do + case $opt in + p) pyintf="$OPTARG" + ;; + c) ctype="$OPTARG" + ;; + d) uqtksrc="$OPTARG" + ;; + h) usage + ;; + \?) echo "Invalid option -$OPTARG" >&2; usage + ;; + esac +done + +echo "============================================" +echo "Compiling UQTk with:" +echo " - $ctype compilers" +echo " - python interface $pyintf" +echo "============================================" + +#PATH2MUQ=${HOME}/Projects/muq-install +GNUROOT=/opt/local + +if [ "${ctype}" == "gnu53" ]; then +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../install_5.3 \ + -DCMAKE_Fortran_COMPILER=/usr/local/opt/gcc53/bin/gfortran-5.3.0 \ + -DCMAKE_C_COMPILER=/usr/local/opt/gcc53/bin/gcc-5.3.0 \ + -DCMAKE_CXX_COMPILER=/usr/local/opt/gcc53/bin/g++-5.3.0 \ + -DPATH2MUQ=${PATH2MUQ} \ + -DPyUQTk=${pyintf} \ + ${uqtksrc} +elif [ "${ctype}" == "gnu61" ]; then +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../install_6.1 \ + -DCMAKE_Fortran_COMPILER=$GNUROOT/gcc61/bin/gfortran-6.1.0 \ + -DCMAKE_C_COMPILER=$GNUROOT/gcc61/bin/gcc-6.1.0 \ + -DCMAKE_CXX_COMPILER=$GNUROOT/gcc61/bin/g++-6.1.0 \ + -DPATH2MUQ=${PATH2MUQ} \ + -DPyUQTk=${pyintf} \ + ${uqtksrc} +elif [ "${ctype}" == "gnu61m" ]; then +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../install_6.1m \ + -DCMAKE_Fortran_COMPILER=$GNUROOT/gcc61/bin/mpif90 \ + -DCMAKE_C_COMPILER=$GNUROOT/gcc61/bin/mpicc \ + -DCMAKE_CXX_COMPILER=$GNUROOT/gcc61/bin/mpic++ \ + -DPATH2MUQ=${PATH2MUQ} \ + -DPyUQTk=${pyintf} \ + ${uqtksrc} +elif [ "${ctype}" == "gnu71" ]; then +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../install_7.1 \ + -DCMAKE_Fortran_COMPILER=$GNUROOT/gcc71/bin/gfortran-7.1.0 \ + -DCMAKE_C_COMPILER=$GNUROOT/gcc71/bin/gcc-7.1.0 \ + -DCMAKE_CXX_COMPILER=$GNUROOT/gcc71/bin/g++-7.1.0 \ + -DPATH2MUQ=${PATH2MUQ} \ + -DPyUQTk=${pyintf} \ + ${uqtksrc} +elif [ "${ctype}" == "intel" ]; then +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../install_intel \ + -DCMAKE_Fortran_COMPILER=/opt/intel/composerxe/bin/ifort \ + -DCMAKE_C_COMPILER=/opt/intel/composerxe/bin/icc \ + -DCMAKE_CXX_COMPILER=/opt/intel/composerxe/bin/icpc \ + -DPyUQTk=${pyintf} \ + ${uqtksrc} +elif [ "${ctype}" == "clang" ]; then +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PWD/../install_clang \ + -DCMAKE_Fortran_COMPILER=$GNUROOT/gcc61/bin/gfortran-6.1.0 \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DClangLibPath=/opt/local/gcc61/lib \ + -DPyUQTk=${pyintf} \ + ${uqtksrc} +else + echo "Unknown compiler: ${ctype}" +fi diff --git a/cpp/.!98082!.DS_Store b/cpp/.!98082!.DS_Store new file mode 100644 index 00000000..e69de29b diff --git a/cpp/.!98083!.DS_Store b/cpp/.!98083!.DS_Store new file mode 100644 index 00000000..e69de29b diff --git a/cpp/.DS_Store b/cpp/.DS_Store new file mode 100644 index 00000000..45c70cb2 Binary files /dev/null and b/cpp/.DS_Store differ diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 00000000..852bdadc --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,5 @@ +project (UQTk) + +add_subdirectory (lib) +add_subdirectory (app) +add_subdirectory (tests) diff --git a/cpp/app/CMakeLists.txt b/cpp/app/CMakeLists.txt new file mode 100644 index 00000000..954032bf --- /dev/null +++ b/cpp/app/CMakeLists.txt @@ -0,0 +1,13 @@ +add_subdirectory (gen_mi) +add_subdirectory (generate_quad) +add_subdirectory (model_inf) +add_subdirectory (pce_eval) +add_subdirectory (pce_quad) +add_subdirectory (pce_resp) +add_subdirectory (pce_rv) +add_subdirectory (pce_sens) +add_subdirectory (pdf_cl) +add_subdirectory (sens) +add_subdirectory (regression) +add_subdirectory (gp_regr) +add_subdirectory (gkpSparse) diff --git a/cpp/app/gen_mi/CMakeLists.txt b/cpp/app/gen_mi/CMakeLists.txt new file mode 100644 index 00000000..9002bb9a --- /dev/null +++ b/cpp/app/gen_mi/CMakeLists.txt @@ -0,0 +1,47 @@ + +add_executable (gen_mi gen_mi.cpp) + +target_link_libraries (gen_mi uqtkpce ) +target_link_libraries (gen_mi uqtkarray) +target_link_libraries (gen_mi uqtktools) + +target_link_libraries (gen_mi depdsfmt ) +target_link_libraries (gen_mi deplapack) +target_link_libraries (gen_mi depblas ) +target_link_libraries (gen_mi depfigtree ) +target_link_libraries (gen_mi depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (gen_mi gfortran stdc++) + else() + target_link_libraries (gen_mi ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (gen_mi ifcore) + else() + target_link_libraries (gen_mi ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (gen_mi gfortran stdc++) + else() + target_link_libraries (gen_mi ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/include) +include_directories(../../lib/array ) +include_directories(../../lib/tools ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/figtree) + + +INSTALL(TARGETS gen_mi DESTINATION bin) + diff --git a/cpp/app/gen_mi/gen_mi.cpp b/cpp/app/gen_mi/gen_mi.cpp new file mode 100644 index 00000000..b48017de --- /dev/null +++ b/cpp/app/gen_mi/gen_mi.cpp @@ -0,0 +1,193 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file gen_mi.cpp +/// \author K. Sargsyan 2014 - +/// \brief Command-line utility to generate multiindex + +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" +#include + +using namespace std; + + +/// default multiindex type +#define MI_TYPE "TO" +/// default multiindex sequence +#define MI_SEQ "NONE" +/// default order +#define ORD 1 +/// default dimensionality +#define DIM 3 +/// default parameter filename +#define PARAM_FILE "mi_param.dat" +/// default verbosity +#define VERBOSITY 1 + + + +/******************************************************************************/ +/// Displays information about this program +int usage(){ + printf("This program to generate multiindex files given rules.\n"); + printf("usage: gen_mi [-h] [-x] [-s] [-p] [-q] [-f] [-v ]\n"); + printf(" -h : print out this help message \n"); + printf(" -x : define the multiindex type (default=%s) \n",MI_TYPE); + printf(" -s : define the multiindex sequence (default=%s) \n",MI_SEQ); + printf(" -p : define the first parameter (default=%d) \n",ORD); + printf(" -q : define the second parameter (default=%d) \n",DIM); + printf(" -f : define the parameter filename for multiindex (default=%s) \n",PARAM_FILE); + printf(" -v : define verboosity 0-no output/1-output info (default=%d) \n",VERBOSITY); + printf("================================================================================\n"); + printf("Input : None \n"); + printf("Output : File 'mindex.dat'\n"); + printf("--------------------------------------------------------------------------------\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + + +/// Main program: Generates multiindex of requested type with given parameters +int main(int argc, char *argv[]) +{ + + + /// Set the default values + int nord = ORD; + int ndim = DIM; + int verb = VERBOSITY; + char* param_file= (char *)PARAM_FILE; + char* mi_type = (char *)MI_TYPE; + char* mi_seq = (char *)MI_SEQ; + + bool pflag = false; + bool sflag = false; + bool qflag = false; + bool fflag = false; + + /// Read the user input + int c; + + while ((c=getopt(argc,(char **)argv,"hx:s:p:q:f:v:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'x': + mi_type = optarg; + break; + case 's': + mi_seq = optarg; + sflag=true; + break; + case 'p': + nord = strtol(optarg, (char **)NULL,0); + pflag=true; + break; + case 'q': + ndim = strtol(optarg, (char **)NULL,0); + qflag=true; + break; + case 'f': + param_file = optarg; + fflag=true; + break; + case 'v': + verb = strtol(optarg, (char **)NULL,0); + break; + default : + break; + } + } + + /*----------------------------------------------------------------------------*/ + /// Print the input information on screen + if ( verb > 0 ) { + fprintf(stdout,"mi_type = %s \n",mi_type); + if (sflag) fprintf(stdout,"mi_seq = %s \n",mi_seq); + if (qflag) fprintf(stdout,"ndim = %d \n",ndim); + if (pflag) fprintf(stdout,"nord = %d \n",nord); + if (fflag) fprintf(stdout,"param_file = %s \n",param_file); + } + /*----------------------------------------------------------------------------*/ + + if(fflag && (pflag)){ + printf("gen_mi(): Can not specify both parameter file and order. Exiting.\n"); + exit(1); + } + + // Cast multiindex type as string + string mi_type_str(mi_type); + + int npc; + Array2D mindex; + + // Choose between TO, TP or HDMR + + // Total order + if (mi_type_str == "TO") { + if ( not sflag ) + npc=computeMultiIndex(ndim,nord,mindex); + else + npc=computeMultiIndex(ndim,nord,mindex,string(mi_seq)); + } + + else if (mi_type_str == "TP") { + Array1D maxorders; + Array2D maxorders2d; + read_datafileVS(maxorders2d,param_file); + getCol(maxorders2d, 0, maxorders); + npc=computeMultiIndexTP(maxorders, mindex); + } + + // HDMR ordering + else if(mi_type_str=="HDMR"){ + Array1D maxorders; + Array2D maxorders2d; + read_datafileVS(maxorders2d,param_file); + getCol(maxorders2d, 0, maxorders); + npc=computeMultiIndexHDMR(ndim, maxorders, mindex); + } + + else { + printf("gen_mi():: Multiindex type %s is not recognized. \n", mi_type); + exit(1); + } + + /// Write to file mindex.dat + write_datafile(mindex, "mindex.dat"); + if ( verb > 0 ) + cout << "Generated multiindex of size " << npc + << " and stored in mindex.dat" << endl; + + return 0; + +} + + diff --git a/cpp/app/generate_quad/CMakeLists.txt b/cpp/app/generate_quad/CMakeLists.txt new file mode 100644 index 00000000..d7ef6da1 --- /dev/null +++ b/cpp/app/generate_quad/CMakeLists.txt @@ -0,0 +1,48 @@ + +add_executable (generate_quad generate_quad.cpp) + +target_link_libraries (generate_quad uqtkquad ) +target_link_libraries (generate_quad uqtktools) +target_link_libraries (generate_quad uqtkarray) + +target_link_libraries (generate_quad depdsfmt ) +target_link_libraries (generate_quad deplapack) +target_link_libraries (generate_quad depblas ) +target_link_libraries (generate_quad depfigtree ) +target_link_libraries (generate_quad depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (generate_quad gfortran stdc++) + else() + target_link_libraries (generate_quad ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel C++ + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (generate_quad ifcore) + else() + target_link_libraries (generate_quad ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (generate_quad gfortran stdc++) + else() + target_link_libraries (generate_quad ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/include) +include_directories(../../lib/tools ) +include_directories(../../lib/quad ) +include_directories(../../lib/array ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/figtree) + + +INSTALL(TARGETS generate_quad DESTINATION bin) + diff --git a/cpp/app/generate_quad/generate_quad.cpp b/cpp/app/generate_quad/generate_quad.cpp new file mode 100644 index 00000000..002b610e --- /dev/null +++ b/cpp/app/generate_quad/generate_quad.cpp @@ -0,0 +1,263 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file generate_quad.cpp +/// \author K. Sargsyan 2013 - +/// \brief Command-line utility to generate quadrature points + +#include +#include "quad.h" +#include "tools.h" +#include "arrayio.h" + +using namespace std; + +/// default value of parameter (level for sparse quadrature, or number of grid points for full quadrature) +#define PARAM 3 +/// default data dimensionality +#define DIM 2 +/// default sparseness type (full or sparse) +#define FSTYPE "sparse" +/// default quadrature type +#define QUADTYPE "CC" +/// default alpha parameter for chaos +#define ALPHA 0.0 +/// default beta parameter for chaos +#define BETA 1.0 +/// default domain file +#define DOMAIN_FILE "param_domain.dat" +/// default verbosity +#define VERBOSITY 1 + +/******************************************************************************/ +/// \brief Displays information about this program +int usage(){ + printf("usage: generate_quad [-h] [-r] [-d] [-g] [-x] [-p] [-a] [-b] [-s] [-v ]\n"); + printf(" -h : print out this help message \n"); + printf(" -r : use if building the next quadrature level on top of existing rule\n"); + printf(" -d : define the data dimensionality (default=%d) \n",DIM); + printf(" -g : define the quad type, implemented 'CC','CCO','NC','NCO','LU','HG','JB','GLG','SW','pdf'. (default=%s) \n",QUADTYPE); + printf(" -x : define 'full' or 'sparse' (default=%s) \n",FSTYPE); + printf(" -p : define the level or nquad parameter(default=%d) \n",PARAM); + printf(" -a : define the alpha parameter of the quadrature (default=%lg) \n",ALPHA); + printf(" -b : define the beta parameter of the quadrature (default=%lg) \n",BETA); + printf(" -s : define the domain file for compact-support quadratures (default=%s) \n",DOMAIN_FILE); + printf(" -v : define verbosity 0-no output/1-output info (default=%d) \n",VERBOSITY); + printf("================================================================================\n"); + printf("Input : If -r flagged, files qdpts.dat, wghts.dat, indices.dat required as quadrature will be built on top of them\n"); + printf("Output : qdpts.dat, wghts.dat, indices.dat - quadrature points, weights, and indices w.r.t. default quadrature domain\n"); + printf(" xqdpts.dat, xwghts.dat - quadrature points and weights w.r.t. given physical domain for compact domains,\n"); + printf(" if the domain is given by -s\n"); + printf(" *_new.dat - newly generated points/weights; if -r is not flagged these are the same as all points/wghts)\n"); + printf("--------------------------------------------------------------------------------\n"); + printf("Comments: -r flag may be activated only after a run with the SAME parameters, otherwise incremental addition does not make sense!\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} +/******************************************************************************/ + + + +/// Main program: Generates various kinds of quadrature points and weights +int main (int argc, char *argv[]) +{ + /// Set the default values + int verb = VERBOSITY ; + int ndim = DIM ; + char* quadType = (char *) QUADTYPE; + char* fsType = (char *) FSTYPE ; + int param = PARAM ; + double alpha = ALPHA; + double beta = BETA; + char* domain_file = (char *) DOMAIN_FILE; + + /// Read the user input + int c; + + bool rflag=false; + bool aflag=false; + bool bflag=false; + bool sflag=false; + + while ((c=getopt(argc,(char **)argv,"hrd:g:x:p:a:b:s:v:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'r': + rflag=true; + break; + case 'd': + ndim = strtol(optarg, (char **)NULL,0); + break; + case 'g': + quadType = optarg; + break; + case 'x': + fsType = optarg; + break; + case 'p': + param = strtol(optarg, (char **)NULL,0); + break; + case 'a': + aflag=true; + alpha = strtod(optarg, (char **)NULL); + break; + case 'b': + bflag=true; + beta = strtod(optarg, (char **)NULL); + break; + case 's': + sflag=true; + domain_file = optarg; + break; + case 'v': + verb = strtol(optarg, (char **)NULL,0); + break; + default : + break; + } + } + + /// Print the input information on screen + if ( verb > 0 ) { + fprintf(stdout,"generate_quad() : parameters ================================= \n"); + fprintf(stdout," ndim = %d \n",ndim); + fprintf(stdout," quadType = %s \n",quadType); + fprintf(stdout," fsType = %s \n",fsType); + fprintf(stdout," param = %d \n",param); + if (aflag) + fprintf(stdout," alpha = %lg \n",alpha); + if (bflag) + fprintf(stdout," beta = %lg \n",beta); + if (rflag) + fprintf(stdout,"generate_quad() : building on top of existing quad points\n"); + if (sflag) + fprintf(stdout,"generate_quad() : domain file %s is provided\n",domain_file); + } + /*----------------------------------------------------------------------------*/ + + /// Parameter sanity checks + if (rflag && string(fsType)=="full") + throw Tantrum("Incremental addition makes sense only in the sparse mode!"); + if (sflag && string(quadType)!="CC" + && string(quadType)!="CCO" + && string(quadType)!="NC" + && string(quadType)!="NCO" + && string(quadType)!="LU" + && string(quadType)!="JB") + throw Tantrum("Input domain should be provided only for compact-support quadratures!"); + + + /// Declare the quadrature rule object + Array1D quadtypes(ndim,string(quadType)); + + Array1D alphas(ndim,alpha); + Array1D betas(ndim,beta); + Array1D params(ndim,param); + + Quad spRule(quadtypes,fsType,params,alphas, betas); + spRule.SetVerbosity(verb); + + // Declare arrays + Array1D newPtInd; + Array2D qdpts; + Array1D wghts; + + spRule.SetRule(); + + // DEBUG + //Array1D ind; + //spRule.compressRule(ind); + + /// Extract the properties of the rule + spRule.GetRule(qdpts,wghts); + int nQdpts=qdpts.XSize(); + + + /// Write-out to files + write_datafile(qdpts,"qdpts.dat"); + write_datafile_1d(wghts,"wghts.dat"); + + /// Scale if domain is provided + if (sflag){ + /// Set the domain + Array1D aa(ndim,-1.e0); + Array1D bb(ndim,1.e0); + Array2D aabb(ndim,2,0.e0); + + if(ifstream(domain_file)){ + read_datafile(aabb,domain_file); + for (int i=0;i xqdpts(nQdpts,ndim); + // Array2D xqdpts_new(nNewQdpts,ndim); + Array1D xwghts(nQdpts); + // Array1D xwghts_new(nNewQdpts); + + // Scale points according to the given domain + for(int it=0;it 0 ) { + //fprintf(stdout,"generate_quad() : generated %d new quadrature points\n",nNewQdpts); + fprintf(stdout,"generate_quad() : total number of quadrature points: %d\n",nQdpts); + fprintf(stdout,"generate_quad() : done ========================================\n"); + } + + return 0; +} + + diff --git a/cpp/app/gkpSparse/CMakeLists.txt b/cpp/app/gkpSparse/CMakeLists.txt new file mode 100644 index 00000000..28c07ba5 --- /dev/null +++ b/cpp/app/gkpSparse/CMakeLists.txt @@ -0,0 +1,47 @@ +enable_language(Fortran) +enable_language(CXX) + +add_executable (gkpSparse gkpSparse.cpp gkpclib.cpp gkpflib.f) + +target_link_libraries (gkpSparse uqtktools) +target_link_libraries (gkpSparse uqtkarray) + +target_link_libraries (gkpSparse depdsfmt ) +target_link_libraries (gkpSparse deplapack) +target_link_libraries (gkpSparse depblas ) +target_link_libraries (gkpSparse depfigtree ) +target_link_libraries (gkpSparse depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (gkpSparse gfortran stdc++) + else() + target_link_libraries (gkpSparse ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel C++ + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (gkpSparse ifcore ifport) + else() + target_link_libraries (gkpSparse ${IntelLibPath}/libifcore.a ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (gkpSparse gfortran stdc++) + else() + target_link_libraries (gkpSparse ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/include) +include_directories(../../lib/tools ) +include_directories(../../lib/array ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/figtree) + +INSTALL(TARGETS gkpSparse DESTINATION bin) + diff --git a/cpp/app/gkpSparse/gkpSparse.cpp b/cpp/app/gkpSparse/gkpSparse.cpp new file mode 100644 index 00000000..6736b6dd --- /dev/null +++ b/cpp/app/gkpSparse/gkpSparse.cpp @@ -0,0 +1,164 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include +#include +#include +#include +#include + +#include "arrayio.h" +#include "gkplib.h" +#define NDIM 2 +#define NLEV 2 +#define VERBOSITY 1 +#define PDFTYPE "unif" + +/******************************************************************************/ +/// \brief Displays information about this program +int usage(){ + printf("usage: gkpSparse [-h] [-d] [-l] [-v ]\n"); + printf(" -h : print out this help message \n"); + printf(" -d : define the data dimensionality (default=%d) \n",NDIM); + printf(" -l : define the level or nquad parameter(default=%d) \n",NLEV); + printf(" -t : pdf type 'unif'/'norm'/'cc' (default=%s) \n",PDFTYPE); + printf(" -v : define verboosity 0-no output/1-output info (default=%d) \n",VERBOSITY); + printf("================================================================================\n"); + printf("Output : qdpts.dat, wghts.dat - quadrature points, weights w.r.t. default quadrature domain\n"); + printf("================================================================================\n"); + exit(0); + return (0); +} + +int main(int argc, char *argv[]) { + + double *qpts=NULL, *w=NULL; + int dim=NDIM, lev=NLEV, verb=VERBOSITY, nqpts; + char *pdftype = (char *) PDFTYPE; + bool anisFlag = false; + + /// Read the user input + int c; + while ((c=getopt(argc,(char **)argv,"had:l:v:t:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'd': + dim = strtol(optarg, (char **)NULL,0); + break; + case 'l': + lev = strtol(optarg, (char **)NULL,0); + break; + case 'v': + verb = strtol(optarg, (char **)NULL,0); + break; + case 't': + pdftype = optarg; + break; + case 'a': + anisFlag = true; + break; + default : + break; + } + } + + if ( verb > 0 ) { + fprintf(stdout,"gkpSparse : parameters ================================= \n"); + fprintf(stdout," ndim = %d \n",dim); + fprintf(stdout," nlev = %d \n",lev); + fprintf(stdout," pdf = %s \n",pdftype); + fprintf(stdout," anis = %d \n",anisFlag); + fprintf(stdout," verb = %d \n",verb); + } + + + Array2D levList; + if (anisFlag) { + read_datafileVS(levList,"levList.dat"); + assert(levList.XSize() == dim); + assert(levList.YSize() == 1 ); + } + + /* Get sparse quad */ + if ( std::string(pdftype) == std::string("unif") ) { + if (anisFlag) + getSpgAnisQW ( getGKPunif, getOrderGKPunif, dim, levList.GetArrayPointer(), &nqpts, &qpts, &w ) ; + else + getSpgQW ( getGKPunif, getOrderGKPunif, dim, lev, &nqpts, &qpts, &w ) ; + } + else if ( std::string(pdftype) == std::string("norm") ) { + if (anisFlag) + getSpgAnisQW ( getGKPnorm, getOrderGKPnorm, dim, levList.GetArrayPointer(), &nqpts, &qpts, &w ) ; + else + getSpgQW ( getGKPnorm, getOrderGKPnorm, dim, lev, &nqpts, &qpts, &w ) ; + } + else if ( std::string(pdftype) == std::string("cc") ) { + if (anisFlag) + getSpgAnisQW ( getCC, getOrderCC, dim, levList.GetArrayPointer(), &nqpts, &qpts, &w ) ; + else + getSpgQW ( getCC, getOrderCC, dim, lev, &nqpts, &qpts, &w ) ; + } + else { + std::cout<<"Unknown quadrature type: "< 0 ) { + std::cout<<"No. of quadrature points: "<. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include "math.h" +#include "tools.h" +#include "gkplib.h" + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + + +/* (1) */ +static double x1[] = {0.0000000}; +static double w1[] = {2.0000000}; + +/* (1+2) */ +static double x3[] = {-0.77459666924148337704,0.0, 0.77459666924148337704 }; +static double w3[] = {0.555555555555555555556,0.888888888888888888889,0.555555555555555555556}; + +/* (1+2+4) */ +static double x7[] = {-0.96049126870802028342,-0.77459666924148337704,-0.43424374934680255800, + 0.0, + 0.43424374934680255800, 0.77459666924148337704, 0.96049126870802028342}; +static double w7[] = { 0.104656226026467265194,0.268488089868333440729,0.401397414775962222905, + 0.450916538658474142345, + 0.401397414775962222905,0.268488089868333440729,0.104656226026467265194}; + +/* (1+2+4+8) */ +static double x15[] = {-0.99383196321275502221,-0.96049126870802028342,-0.88845923287225699889, + -0.77459666924148337704,-0.62110294673722640294,-0.43424374934680255800, + -0.22338668642896688163, 0.0, 0.22338668642896688163, + 0.43424374934680255800, 0.62110294673722640294, 0.77459666924148337704, + 0.88845923287225699889, 0.96049126870802028342, 0.99383196321275502221 }; +static double w15[] = {0.0170017196299402603390,0.0516032829970797396969,0.0929271953151245376859, + 0.134415255243784220360, 0.171511909136391380787, 0.200628529376989021034, + 0.219156858401587496404, 0.225510499798206687386, 0.219156858401587496404, + 0.200628529376989021034, 0.171511909136391380787, 0.134415255243784220360, + 0.0929271953151245376859,0.0516032829970797396969, 0.0170017196299402603390}; + +/* (1+2+4+8+16) */ +static double x31[] = {-0.99909812496766759766,-0.99383196321275502221,-0.98153114955374010687, + -0.96049126870802028342,-0.92965485742974005667,-0.88845923287225699889, + -0.83672593816886873550,-0.77459666924148337704,-0.70249620649152707861, + -0.62110294673722640294,-0.53131974364437562397,-0.43424374934680255800, + -0.33113539325797683309,-0.22338668642896688163,-0.11248894313318662575, + 0.0, + 0.11248894313318662575, 0.22338668642896688163, 0.33113539325797683309, + 0.43424374934680255800, 0.53131974364437562397, 0.62110294673722640294, + 0.70249620649152707861, 0.77459666924148337704, 0.83672593816886873550, + 0.88845923287225699889, 0.92965485742974005667, 0.96049126870802028342, + 0.98153114955374010687, 0.99383196321275502221, 0.99909812496766759766 }; +static double w31[] = {0.00254478079156187441540,0.00843456573932110624631,0.0164460498543878109338, + 0.0258075980961766535646, 0.0359571033071293220968, 0.0464628932617579865414, + 0.0569795094941233574122, 0.0672077542959907035404, 0.0768796204990035310427, + 0.0857559200499903511542, 0.0936271099812644736167, 0.100314278611795578771, + 0.105669893580234809744, 0.109578421055924638237, 0.111956873020953456880, + 0.112755256720768691607, + 0.111956873020953456880, 0.109578421055924638237, 0.105669893580234809744, + 0.100314278611795578771, 0.0936271099812644736167, 0.0857559200499903511542, + 0.0768796204990035310427, 0.0672077542959907035404, 0.0569795094941233574122, + 0.0464628932617579865414, 0.0359571033071293220968, 0.0258075980961766535646, + 0.0164460498543878109338, 0.00843456573932110624631,0.00254478079156187441540 }; + +/* (1+2+4+8+16+32) */ +static double x63[] = {-0.99987288812035761194,-0.99909812496766759766,-0.99720625937222195908, + -0.99383196321275502221,-0.98868475754742947994,-0.98153114955374010687, + -0.97218287474858179658,-0.96049126870802028342,-0.94634285837340290515, + -0.92965485742974005667,-0.91037115695700429250,-0.88845923287225699889, + -0.86390793819369047715,-0.83672593816886873550,-0.80694053195021761186, + -0.77459666924148337704,-0.73975604435269475868,-0.70249620649152707861, + -0.66290966002478059546,-0.62110294673722640294,-0.57719571005204581484, + -0.53131974364437562397,-0.48361802694584102756,-0.43424374934680255800, + -0.38335932419873034692,-0.33113539325797683309,-0.27774982202182431507, + -0.22338668642896688163,-0.16823525155220746498,-0.11248894313318662575, + -0.056344313046592789972,0.0, 0.056344313046592789972, + 0.11248894313318662575, 0.16823525155220746498, 0.22338668642896688163, + 0.27774982202182431507, 0.33113539325797683309, 0.38335932419873034692, + 0.43424374934680255800, 0.48361802694584102756, 0.53131974364437562397, + 0.57719571005204581484, 0.62110294673722640294, 0.66290966002478059546, + 0.70249620649152707861, 0.73975604435269475868, 0.77459666924148337704, + 0.80694053195021761186, 0.83672593816886873550, 0.86390793819369047715, + 0.88845923287225699889, 0.91037115695700429250, 0.92965485742974005667, + 0.94634285837340290515, 0.96049126870802028342, 0.97218287474858179658, + 0.98153114955374010687, 0.98868475754742947994, 0.99383196321275502221, + 0.99720625937222195908, 0.99909812496766759766, 0.99987288812035761194 }; +static double w63[] = {0.000363221481845530659694,0.00126515655623006801137,0.00257904979468568827243, + 0.00421763044155885483908, 0.00611550682211724633968,0.00822300795723592966926, + 0.0104982469096213218983, 0.0129038001003512656260, 0.0154067504665594978021, + 0.0179785515681282703329, 0.0205942339159127111492, 0.0232314466399102694433, + 0.0258696793272147469108, 0.0284897547458335486125, 0.0310735511116879648799, + 0.0336038771482077305417, 0.0360644327807825726401, 0.0384398102494555320386, + 0.0407155101169443189339, 0.0428779600250077344929, 0.0449145316536321974143, + 0.0468135549906280124026, 0.0485643304066731987159, 0.0501571393058995374137, + 0.0515832539520484587768, 0.0528349467901165198621, 0.0539054993352660639269, + 0.0547892105279628650322, 0.0554814043565593639878, 0.0559784365104763194076, + 0.0562776998312543012726, 0.0563776283603847173877, 0.0562776998312543012726, + 0.0559784365104763194076, 0.0554814043565593639878, 0.0547892105279628650322, + 0.0539054993352660639269, 0.0528349467901165198621, 0.0515832539520484587768, + 0.0501571393058995374137, 0.0485643304066731987159, 0.0468135549906280124026, + 0.0449145316536321974143, 0.0428779600250077344929, 0.0407155101169443189339, + 0.0384398102494555320386, 0.0360644327807825726401, 0.0336038771482077305417, + 0.0310735511116879648799, 0.0284897547458335486125, 0.0258696793272147469108, + 0.0232314466399102694433, 0.0205942339159127111492, 0.0179785515681282703329, + 0.0154067504665594978021, 0.0129038001003512656260, 0.0104982469096213218983, + 0.00822300795723592966926, 0.00611550682211724633968,0.00421763044155885483908, + 0.00257904979468568827243, 0.00126515655623006801137,0.000363221481845530659694 }; + +/* (1) */ +static double xn1[] = {0.0000000000000000}; +static double wn1[] = {1.0000000000000000}; + +/* (1+2) */ +static double xn3[] = {-1.73205080756887719, 0.000000000000000000, 1.73205080756887719}; +static double wn3[] = {0.166666666666666657, 0.66666666666666663, 0.166666666666666657}; + +/* (1+2+6) */ +static double xn9[] = {-4.18495601767273229, -2.86127957605705818, -1.73205080756887719, + -0.741095349994540853, 0.00000000000000000, 0.741095349994540853, + 1.73205080756887719, 2.86127957605705818, 4.18495601767273229 }; +static double wn9[] = { 9.42694575565174701E-05, 0.00799632547089352934, 0.0948509485094851251, + 0.270074329577937755, 0.253968253968254065, 0.270074329577937755, + 0.0948509485094851251,0.00799632547089352934,9.42694575565174701E-05 }; + +/* (1+2+6+10) */ +static double xn19[] = {-6.36339449433636961, -5.18701603991365623, -4.18495601767273229, + -3.20533379449919442, -2.86127957605705818, -2.59608311504920231, + -1.73205080756887719, -1.23042363402730603, -0.741095349994540853, + 0.0000000000000000, + 0.741095349994540853, 1.23042363402730603, 1.73205080756887719, + 2.59608311504920231, 2.86127957605705818, 3.20533379449919442, + 4.18495601767273229, 5.18701603991365623, 6.36339449433636961 }; +static double wn19[] = { 8.62968460222986318E-10, 6.09480873146898402E-07, 6.01233694598479965E-05, + 0.00288488043650675591, -0.00633722479337375712, 0.0180852342547984622, + 0.0640960546868076103, 0.0611517301252477163, 0.208324991649608771, + 0.303467199854206227, + 0.208324991649608771, 0.0611517301252477163, 0.0640960546868076103, + 0.0180852342547984622, -0.00633722479337375712, 0.00288488043650675591, + 6.01233694598479965E-05, 6.09480873146898402E-07,8.62968460222986318E-10 }; + +/* (1+2+6+10+16) */ +static double xn35[] = {-9.0169397898903032, -7.98077179859056063, -7.12210670080461661, + -6.36339449433636961, -5.69817776848810986, -5.18701603991365623, + -4.73643308595229673, -4.18495601767273229, -3.63531851903727832, + -3.20533379449919442, -2.86127957605705818, -2.59608311504920231, + -2.23362606167694189, -1.73205080756887719, -1.23042363402730603, + -0.741095349994540853, -0.248992297579960609, + 0.00000000000000000, + 0.248992297579960609, 0.741095349994540853, + 1.23042363402730603, 1.73205080756887719, 2.23362606167694189, + 2.59608311504920231, 2.86127957605705818, 3.20533379449919442, + 3.63531851903727832, 4.18495601767273229, 4.73643308595229673, + 5.18701603991365623, 5.69817776848810986, 6.36339449433636961, + 7.12210670080461661, 7.98077179859056063, 9.0169397898903032 }; +static double wn35[] = { 1.05413265823340136E-18, 5.45004126506381281E-15, 3.09722235760629949E-12, + 4.60117603486559168E-10, 2.13941944795610622E-08, 2.46764213457981401E-07, + 2.73422068011878881E-06, 3.57293481989753322E-05, 0.000275242141167851312, + 0.000818953927502267349, 0.00231134524035220713, 0.00315544626918755127, + 0.015673473751851151, 0.0452736854651503914, 0.0923647267169863534, + 0.148070831155215854, 0.191760115888044341, + 0.000514894508069213769, + 0.191760115888044341, 0.148070831155215854, + 0.0923647267169863534, 0.0452736854651503914, 0.015673473751851151, + 0.00315544626918755127, 0.00231134524035220713, 0.000818953927502267349, + 0.000275242141167851312, 3.57293481989753322E-05, 2.73422068011878881E-06, + 2.46764213457981401E-07, 2.13941944795610622E-08, 4.60117603486559168E-10, + 3.09722235760629949E-12, 5.45004126506381281E-15, 1.05413265823340136E-18 }; + + + +void getCC ( int n, int *nq, double **x, double **w ) { + + if ((n-1)%2 != 0) std::cout<lev) lev=levList[j]; + + /* Initial estimate for number of quad points */ + (*nqpts) = getSpgSize ( getOrder, dim, lev ); +#ifdef DEBUG + std::cout<<(*nqpts)<levList[j]) { + goodElem = false; + std::cout<0); + assert(spgSize>1); + + int isgn=0, i1=0, j1=0, index=0; + + do { + + heap_ext_(&spgSize,&isgn,&i1,&j1,&index); + if (index < 0) { + isgn = 0; + for ( int j = 0; j < dim; j++ ) { + if ( qpts[(i1-1)*dim+j] < qpts[(j1-1)*dim+j] ) { + isgn = -1; break; + } + else if ( qpts[(j1-1)*dim+j] < qpts[(i1-1)*dim+j] ) { + isgn = 1; + break; + } + } + } + + if (index > 0) { + double dtmp ; + for ( int j = 0; j < dim; j++ ) { + double dtmp = qpts[(i1-1)*dim+j]; + qpts[(i1-1)*dim+j] = qpts[(j1-1)*dim+j]; + qpts[(j1-1)*dim+j] = dtmp; + } + dtmp = w[i1-1]; + w[i1-1] = w[j1-1]; + w[j1-1] = dtmp; + } + + } while (index != 0); + + + return; + +} + +void getTensorProd(int dim, double *qpts, double *w, int *spgSize, int *n1D, + double **x1D, double **w1D, double qfac) { + + int n1 = 1, n2 = 1; + for (int i=1; i. +c$$$ +c$$$ Questions? Contact Bert Debusschere +c$$$ Sandia National Laboratories, Livermore, CA, USA +c$$$===================================================================================== + subroutine heap_ext(n,isgn,i,j,index) + + implicit none + integer n,isgn,i,j,index + + integer l,l1,n1 + + common /hpwrk/ l,l1,n1 + + if (index) 90,10,80 + 10 n1 = n + l = 1+n/2 + 20 l = l-1 + 30 l1 = l + 40 i = l1+l1 + if (i-n1) 50,60,70 + 50 j = i+1 + index = -2 + return + 60 j = l1 + l1 = i + index = -1 + return + 70 if (l.gt.1) goto 20 + if (n1.eq.1) goto 110 + i = n1 + n1 = n1-1 + j = 1 + index = 1 + return + 80 if (index-1) 30,30,40 + 90 if (index.eq.-1) goto 100 + if (isgn.lt.0) i=i+1 + goto 60 + 100 if (isgn.le.0) goto 70 + index = 2 + return + 110 index = 0 + return + end + + diff --git a/cpp/app/gkpSparse/gkplib.h b/cpp/app/gkpSparse/gkplib.h new file mode 100644 index 00000000..792248cf --- /dev/null +++ b/cpp/app/gkpSparse/gkplib.h @@ -0,0 +1,89 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef GKPLIB +#define GKPLIB + +/** \file gkplib.h + * Functions related to Gauss-Kronrod-Patterson sparse quadrature construction + */ + +/// \brief retrieve pointers to 1D Clenshaw-Curtis rules +void getCC ( int n, int *nq, double **x, double **w ); + +/// \brief get order of Clenshaw-Curtis rules based on level +int getOrderCC ( int lev ) ; + +/// \brief retrieve pointers to 1D Gauss-Kronrod-Patterson rules for +/// uniform pdf based on the quadrature level +void getGKPunif ( int n, int *nq, double **x, double **w ); + +/// \brief retrieve pointers to 1D Kronrod-Patterson rules for +/// normal pdf based on the quadrature level +void getGKPnorm ( int n, int *nq, double **x, double **w ); + +/// \brief get order of uniform Gauss-Kronrod-Patterson rules based on level +int getOrderGKPunif ( int lev ) ; + +/// \brief get order of normal Gauss-Kronrod-Patterson rules based on level +int getOrderGKPnorm ( int lev ) ; + +/// \brief List of decompositions of 'n' into 'dim' parts. The +/// implementation is based on Algorithm 5 of Combinatorial Algorithms +/// by Albert Nijenhuis, Herbert Wilf +void getCompNintoDim(int n, int dim, int *nelem, int **plist) ; + +/// \brief Initial estimate for sparse grid size +int getSpgSize ( int getOrder ( int ), int dim, int lev ); + +/// \brief Sort sparse grid in lexicographical order +void sortSpg ( int dim, int spgSize, double *qpts, double *w ); + +/// \brief compute dim-dimensional tensor grid based a series of 1D rules +void getTensorProd(int dim, double *qpts, double *w, int *spgSize, int *n1D, + double **x1D, double **w1D, double qfac); + +/// \brief Main function that connects the user setup for pdftype, +/// dimensionality, and quadrature level and various pieces of the +/// sparse quadrature algorithm employing Gauss-Kronrod-Patterson rules +void getSpgQW ( void get1DQW ( int , int *, double **, double** ), int getOrder ( int ), + int dim, int lev, int *nqpts, double **qpts, double + **w ); + +void getSpgAnisQW ( void get1DQW ( int , int *, double **, double** ), int getOrder ( int ), + int dim, int *levList, int *nqpts, double **qpts, double **w ) ; + +void getCC ( int n, int *nq, double **x, double **w ); +int getOrderCC ( int lev ); + +/// brief Fortran function for sorting an array of items. The array +/// operations happen outside this function, based on a series of +/// flags passed between the user code and this function. This +/// implementation is based on Algorithm 15 of Combinatorial Algorithms +/// by Albert Nijenhuis, Herbert Wilf +extern "C" void heap_ext_(const int *,const int *, int *, int *, int *); + +#endif diff --git a/cpp/app/gp_regr/CMakeLists.txt b/cpp/app/gp_regr/CMakeLists.txt new file mode 100644 index 00000000..90a033a5 --- /dev/null +++ b/cpp/app/gp_regr/CMakeLists.txt @@ -0,0 +1,64 @@ +project (UQTk) + +add_executable (gp_regr gp_regr.cpp) + +target_link_libraries (gp_regr uqtkgproc ) +target_link_libraries (gp_regr uqtkpce ) +target_link_libraries (gp_regr uqtkbcs ) +target_link_libraries (gp_regr uqtkquad ) +target_link_libraries (gp_regr uqtktools) +target_link_libraries (gp_regr uqtkarray) + +target_link_libraries (gp_regr depdsfmt ) +target_link_libraries (gp_regr deplbfgs ) +target_link_libraries (gp_regr depcvode ) +target_link_libraries (gp_regr depnvec ) +target_link_libraries (gp_regr depslatec) +target_link_libraries (gp_regr deplapack) +target_link_libraries (gp_regr depblas ) +target_link_libraries (gp_regr depfigtree ) +target_link_libraries (gp_regr depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (gp_regr gfortran stdc++) + else() + target_link_libraries (gp_regr ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (gp_regr ifcore) + target_link_libraries (gp_regr ifport) + else() + target_link_libraries (gp_regr ${IntelLibPath}/libifcore.a) + target_link_libraries (gp_regr ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (gp_regr gfortran stdc++) + else() + target_link_libraries (gp_regr ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/bcs ) +include_directories(../../lib/gproc ) + + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS gp_regr DESTINATION bin) + diff --git a/cpp/app/gp_regr/gp_regr.cpp b/cpp/app/gp_regr/gp_regr.cpp new file mode 100644 index 00000000..5f92155c --- /dev/null +++ b/cpp/app/gp_regr/gp_regr.cpp @@ -0,0 +1,296 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file gp_regr.cpp +/// \author K. Sargsyan 2015 - +/// \brief Command-line utility for Gaussian Process regression + +#include +#include +#include +#include +#include +#include +#include + +#include "Array1D.h" +#include "Array2D.h" + +#include "PCSet.h" +#include "error_handlers.h" +#include "ftndefs.h" +#include "gen_defs.h" +#include "assert.h" +#include "quad.h" +#include "gproc.h" + +#include "arrayio.h" +#include "tools.h" +#include "arraytools.h" +#include "dsfmt_add.h" + +using namespace std; + + + +/// default x-file +#define XFILE "xdata.dat" +/// default y-file +#define YFILE "ydata.dat" +/// default flag to output mean (m), mean+std (ms) or mean+std+cov (msc) +#define MSC "ms" +/// default PC order +#define ORD 3 + +/******************************************************************************/ + +/// Displays information about this program +int usage(){ + printf("usage: gp_regr [-h] [-x] [-y] [-m] [-t] [-o] [-l] [-w] [-s]\n"); + printf(" -h : print out this help message \n"); + printf(" -x : xdata filename, matrix Nxd (default=%s) \n",XFILE); + printf(" -y : ydata filename, matrix Nxe (default=%s) \n",YFILE); + printf(" -m : flag to determine whether only mean is needed or not (default=%s) \n",MSC); + printf(" -t : optional filename of x-values for validation/plotting \n"); + printf(" -o : define the PC order (default=%d) \n",ORD); + printf(" -l : optional correlation length (isotropic)\n"); + printf(" -w : optional file name for correlation lengths, if not given and -l is not given, then finds the best.\n"); + printf(" -s : optional file name for data variance. If not given, set to a small nugget 1.e-6\n"); + printf("================================================================================\n"); + printf("Input:: \n"); + printf("Output:: ycheck.dat, ycheck_std.dat (if ms), cov.dat, xycov.dat, sttmat.dat (if msc)\n"); + + printf("--------------------------------------------------------------------------------\n"); + printf("Comments: None yet.\n"); + printf("Complexity: Not tested yet.\n"); + printf("Todo: -Clean up the matrix manipulations\n"); + printf("Todo: -Investigate addition of a stochastic dimension with roughness parameter=infty\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + + +/******************************************************************************/ +/// Main program of building Gaussian Process response surface +int main (int argc, char *argv[]) { + + /// Set the default values + char* xfile = XFILE; + char* yfile = YFILE; + int nord=ORD; + char* msc=MSC; + + + char* xcheckfile; + double corlength; + char* corlength_file; + char* datavar_file; + + bool tflag=false; + bool lflag=false; + bool wflag=false; + bool sflag=false; + + + /// Read the user input + int c; + + while ((c=getopt(argc,(char **)argv,"hx:y:m:t:o:l:w:s:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'x': + xfile = optarg; + break; + case 'y': + yfile = optarg; + break; + case 'm': + msc = optarg; + break; + case 't': + xcheckfile = optarg; + tflag=true; + break; + case 'o': + nord = strtol(optarg, (char **)NULL,0); + break; + case 'l': + corlength = strtod(optarg, (char **)NULL); + lflag=true; + break; + case 'w': + corlength_file = optarg; + wflag=true; + break; + case 's': + datavar_file = optarg; + sflag=true; + break; + } + } + + /// Sanity checks + if (lflag and wflag){ + printf("gp_regr():: can not provide both -l and -w. Exiting\n") ; + exit(1); + } + + /// Print the input information on screen + fprintf(stdout,"\ngp_regr() : parameters ================================= \n"); + fprintf(stdout,"xfile = %s \n",xfile); + fprintf(stdout,"yfile = %s \n",yfile); + fprintf(stdout,"msc = %s \n",msc); + fprintf(stdout,"nord = %d \n",nord); + if (lflag) + fprintf(stdout,"corlength = %lg \n",corlength); + if (wflag) + fprintf(stdout,"corlength_file = %s \n",corlength_file); + if (sflag) + fprintf(stdout,"datavar_file = %s \n",datavar_file); + /*----------------------------------------------------------------------------*/ + + string msc_str(msc); + + /// Read data + Array2D xdata,xcheck; + read_datafileVS(xdata,xfile); + int nx=xdata.XSize(); + int ndim=xdata.YSize(); + Array1D ydata(nx,0.e0); + + read_datafile_1d(ydata,yfile); + + /// Set or read data variance + Array1D datavar(nx,1.e-6); + if (sflag) + read_datafile_1d(datavar,datavar_file); + + + + + /// Read validation check data, if any + if (tflag) + read_datafileVS(xcheck,xcheckfile); + else + xcheck=xdata; + int ncheck=xcheck.XSize(); + + + printf("gp_regr() : Number of training points : %d\n",nx); + printf("gp_regr() : Dimensionality : %d\n",ndim); + printf("gp_regr() : Number of test points : %d\n",ncheck); + + /// Set the correlation parameters + Array1D corlengths; + + if (lflag){ + assert (corlength>=0.0); + corlengths.Resize(ndim,corlength); + } + else if (wflag){ + corlengths.Resize(ndim,0.0); + read_datafile_1d(corlengths,corlength_file); + } + else{ + corlengths.Resize(ndim,0.0); + } + + + /// Set the PC trend + PCSet PCModel("NISPnoq",nord,ndim,"LEG",0.0,1.0); + + /// Initialize a GP object + Gproc gpr("SqExp",&PCModel,corlengths); + gpr.SetupPrior(); + gpr.SetupData(xdata,ydata,datavar); + if (!lflag and !wflag){ + gpr.findBestCorrParam(); + /// Print out the roughness param + Array1D bestparam; + gpr.getParam(bestparam); + write_datafile_1d(bestparam,"best_corlengths.dat"); + } + + int npc=gpr.getNPC(); + int al=gpr.getAl(); + + /// Sanity check to ensure the regression is well-defined + if (nx+2*al<=npc+2){ + printf("gp_regr() : Error Message: [Number of input points + Prior constraint on sigma <= Number of PC terms + 2] Student-t process will have infinite variance.\n"); + exit(1); + } + + /// Build the GP + gpr.BuildGP(); + + /// Evaluate the GP (actually, a Student-t process, see the UQTk Manual) + Array1D mst; + gpr.EvalGP(xcheck,msc_str,mst); + + /// Write the mean + write_datafile_1d(mst,"ycheck.dat"); + //write_datafile_1d(bhat,"PCcoeff.dat"); + + /// If asked, compute and write standard deviation and covariance of the Student-t process + Array2D cov; + Array1D var; + if (msc_str != "m"){ + gpr.getVar(var); + //Array1D std; + //for(int it=0;it sttmat; + Array2D xycov; + + gpr.getXYCov(xcheck,xycov); + gpr.getSttPars(sttmat); + + write_datafile(cov,"cov.dat"); + write_datafile(xycov,"xycov.dat"); + write_datafile_1d(sttmat,"sttmat.dat"); + } + + /// Print out output information + fprintf(stdout,"gp_regr() : mean values : ycheck.dat\n"); + if (msc_str != "m") fprintf(stdout,"gp_regr() : standard deviation : ycheck_std.dat\n"); + if (msc_str == "msc"){ + fprintf(stdout,"gp_regr() : covariance matrix : cov.dat\n"); + fprintf(stdout,"gp_regr() : covariance matrix to plot : xycov.dat\n"); + fprintf(stdout,"gp_regr() : scale matrix values and d.o.f. for student-t : sttmat.dat\n"); + } + fprintf(stdout,"gp_regr() : done ========================================\n"); + + return 0; + +} diff --git a/cpp/app/model_inf/CMakeLists.txt b/cpp/app/model_inf/CMakeLists.txt new file mode 100644 index 00000000..4e6c187e --- /dev/null +++ b/cpp/app/model_inf/CMakeLists.txt @@ -0,0 +1,64 @@ +project (UQTk) + +add_executable (model_inf model_inf.cpp) + +target_link_libraries (model_inf uqtkinfer) +target_link_libraries (model_inf uqtkmcmc ) +target_link_libraries (model_inf uqtkpce ) +target_link_libraries (model_inf uqtkquad ) +target_link_libraries (model_inf uqtktools) +target_link_libraries (model_inf uqtkarray) + +target_link_libraries (model_inf depdsfmt ) +target_link_libraries (model_inf deplbfgs ) +target_link_libraries (model_inf depcvode ) +target_link_libraries (model_inf depnvec ) +target_link_libraries (model_inf depslatec) +target_link_libraries (model_inf deplapack) +target_link_libraries (model_inf depblas ) +target_link_libraries (model_inf depfigtree ) +target_link_libraries (model_inf depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (model_inf gfortran stdc++) + else() + target_link_libraries (model_inf ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (model_inf ifcore ifport) + else() + target_link_libraries (model_inf ${IntelLibPath}/libifcore.a) + target_link_libraries (model_inf ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (model_inf gfortran stdc++) + else() + target_link_libraries (model_inf ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include ) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) +include_directories(../../lib/infer ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + + +INSTALL(TARGETS model_inf DESTINATION bin) + diff --git a/cpp/app/model_inf/model_inf.cpp b/cpp/app/model_inf/model_inf.cpp new file mode 100644 index 00000000..ab03c372 --- /dev/null +++ b/cpp/app/model_inf/model_inf.cpp @@ -0,0 +1,510 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file model_inf.cpp +/// \author K. Sargsyan 2015 - +/// \brief Command-line utility for model parameter inference + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "func.h" +#include "post.h" +#include "mrv.h" +#include "inference.h" + +#include "mcmc.h" +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" + +using namespace std; + + + +/// default model type +#define MODELTYPE "linear" //"exp", "exp_quad", "prop", "prop_quad", "pcx","pc", "pcs", linear", "bb", "heat_transfer1", "heat_transfer2", "exp_sketch" +/// default likelihood type +#define LIKTYPE "classical" //"classical", "abc", "gausmarg", "marg", "mvn", "full", "koh" +/// default likelihood parameter of type double +#define LIKPARAM_DBL 0.01 // cov. nugget for MVN, cor. length for koh likelihood, KDE bandwidth for full and marg(but then Optimal is chosen!!), and epsilon for ABC likilohoods +/// default likelihood parameter of type int +#define LIKPARAM_INT 1000 // number of KDE samples for full and marg +/// default prior type +#define PRIORTYPE "uniform" //"uniform", "normal", "inverse", "wishart" +/// default prior parameter #1 +#define PRIORA -DBL_MAX +/// default prior parameter #2 +#define PRIORB DBL_MAX +/// default xfile +#define XFILE "xdata.dat" +/// default yfile +#define YFILE "ydata.dat" +/// default model parameter dimensionailty +#define PDIM 2 +/// default parameter pdf order +#define ORDER 1 +/// default parameter pdf type +#define PDFTYPE "pct" +/// default parameter pc for parameter pdf +#define PCTYPE "HG" +/// default datanoise +#define DATANOISE 0.1 +/// default number of MCMC steps +#define NMCMC 10000 //if 0, only does optimization +/// default MCMC gamma (i.e. proposal size factor) for adaptive MCMC +#define MCMCGAMMA 0.1 +/// default burn-in ratio +#define FBURN 10 +/// default chain thinning +#define NSTEP 5 + +/// Displays information about this program +int usage(){ + // Note that all letters of alphabet are used, except -v (todo: omplement -v for verbosity levels) + printf("This program infers model parameters given data.\n"); + printf("usage: model_inf [-h] [-f] [-l] [-w] [-k]\n"); + printf(" [-i] [-a] [-b] [-j] [-y] [-t] \n"); + printf(" [-e] \n"); + printf(" [-d] [-o] [-r] [-v] [-s] [-c] \n"); + printf(" [-m] [-g] \n"); + printf(" [-q] [-p] [-u] [-n]\n"); + printf(" -h : Print out this help message \n"); + printf(" -f : Model type (default=%s) \n",MODELTYPE); + printf(" -l : Likelihood type (default=%s) \n",LIKTYPE); + printf(" -w : Likelihood parameter of type double (default=%lg) \n",LIKPARAM_DBL); + printf(" -k : Likelihood parameter of type int (default=%d) \n",LIKPARAM_INT); + printf(" -i : Prior type (default=%s) \n",PRIORTYPE); + printf(" -a : Prior parameter #1 (default=%lg) \n", PRIORA); + printf(" -b : Prior parameter #2 (default=%lg) \n", PRIORB); + printf(" -j : Chain initial state \n"); + printf(" -z : Whether to prepend optimization to MCMC \n"); + printf(" -x : Input x-data (default=%s) \n",XFILE); + printf(" -y : Input y-data (default=%s) \n",YFILE); + printf(" -t : x-grid where the model is evaluated \n"); + printf(" -d : Model parameter dimensionality (default=%d) \n",PDIM); + printf(" -o : NISP order (default=%d) \n",ORDER); + printf(" -r : Indices of randomized parameters \n"); + printf(" -v : Indices and nominals of fixed parameters \n"); + printf(" -s : Parameter pdf type (default=%s) \n",PDFTYPE); + printf(" -c : PC type for parameter PDF (default=%s) \n",PCTYPE); + printf(" -e : Data noise parameter\n"); + printf(" -m : Number of MCMC samples (default=%d) \n",NMCMC); + printf(" -g : MCMC parameter gamma (default=%lg) \n",MCMCGAMMA); + printf(" -q : Parameter grid where the posterior is computed \n"); + printf(" -p : Parameters file for which the model is evaluated \n"); + printf(" -u : Ratio of burn-in MCMC samples (default=%d) \n",FBURN); + printf(" -n : Thinning of MCMC samples (default=%d) \n",NSTEP); + printf("=========================================================================\n"); + printf("Input : mindexx.dat (if model='pcl')\n"); + printf(" : mindexpx.dat, pccfpx.dat (if model='pcx')\n"); + printf(" : mindexp.dat, pccf_all.dat (if model='pc')\n"); + printf(" : mindexp.*.dat, pccfp.*.dat (if model='pcs')\n"); + printf("Output : chain.dat, pchain.dat, mapparam.dat, datavars.dat, parampccfs.dat\n"); + printf(" pmeans.dat, pvars.dat, fmeans.dat, fvars.dat\n"); + printf(" : pdens.dat and pdens_log.dat (if -q)\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + +/// Main program: Bayesian inference of a few standard function types +int main (int argc, char *argv[]) +{ + /// Set the defaults, where necessary + const char* modeltype=MODELTYPE; + const char* liktype=LIKTYPE; + double likParam_dbl=LIKPARAM_DBL; + int likParam_int=LIKPARAM_INT; + const char* priortype=PRIORTYPE; + double priora=PRIORA; + double priorb=PRIORB; + const char* datanoise_input; + const char* chaininitfile; + const char* xfile=XFILE; + const char* yfile=YFILE; + char* xgridfile; + int pdim=PDIM; + int order=ORDER; + const char* rndindfile; + const char* pdftype=PDFTYPE; + const char* pctype=PCTYPE; + double datanoise=DATANOISE; + int nmcmc=NMCMC; + double mcmcgamma=MCMCGAMMA; + char* pgridfile; + char* pchainfile; + int fburn=FBURN; + int nstep=NSTEP; + char* fixindnomfile; + + bool tflag=false; + bool eflag=false; + bool rflag=false; + bool qflag=false; + bool pflag=false; + bool jflag=false; + bool zflag=false; + bool vflag=false; + + /// Parse input arguments + int cc; + while ((cc=getopt(argc,(char **)argv,"hf:l:w:k:i:a:b:j:x:y:t:d:o:r:s:c:e:m:g:q:p:u:n:zv:"))!=-1){ + switch (cc) { + case 'h': + usage(); + break; + case 'f': + modeltype = optarg; + break; + case 'l': + liktype = optarg; + break; + case 'w': + likParam_dbl = strtod(optarg, (char **)NULL); + break; + case 'k': + likParam_int = strtol(optarg, (char **)NULL,0); + break; + case 'i': + priortype=optarg; + break; + case 'a': + priora = strtod(optarg, (char **)NULL); + break; + case 'b': + priorb = strtod(optarg, (char **)NULL); + break; + case 'j': + chaininitfile = optarg; + jflag=true; + break; + case 'x': + xfile = optarg; + break; + case 'y': + yfile = optarg; + break; + case 't': + xgridfile = optarg; + tflag=true; + break; + case 'd': + pdim = strtol(optarg, (char **)NULL,0); + break; + case 'o': + order = strtol(optarg, (char **)NULL,0); + break; + case 'r': + rndindfile = optarg; + rflag=true; + break; + case 's': + pdftype=optarg; + break; + case 'c': + pctype=optarg; + break; + case 'e': + datanoise_input=optarg; + eflag=true; + break; + case 'm': + nmcmc = strtol(optarg, (char **)NULL,0); + break; + case 'g': + mcmcgamma = strtod(optarg, (char **)NULL); + break; + case 'q': + pgridfile=optarg; + qflag=true; + break; + case 'p': + pchainfile = optarg; + pflag=true; + break; + case 'u': + fburn = strtol(optarg, (char **)NULL,0); + break; + case 'n': + nstep = strtol(optarg, (char **)NULL,0); + break; + case 'z': + zflag = true; + break; + case 'v': + fixindnomfile=optarg; + vflag=true; + break; + default : + break; + } + } + + + + /// Read datafiles + Array2D xdata,ydata; + read_datafileVS(xdata,xfile); + read_datafileVS(ydata,yfile); + int nx=xdata.XSize(); + + // Define arrays + Array2D xgrid,pgrid,pchain,chaininit; + + + // Data noise indicator + int dataNoiseInference; + Array1D datanoise_array; + + + /*******************************************************************************************************/ + // Dump the input information + printf("==============================================================\n") ; + printf("model_inf() settings:\n"); + printf("---------------------\n"); + printf("Forward model name : %s \n",modeltype); + printf("Likelihood type : %s \n",liktype); + printf("Prior type : %s \n",priortype); + printf("Xdata file : %s \n",xfile); + printf("Ydata file : %s \n",yfile); + printf("Model parameter dim : %d \n",pdim); + printf("Model parameter PC order : %d \n",order); + printf("Model parameter PDF type : %s \n",pdftype); + printf("Model parameter PC type : %s \n",pctype); + + if (jflag){ + read_datafileVS(chaininit,chaininitfile); + } + else{ + chaininit.Resize(0,2); + } + + if (rflag){ + printf("Indices of randomized model parameters : %s \n",rndindfile); + } + + if (tflag){ + read_datafileVS(xgrid,xgridfile); + printf("Xgrid file for predictions : %s\n", xgridfile) ; + } + else{ + read_datafileVS(xgrid,xfile); + printf("Xgrid file for predictions : %s\n", xfile) ; + } + + if (qflag){ + printf("Posterior will be evaluated at : %s\n", pgridfile) ; + read_datafileVS(pgrid,pgridfile); + } + + if (pflag){ + printf("No MCMC; only postprocessing from file : %s \n", pchainfile) ; + read_datafileVS(pchain,pchainfile); + } + else{ + printf("Number of MCMC samples : %d \n",abs(nmcmc)); + if (nmcmc>0) + printf("Gamma parameter for adaptive MCMC : %lg \n",mcmcgamma); + else if (nmcmc<0) + printf("Non-adaptive MCMC is requested.\n"); + + } + + if (eflag){ + if (isalpha(datanoise_input[0])) { + dataNoiseInference=0; + read_datafileVS(datanoise_array,datanoise_input); + printf("Data noise is fixed and read from file %s. \n", datanoise_input) ; + + assert(nx==datanoise_array.Length()); + } + else + { + + double datanoise = strtod(datanoise_input, (char **)NULL); + + if (datanoise<0.0){ + dataNoiseInference=1; + printf("Data noise will be inferred. \n") ; + datanoise_array.Resize(nx,-datanoise); + } + else{ + dataNoiseInference=0; + printf("Data noise will be fixed at %lg. \n", datanoise) ; + datanoise_array.Resize(nx,datanoise); + } + } + + } + else{ + dataNoiseInference=2; + printf("Logarithm of data noise will be inferred. \n") ; + datanoise_array.Resize(nx,log(datanoise)); + + } + + /*******************************************************************************************************/ + + + // Get xgrid and nburn sizes + int nxgr=xgrid.XSize(); + int nburn=(int) abs(nmcmc)/fburn; + + /// Read the indices of randomized parameters + Array1D rndInd; + if (rflag){ + Array2D rndind2d; + read_datafileVS(rndind2d,rndindfile); + assert(rndind2d.YSize()==1); + array2Dto1D(rndind2d,rndInd); + } + else{ +// rndInd.Resize(0); + for (int i=0;i fixIndNom(0,2); + if (vflag){ + read_datafileVS(fixIndNom,fixindnomfile); + assert (fixIndNom.YSize()==2); + } + + // Output containers + Array1D mapparam,pmean_map,pvar_map, fmean_map,fvar_map; + Array1D datavar_map; + Array1D p_postave_mean(pdim), p_postave_var(pdim), p_postvar_mean(pdim); + Array2D f_postsam_mean(nxgr,0); + Array1D f_postave_mean(nxgr), f_postave_var(nxgr), f_postvar_mean(nxgr); + Array1D postave_datavar; + Array2D pmeans,pvars,fmeans,fvars,datavars,paramPCcfs; + + + map (*)(Array2D&, Array2D&, Array2D&, void *) > func_dict; + func_dict["prop"] = Func_Prop; + func_dict["prop_quad"] = Func_PropQuad; + func_dict["exp"] = Func_Exp; + func_dict["exp_quad"] = Func_ExpQuad; + func_dict["const"] = Func_Const; + func_dict["linear"] = Func_Linear; + func_dict["bb"] = Func_BB; + func_dict["heat_transfer1"] = Func_HT1; + func_dict["heat_transfer2"] = Func_HT2; + func_dict["frac_power"] = Func_FracPower; + func_dict["exp_sketch"] = Func_ExpSketch; + func_dict["inp"] = Func_Inputs; + func_dict["pcl"] = Func_PCl; + func_dict["pcx"] = Func_PCx; + func_dict["pc"] = Func_PC; + func_dict["pcs"] = Func_PCs; + + + if (func_dict.count(modeltype)==0){ + cout << "Model type " << modeltype << " is not found. Exiting." << endl; + exit(1); + } + Array2D (*forwardFunc)(Array2D&, Array2D&, Array2D&, void *); + forwardFunc=func_dict[modeltype]; + + int nf=1; + Array1D< Array2D (*)(Array2D&, Array2D&, Array2D&, void *) > forwardFuncs(nf,NULL); + forwardFuncs(0)=forwardFunc; + //forwardFuncs(1)=func_dict["prop"]; + + Array1D chstart,chsig; + getCol(chaininit, 0, chstart); + getCol(chaininit, 1, chsig); + bool optimflag=zflag; + + //int seed=SEED; + srand (time(NULL)); + int seed=rand(); + cout << "Random seed : " << seed << endl; + + int pred_mode=0; + void* funcinfo=(void*) &pred_mode; + /// Run the inference + infer_model(forwardFuncs,funcinfo, + liktype, + priortype,priora,priorb, + xdata,ydata, xgrid, + dataNoiseInference,datanoise_array, + pdim,order,rndInd,fixIndNom,pdftype,pctype, + seed,nmcmc,mcmcgamma, optimflag,chstart, chsig, + likParam_dbl,likParam_int, + pgrid, pchain, nburn, nstep, + mapparam, datavar_map, + pmean_map,pvar_map, + fmean_map,fvar_map, + postave_datavar, + p_postave_mean,p_postave_var,p_postvar_mean, + f_postsam_mean,f_postave_mean,f_postave_var,f_postvar_mean, + paramPCcfs); + + /// Write the outputs + if (!pflag){ + write_datafile(pchain,"pchain.dat"); + write_datafile_1d(mapparam,"mapparam.dat"); + } + + array1Dto2D(p_postave_mean, pmeans); + pmeans.insertCol(pmean_map,1); + write_datafile(pmeans,"pmeans.dat"); + array1Dto2D(p_postave_var, pvars); + pvars.insertCol(p_postvar_mean,1); + pvars.insertCol(pvar_map,2); + write_datafile(pvars,"pvars.dat"); + + array1Dto2D(f_postave_mean, fmeans); + fmeans.insertCol(fmean_map,1); + write_datafile(fmeans,"fmeans.dat"); + array1Dto2D(f_postave_var, fvars); + fvars.insertCol(f_postvar_mean,1); + fvars.insertCol(fvar_map,2); + write_datafile(fvars,"fvars.dat"); + array1Dto2D(postave_datavar,datavars); + datavars.insertCol(datavar_map,1); + write_datafile(datavars,"datavars.dat"); + + write_datafile(f_postsam_mean,"fmeans_sams.dat"); + write_datafile(paramPCcfs,"parampccfs.dat"); + + + return 0; +} + diff --git a/cpp/app/pce_eval/CMakeLists.txt b/cpp/app/pce_eval/CMakeLists.txt new file mode 100644 index 00000000..4b51a368 --- /dev/null +++ b/cpp/app/pce_eval/CMakeLists.txt @@ -0,0 +1,57 @@ +project (UQTk) + +add_executable (pce_eval pce_eval.cpp) + +target_link_libraries (pce_eval uqtkpce ) +target_link_libraries (pce_eval uqtkquad ) +target_link_libraries (pce_eval uqtktools) +target_link_libraries (pce_eval uqtkarray) + +target_link_libraries (pce_eval depdsfmt ) +target_link_libraries (pce_eval depcvode ) +target_link_libraries (pce_eval depnvec ) +target_link_libraries (pce_eval depslatec) +target_link_libraries (pce_eval deplapack) +target_link_libraries (pce_eval depblas ) +target_link_libraries (pce_eval depfigtree ) +target_link_libraries (pce_eval depann ) + + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (pce_eval gfortran stdc++) + else() + target_link_libraries (pce_eval ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (pce_eval ifcore) + else() + target_link_libraries (pce_eval ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (pce_eval gfortran stdc++) + else() + target_link_libraries (pce_eval ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) + + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS pce_eval DESTINATION bin) + diff --git a/cpp/app/pce_eval/pce_eval.cpp b/cpp/app/pce_eval/pce_eval.cpp new file mode 100644 index 00000000..8d890523 --- /dev/null +++ b/cpp/app/pce_eval/pce_eval.cpp @@ -0,0 +1,315 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file pce_eval.cpp +/// \author K. Sargsyan 2012 - +/// \brief Command-line utility for PC-related evaluations + +#include + +#include "PCSet.h" +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" + +using namespace std; + + + +/// default function type +#define FCNTYPE "PC" +/// default PC order +#define PCORD 1 +/// default parameter file +#define PARAMFILE "pccf.dat" +/// default a parameter +#define AA 0.0 +/// default b parameter +#define BB 1.0 +/// default c parameter +#define CC 0.0 +/// default d parameter +#define DD 1.0 +/// default string parameter # 1 +#define STR1 "HG" +/// default string parameter # 2 +#define STR2 "mindex.dat" + + +/// \brief Evaluates a PC given dimensionality, order, and coefficients array +void fEval_PC(Array2D& xdata, Array1D& ydata, int pcdim, int pcord, Array1D& c_k, char* pcType, double alpha, double beta); +/// \brief Evaluates a PC given multiindex file and coefficients array +void fEval_PCmi(Array2D& xdata, Array1D& ydata, Array1D& c_k, char* pcType, char* miFile, double alpha, double beta); +/// \brief Maps given points according to PC maps, i.e. if x=PC1(\xi) and y=PC2(\xi), this function is y=PC2( PC1^{-1} (x) ) +void fEval_PCmap(Array2D& xdata, Array1D& ydata, string pcIn, double a,double b, string pcOut, double c,double d); + +/******************************************************************************/ +/// \brief Displays information about this program +int usage(){ + printf("usage: pce_eval [-h] [-x] [-o] [-f] [-a] [-b] [-c] [-d] [-s] [-r]\n"); + printf(" -h : print out this help message \n"); + printf(" -x : define the type of fcn (default=%s) \n",FCNTYPE); + printf(" -o : define the PC order(default=%d) \n",PCORD); + printf(" -f : point to parameter file, if any (default=%s) \n",PARAMFILE); + printf(" -a : define the double parameter #1 (default=%lg) \n",AA); + printf(" -b : define the double parameter #2 (default=%lg) \n",BB); + printf(" -c : define the double parameter #3 (default=%lg) \n",CC); + printf(" -d : define the double parameter #4 (default=%lg) \n",DD); + printf(" -s : define the string parameter #1 (default=%s) \n",STR1); + printf(" -r : define the string parameter #2 (default=%s) \n",STR2); + + printf("================================================================================\n"); + printf("Input : xdata.dat \n"); + printf("Output : ydata.dat - function evaluations at xdata.dat \n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + +/// Main program: evaluates PC-related functions +/// \todo Make the input arguments more transparent, i.e. what do they mean in different scenarios? +int main (int argc, char *argv[]) +{ + /// Set the default values + char* fcn_type = (char *)FCNTYPE ; + int pcord=PCORD; + char* param_file = (char *)PARAMFILE; + double a=AA; + double b=BB; + double c=CC; + double d=DD; + char* str1=(char *)STR1; + char* str2=(char *)STR2; + + bool oflag=false; + bool fflag=false; + bool aflag=false; + bool bflag=false; + bool cflag=false; + bool dflag=false; + bool sflag=false; + bool rflag=false; + + /// Read the user input + int ch; + + while ((ch=getopt(argc,(char **)argv,"hx:o:f:a:b:c:d:s:r:"))!=-1){ + switch (ch) { + case 'h': + usage(); + break; + case 'x': + fcn_type = optarg; + break; + case 'o': + oflag=true; + pcord = strtol(optarg, (char **)NULL,0); + break; + case 'f': + fflag=true; + param_file = optarg; + break; + case 'a': + aflag=true; + a = strtod(optarg, (char **)NULL); + break; + case 'b': + bflag=true; + b = strtod(optarg, (char **)NULL); + break; + case 'c': + cflag=true; + c = strtod(optarg, (char **)NULL); + break; + case 'd': + dflag=true; + d = strtod(optarg, (char **)NULL); + break; + case 's': + sflag=true; + str1 = optarg; + break; + case 'r': + rflag=true; + str2 = optarg; + break; + default : + break; + } + } + + /// Print the input information on screen + fprintf(stdout,"fcn_type = %s \n",fcn_type); + if (oflag) + fprintf(stdout,"pcord = %d \n",pcord); + if (fflag) + fprintf(stdout,"param_file = %s \n",param_file); + if (aflag) + fprintf(stdout,"a = %lg \n",a); + if (bflag) + fprintf(stdout,"b = %lg \n",b); + if (cflag) + fprintf(stdout,"c = %lg \n",c); + if (dflag) + fprintf(stdout,"d = %lg \n",d); + if (sflag) + fprintf(stdout,"str1 = %s \n",str1); + if (rflag) + fprintf(stdout,"str2 = %s \n",str2); + +/*----------------------------------------------------------------------------*/ + + /// Read the input data + Array2D xdata; + read_datafileVS(xdata,"xdata.dat"); + // Create output container + Array1D ydata; + + /// Check which function is requested and compute it + if (string(fcn_type) =="PC"){ + Array2D c_k_; + read_datafileVS(c_k_,param_file); + Array1D c_k; + array2Dto1D(c_k_,c_k); + fEval_PC(xdata,ydata, xdata.YSize(), pcord, c_k, str1,a, b); + } + else if (string(fcn_type) =="PC_mi"){ + Array2D c_k_; + read_datafileVS(c_k_,param_file); + Array1D c_k; + array2Dto1D(c_k_,c_k); + fEval_PCmi(xdata,ydata, c_k, str1,str2,a, b); + } + else if (string(fcn_type) =="PCmap") + fEval_PCmap(xdata,ydata,string(str1),a,b,string(str2),c,d); + else + throw Tantrum("pce_eval.cpp::Function type is not recognized"); + + /// Write the resulting array to a file + write_datafile_1d(ydata,"ydata.dat"); + + + return ( 0 ) ; + +} + +/// \brief Evaluates a PC given dimensionality, order, and coefficients array +/// \param[in] xdata : Input samples +/// \param[out] ydata : Output array +/// \param[in] ndim : PC dimesnionality +/// \param[in] nord : PC order +/// \param[in] c_k : Coefficient array +/// \param[in] pcType : PC type +/// \param[in] alpha : PC parameter #1 +/// \param[in] beta : PC parameter #2 +void fEval_PC(Array2D& xdata, Array1D& ydata, int ndim, int nord, Array1D& c_k, char* pcType, double alpha, double beta) +{ + + /// Get the number of input points and appropriately resize the output array + int ns=xdata.XSize(); + ydata.Resize(ns); + + /// Sanity check of dimensionality + if (ndim != (int) xdata.YSize()) + throw Tantrum("fEval_PC(): the input data does not have the requested dimensionality"); + + /// Declare the PC object + PCSet currPCModel("NISPnoq",nord,ndim,pcType,alpha, beta); + /// Get the number of terms + int npc=currPCModel.GetNumberPCTerms(); + assert(npc==c_k.Length()); + + /// Evaluate the PC expansion + currPCModel.EvalPCAtCustPoints(ydata,xdata,c_k); + + return; + +} + +/// \brief Evaluates a PC given multiindex file and coefficients array +/// \param[in] xdata : Input samples +/// \param[out] ydata : Output array +/// \param[in] c_k : Coefficient array +/// \param[in] pcType : PC type +/// \param[in] nord : PC multiindex array +/// \param[in] alpha : PC parameter #1 +/// \param[in] beta : PC parameter #2 +void fEval_PCmi(Array2D& xdata, Array1D& ydata, Array1D& c_k, char* pcType, char* miFile, double alpha, double beta) +{ + /// Read the multiindex given the file + Array2D mindex; + read_datafileVS(mindex,miFile); + + /// Get the number of input points and appropriately resize the output array + int ns=xdata.XSize(); + ydata.Resize(ns); + + /// Sanity check of dimensionality + if (mindex.YSize() != xdata.YSize()) + throw Tantrum("fEval_PCmi(): the input data and the multiindex do not have the same dimensionality"); + + /// Declare the PC object + PCSet currPCModel("NISPnoq",mindex,pcType,alpha, beta); + + /// Get the number of terms + int npc=currPCModel.GetNumberPCTerms(); + assert(npc==c_k.Length()); + + + /// Evaluate the PC expansion + currPCModel.EvalPCAtCustPoints(ydata,xdata,c_k); + + return; + +} + +/// \brief Maps given points according to PC maps, i.e. if x=PC1(\xi) and y=PC2(\xi), this function is y=PC2( PC1^{-1} (x) ) +/// \param[in] xdata : Input samples +/// \param[out] ydata : Output array +/// \param[in] pcIn : Input PC type (PC1) +/// \param[in] a : Input PC parameter #1 +/// \param[in] b : Input PC parameter #2 +/// \param[in] pcOut : Output PC type (PC2) +/// \param[in] c : Output PC parameter #1 +/// \param[in] d : Output PC parameter #2 +void fEval_PCmap(Array2D& xdata, Array1D& ydata, string pcIn, double a,double b, string pcOut, double c,double d) +{ + + /// Get the number of input points and appropriately resize the output array + int ns=xdata.XSize(); + int ndim=xdata.YSize(); + ydata.Resize(ns); + + /// Ensure dimensionality = 1 + if (ndim!=1) + throw Tantrum("fEval_PCmap():Only one-dimensional case is implemented for PCmap!"); + + /// Compute the PC map using function in pcmaps.cpp + for(int i=0;i. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file pce_quad.cpp +/// \author K. Sargsyan 2012 - +/// \brief Command-line utility for PC construction given samples + +#include "PCSet.h" +#include "tools.h" +#include "arraytools.h" +#include "arrayio.h" +#include + +using namespace std; + + + +/// default PC order +#define ORD 1 +/// default bandwidth for Rosenblatt transformation +#define BWDTH 0.01 +/// default input filename +#define FILEIN "data_in.dat" +/// default chaos type +#define CHAOS "LU" +/// default PC parameter #1 +#define ALPHA 0.0 +/// default PC parameter #2 +#define BETA 1.0 + + +/// diagnostic: frequency of showing progress of Galerkin projection +#define DIAG_GP 1000 + +/******************************************************************************/ +/// Displays information about this program +int usage(){ + printf("This program to find PC coefficients of a given set of data.\n"); + printf("usage: pce_quad [-h] [-o] [-f] [-w] [-x] [-a] [-b]\n"); + printf(" -h : print out this help message \n"); + printf(" -o : define the PC order (default=%d) \n",ORD); + printf(" -f : define the filename with input data (default=%s) \n",FILEIN); + printf(" -w : define sigma for Rosenblatt, if this is non-positive it finds the rule-of-thumb automatically(default=%lg) \n",BWDTH); + printf(" -x : define the PC type (default=%s) \n",CHAOS); + printf(" -a : chaos parameter #1 (default=%lg) \n",ALPHA); + printf(" -b : chaos parameter #2 (default=%lg) \n",BETA); + printf("================================================================================\n"); + printf("Input : None \n"); + printf("Output : PCcoeff.dat - PC coefficient file \n"); + printf("Output : mindex.dat - Multi-indices file \n"); + printf("--------------------------------------------------------------------------------\n"); + printf("Comments :\n"); + printf("Complexity: linear wrt number of samples, exponential wrt dimensionality.\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + +/// Program to find PC coefficient of a random variable given a set of data samples +int main(int argc, char *argv[]) +{ + + /// Set the defaults and parse the input arguments + int nord = ORD; + char* file_in=(char *)FILEIN; + double bw = BWDTH; + char* which_chaos=(char *)CHAOS; + double alpha = ALPHA; + double beta = BETA; + + int c; + + while ((c=getopt(argc,(char **)argv,"ho:f:w:x:a:b:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'o': + nord = strtol(optarg, (char **)NULL,0); + break; + case 'f': + file_in = optarg; + break; + case 'w': + bw = strtod(optarg, (char **)NULL); + break; + case 'x': + which_chaos = optarg; + break; + case 'a': + alpha = strtod(optarg, (char **)NULL); + break; + case 'b': + beta = strtod(optarg, (char **)NULL); + break; + default : + break; + } + } + + /// Print the input information + fprintf(stdout,"---------------------------------\n") ; + fprintf(stdout,"pce_quad() parameters : \n") ; + fprintf(stdout,"nord = %d \n",nord); + fprintf(stdout,"file_in = %s \n",file_in); + fprintf(stdout,"bw = %lg \n",bw); + fprintf(stdout,"which_chaos = %s \n",which_chaos); + fprintf(stdout,"---------------------------------\n") ; + + /// Read the input datafile and get its size + Array2D ydata; + read_datafileVS(ydata,file_in); + int nsample=ydata.XSize(); + int nvar=ydata.YSize(); + + /// For the projection based PC (unlike the inference), the data dimensionality has to coincide with the stochastic dimension + int ndim=nvar; + + /// Set the chaos + string which_chaos_str(which_chaos); + PCSet PCModel("NISP",nord,ndim,which_chaos_str,alpha,beta); + int npc=PCModel.GetNumberPCTerms(); + + /// Get the default quadrature points + Array2D qdpts; + PCModel.GetQuadPoints(qdpts); + int totquad=PCModel.GetNQuadPoints(); + write_datafile(qdpts,"quadpts.dat"); + + /// Transpose the data array to prepare for invRos() + Array2D ydata_t(nvar,nsample,0.e0); + transpose(ydata,ydata_t); + + /// Array to contain inverse-Rosenblatt transformed points + Array2D invRosData(totquad,ndim,0.e0); + + /// Frequency of showing Galerkin projection progress + int iiout=DIAG_GP; + + /// Begin Loop over all quadrature points + for(int it=0;it quadunif(ndim,0.e0); + Array1D invRosData_1s(ndim,0.e0); + + /// Map quadrature points to uniform[0,1] + for(int id=0;id0) + invRos(quadunif,ydata_t,invRosData_1s,bw); + else + invRos(quadunif,ydata_t,invRosData_1s); + + // Diagnostic output + if ((it/iiout)*iiout==it) + fprintf(stdout,"invRos for Galerkin projection: %d/%d=%d%% completed\n",it,totquad,it*100/totquad); + + // Store the results + for(int idim=0;idim) + Array2D c_k(npc,nvar,0.e0); // remember, above we defined nvar=ndim + + for(int idim=0;idim c_k_1d(npc,0.e0); + Array1D invRosData_1d(totquad,0.e0); + for(int it=0;it mindex; + PCModel.GetMultiIndex(mindex); + write_datafile(mindex,"mindex.dat"); + + return 0; + +} + + diff --git a/cpp/app/pce_resp/CMakeLists.txt b/cpp/app/pce_resp/CMakeLists.txt new file mode 100644 index 00000000..7b0f97c7 --- /dev/null +++ b/cpp/app/pce_resp/CMakeLists.txt @@ -0,0 +1,56 @@ +project (UQTk) + +add_executable (pce_resp pce_resp.cpp) + +target_link_libraries (pce_resp uqtkpce ) +target_link_libraries (pce_resp uqtkquad ) +target_link_libraries (pce_resp uqtktools) +target_link_libraries (pce_resp uqtkarray) + +target_link_libraries (pce_resp depdsfmt ) +target_link_libraries (pce_resp depcvode ) +target_link_libraries (pce_resp depnvec ) +target_link_libraries (pce_resp depslatec) +target_link_libraries (pce_resp deplapack) +target_link_libraries (pce_resp depblas ) +target_link_libraries (pce_resp depfigtree ) +target_link_libraries (pce_resp depann ) + + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (pce_resp gfortran stdc++) + else() + target_link_libraries (pce_resp ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (pce_resp ifcore) + else() + target_link_libraries (pce_resp ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (pce_resp gfortran stdc++) + else() + target_link_libraries (pce_resp ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS pce_resp DESTINATION bin) + diff --git a/cpp/app/pce_resp/pce_resp.cpp b/cpp/app/pce_resp/pce_resp.cpp new file mode 100644 index 00000000..846846b4 --- /dev/null +++ b/cpp/app/pce_resp/pce_resp.cpp @@ -0,0 +1,205 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file pce_resp.cpp +/// \author K. Sargsyan 2012 - +/// \brief Command-line utility for PC orthogonal projection + +#include "PCSet.h" +#include "tools.h" +#include +#include "arrayio.h" +#include + +using namespace std; + + +/// default PC type +#define CHAOS "LEG" +/// default data dimensionality +#define DIM 2 +/// default PC order +#define ORD 3 +///default alpha parameter for PC +#define ALPHA 0.0 +/// default beta parameter for PC +#define BETA 1.0 + + + +/******************************************************************************/ +/// Displays information about this program +int usage(){ + printf("usage: pce_resp [-h] [-e] [-x] [-d] [-o] [-a] [-b]\n"); + printf(" -h : print out this help message \n"); + printf(" -e : flag if we want to evaluate PC representation at the quadrature points and get the error \n"); + printf(" -x : define the PC type (default=%s) \n",CHAOS); + printf(" -d : define the data dimensionality (default=%d) \n",DIM); + printf(" -o : define the PC order (default=%d) \n",ORD); + printf(" -a : define the alpha parameter of the quadrature (default=%lg) \n",ALPHA); + printf(" -b : define the beta parameter of the quadrature (default=%lg) \n",BETA); + printf("================================================================================\n"); + printf("Input : qdpts.dat - quadrature points \n"); + printf(" : wghts.dat - quadrature weights\n"); + printf(" : ydata.dat - function evaluations corresponding to quadrature points\n"); + printf("Output : PCcoeff_quad.dat - PC coefficients\n"); + printf(" : ydata_pc.dat - PC response at the quadrature points\n"); + printf("--------------------------------------------------------------------------------\n"); + printf("Todo : Add an option to use the default quadrature for a given PC \n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + + +/// Main program: gets PC coefficients of a response curve given function evaluations at a grid +int main (int argc, char *argv[]) { + + /// Set the defaults and parse the input arguments + int ndim= DIM; + int nord= ORD; + char* which_chaos=(char *)CHAOS; + double alpha=ALPHA; + double beta =BETA; + + bool eflag=false; + bool aflag=false; + bool bflag=false; + + int c; + + while ((c=getopt(argc,(char **)argv,"hex:d:o:a:b:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'e': + eflag=true; + break; + case 'x': + which_chaos = optarg; + break; + case 'd': + ndim = strtol(optarg, (char **)NULL,0); + break; + case 'o': + nord = strtol(optarg, (char **)NULL,0); + break; + case 'a': + aflag=true; + alpha = strtod(optarg, (char **)NULL); + break; + case 'b': + bflag=true; + beta = strtod(optarg, (char **)NULL); + break; + default : + break; + } + } + + /// Print the input information + fprintf(stdout,"---------------------------------\n") ; + fprintf(stdout,"pce_resp() parameters : \n") ; + fprintf(stdout,"which_chaos = %s \n",which_chaos); + fprintf(stdout,"ndim = %d \n",ndim); + fprintf(stdout,"nord = %d \n",nord); + if ( aflag ) + fprintf(stdout,"alpha = %lg \n",alpha); + if ( bflag ) + fprintf(stdout,"beta = %lg \n",beta); + if ( eflag ) + fprintf(stdout,"will compute the L_2 error, too.\n"); + fprintf(stdout,"---------------------------------\n") ; + + + /// Read the ydata evaluated at quadrature points + Array2D ydata_2d; + read_datafileVS(ydata_2d,"ydata.dat"); + Array1D ydata; + for(int i=0;i<(int) ydata_2d.XSize();i++) + ydata.PushBack(ydata_2d(i,0)); + + /// Read the quadrature rule + Array2D qdpts; + Array1D wghts; + Array2D indices; + + read_datafileVS(qdpts,"qdpts.dat"); + wghts.Resize(qdpts.XSize()); + indices.Resize(qdpts.XSize(),qdpts.YSize()); + read_datafile_1d(wghts,"wghts.dat"); + // read_datafile_1d(indices,"indices.dat"); + + /// Set the chaos + string which_chaos_str(which_chaos); + /// Declare PC model with no quadrature + PCSet currPCModel("NISPnoq",nord,ndim,which_chaos_str,alpha,beta); + + + /// Set the quadrature rule + Quad spRule; + spRule.SetRule(qdpts,wghts,indices); + currPCModel.SetQuadRule(spRule); + int nup=currPCModel.GetNumberPCTerms()-1; + int totquad=currPCModel.GetNQuadPoints(); + + /// Get the multiindex for postprocessing + Array2D mindex; + currPCModel.GetMultiIndex(mindex); + write_datafile(mindex,"mindex.dat"); + + /// Get PC coefficients by Galerkin Projection (c_k=) + Array1D c_k(nup+1,0.e0); + currPCModel.GalerkProjection(ydata,c_k); + write_datafile_1d(c_k,"PCcoeff_quad.dat"); + + /// If requested, compute the L2 error at quadrature points + /// \note Note that the error is computed with the same quadrature rule, and may be inaccurate + /// \todo Perhaps only compute simpler, l2 norm of the error without involving weights + if (eflag){ + // Evaluate the PC expansion at quadrature points + Array1D pcxvalues(totquad,0.e0); + currPCModel.EvalPCAtCustPoints(pcxvalues,qdpts,c_k); + // Write-out + write_datafile_1d(pcxvalues,"ydata_pc.dat"); + + double sum1=0.0, sum2=0.0; + for(int it=0;it. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file pce_rv.cpp +/// \author K. Sargsyan 2014 - +/// \brief Command-line utility for PC-related random variable generation + +#include +#include + +#include "PCSet.h" +#include "tools.h" +#include "arrayio.h" + +using namespace std; + + + +/// default r.v. type +#define RVTYPE "PCvar" +/// default r.v. dimensionality +#define DIM 1 +/// default number of samples +#define SAMPLE 1000 +/// default PC dimensionality +#define PCDIM 1 +/// default PC order +#define PCORD 3 +/// default parameter file +#define PARAMFILE "pccf.dat" +/// default first parameter of PC, if needed +#define AA 0.0 +/// default second parameter of PC, if needed +#define BB 1.0 +/// default multiindex file +#define MIFILE "mi.dat" +/// default seed +#define SEED 1 +/// default string parameter +#define STRPARAM "LEG" + + + +/// \brief Displays information about this program +/// \todo Add more detailed information on options. E.g. what are the different options for type of random variable? +/// When does the order need to be specified? +int usage(){ + printf("usage: pce_rv [-h] [-w] [-d] [-n] [-p] [-o] [-f] [-a] [-b] [-s] [-x] [-m]\n"); + printf(" -h : print out this help message \n"); + printf(" -w : define the type of r.v.(default=%s) \n",RVTYPE); + printf(" -d : define the r.v. dimensionality (default=%d) \n",DIM); + printf(" -n : define number of samples (default=%d) \n",SAMPLE); + printf(" -p : define the PC dimensionality (default=%d) \n",PCDIM); + printf(" -o : define the PC order (default=%d) \n",PCORD); + printf(" -f : define a parameter file (default=%s) \n",PARAMFILE); + printf(" -a : define the double parameter #1 (default=%lg) \n",AA); + printf(" -b : define the double parameter #2 (default=%lg) \n",BB); + printf(" -s : define the seed (default=%d) \n",SEED); + printf(" -x : define string a parameter(default=%s) \n",STRPARAM); + printf(" -m : define multiindex file name(default=%s) \n",MIFILE); + + printf("================================================================================\n"); + printf("Input : None \n"); + printf("Output : rvar.dat - random samples with format nsample x ndim\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + + +/// Main program: generates PC-related random variables +int main(int argc, char *argv[]) +{ + + /// Set the defaults and parse input arguments + int c; + + int ndim=DIM; + int nsample=SAMPLE; + int seed=SEED; + int pcdim=PCDIM; + int pcord=PCORD; + char *type = (char *)RVTYPE;; + char *paramfile = (char *)PARAMFILE; + char *xstr = (char *)STRPARAM; + char *mstr = (char *)MIFILE; + + double a = AA; + double b = BB; + + bool oflag=false; + bool fflag=false; + bool aflag=false; + bool bflag=false; + bool mflag=false; + + while ((c=getopt(argc,(char **)argv,"hw:d:n:p:o:f:a:b:x:m:s:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'w': + type = optarg; + break; + case 'd': + ndim = strtol(optarg, (char **)NULL,0); + break; + case 'n': + nsample = strtol(optarg, (char **)NULL,0); + break; + case 'p': + pcdim = strtol(optarg, (char **)NULL,0); + break; + case 'o': + oflag=true; + pcord = strtol(optarg, (char **)NULL,0); + break; + case 'f': + fflag=true; + paramfile = optarg; + break; + case 'a': + aflag=true; + a = strtod(optarg, (char **)NULL); + break; + case 'b': + bflag=true; + b = strtod(optarg, (char **)NULL); + break; + case 'x': + xstr = optarg; + break; + case 'm': + mflag=true; + mstr = optarg; + break; + case 's': + seed = strtol(optarg, (char **)NULL,0); + break; + default : + break; + } + } + + /// Print out input information + fprintf(stdout,"---------------------------------\n") ; + fprintf(stdout,"pce_rv() parameters : \n") ; + fprintf(stdout,"type = %s \n",type); + fprintf(stdout,"ndim = %d \n",ndim); + fprintf(stdout,"nsample = %d \n",nsample); + fprintf(stdout,"pcdim = %d \n",pcdim); + if (oflag) + fprintf(stdout,"pcord = %d \n",pcord); + if (fflag) + fprintf(stdout,"paramfile = %s \n",paramfile); + if (aflag) + fprintf(stdout,"a = %lg \n",a); + if (bflag) + fprintf(stdout,"b = %lg \n",b); + fprintf(stdout,"xstr = %s \n",xstr); + if (mflag) + fprintf(stdout,"mstr = %s \n",mstr); + + // Declare the samples container + Array2D rvar; + // The r.v. type cast as a string + string type_str(type); + // PC type as a string + string pcType(xstr); + // Multiindex file name + string miFile(mstr); + + + +//////////////////////////////////////////////////////////////////////// + + /// Go through options for R.V. generation + if (type_str=="PC") + { + // Resize the r.v. array + rvar.Resize(nsample,ndim,0.e0); + // Make sure the requested dimnesionality is equal to 1 + // In the future, shoud generalize this + assert(ndim==1); + + // Declare the PC object + PCSet currPCModel("NISPnoq",pcord,pcdim,pcType,a, b); + + // The number of PC basis terms + int npc=currPCModel.GetNumberPCTerms(); + + // Read the coefficient file + // Note: it has to have the correct number of entries + Array1D c_k(npc,0.e0); + read_datafile_1d(c_k,paramfile); + + // A temporary container for the samples + Array1D rvar_1d(nsample,0.e0); + // Draw sample set + currPCModel.SeedBasisRandNumGen(seed); + currPCModel.DrawSampleSet(c_k,rvar_1d); + + // Cast the 1d array as a 2d one + for(int is=0;is mindex; + read_datafileVS(mindex,mstr); + assert(pcdim==mindex.YSize()); + + // Declare the PC object + PCSet currPCModel("NISPnoq",mindex,pcType,a, b); + + // The number of PC basis terms + int npc=currPCModel.GetNumberPCTerms(); + + // Read the coefficient file + // Note: it has to have the correct number of entries + Array1D c_k(npc,0.e0); + read_datafile_1d(c_k,paramfile); + + // A temporary container for the samples + Array1D rvar_1d(nsample,0.e0); + // Draw sample set + currPCModel.SeedBasisRandNumGen(seed); + currPCModel.DrawSampleSet(c_k,rvar_1d); + + // Cast the 1d array as a 2d one + for(int is=0;is. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file pce_sens.cpp +/// \author K. Sargsyan 2014 - +/// \brief Command-line utility for Sobol sensitivity index computation given PC + +#include "PCSet.h" +#include "tools.h" +#include "arrayio.h" +#include + +using namespace std; + + + +/// default PC type +#define CHAOS "LU" +/// default multiindex file +#define MINDEX_FILE "mindex.dat" +/// default coefficient file +#define COEF_FILE "PCcoeff.dat" + + + +/// Displays information about this program +int usage(){ + printf("This program parses the information contained in given pair of multiindex-coefficients\n"); + printf("usage: pce_sens [-h] [-m] [-f] [-x]\n"); + printf(" -h : print out this help message \n"); + printf(" -x : define the PC type (default=%s) \n",CHAOS); + printf(" -m : define multiindex filename (default=%s) \n",MINDEX_FILE); + printf(" -f : define the coefficient filename (default=%s) \n",COEF_FILE); + printf("================================================================================\n"); + printf("Input : None \n"); + printf("Output : sp_mindex.X.dat - sparse format of multiindices, has 2*X columns, \n"); + printf(" - e.g. for X=3, each row has a form [i j k a_i a_j a_k] \n"); + printf(" - and corresponds to a PC term with order a_i in the i-th dimension etc. \n"); + printf(" : varfrac.dat - a column file of variance fractions corresponding to each PC term \n"); + printf(" - the size is Nx1, where N is the number of PC terms \n"); + printf(" : mainsens.dat - a columm file of main sensitivities. The size is dx1, where d is the dimensionality\n"); + printf(" : totsens.dat - a columm file of total sensitivities. The size is dx1\n"); + printf(" : jointsens.dat - a matrix file of joint sensitivities. The size is dxd\n"); + printf("--------------------------------------------------------------------------------\n"); + printf("Comments : Sparse format is useful in high-dimensional problems \n"); + printf("Complexity: Linear in the number of PC terms \n"); + printf("================================================================================\n"); + + exit(0); + return 0; +} + + +/// Main program: parses the information contained in given multiindices and corresponding coefficients +int main(int argc, char *argv[]) +{ + + /// Set the defaults and parse the input arguments + int c; + + char* mindex_file=(char *)MINDEX_FILE; + char* coef_file=(char *)COEF_FILE; + char* which_chaos=(char *)CHAOS; + + while ((c=getopt(argc,(char **)argv,"hm:f:x:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'm': + mindex_file = optarg; + break; + case 'f': + coef_file = optarg; + break; + case 'x': + which_chaos = optarg; + break; + default : + break; + } + } + + /// Print out input information + fprintf(stdout,"---------------------------------\n") ; + fprintf(stdout,"pce_sens() parameters : \n") ; + fprintf(stdout,"mindex_file = %s \n",mindex_file); + fprintf(stdout,"coef_file = %s \n",coef_file); + fprintf(stdout,"which_chaos = %s \n",which_chaos); + fprintf(stdout,"---------------------------------\n") ; + + + /// Read the multiindex and coefficients' files + Array2D mindex; + read_datafileVS(mindex,mindex_file); + int npc=mindex.XSize(); + int ndim=mindex.YSize(); + Array1D coef(npc,0.e0); + read_datafile_1d(coef,coef_file); + + + /// Declare PC in NISP formulation with no quadrature + string which_chaos_str(which_chaos); + PCSet PCModel("NISPnoq",mindex,which_chaos_str,0.0,1.0); + + /// Encode the multiindex in a sparse format and print to files + Array1D< Array2D > sp_mindex; + PCModel.EncodeMindex(sp_mindex); + + char filename[25]; + for (int i=1;i<(int)sp_mindex.XSize();i++){ + int nn=sprintf(filename,"sp_mindex.%d.dat",i); + write_datafile(sp_mindex(i),filename); + } + + + /// Compute mean and variance of PC and variance fractions for each term + Array1D varfrac; + double mean, var; + + mean=PCModel.ComputeMean(coef); + var=PCModel.ComputeVarFrac(coef,varfrac); + cout << "Mean = " << mean << endl; + cout << "Var = " << var << endl; + write_datafile_1d(varfrac,"varfrac.dat"); + + /// Compute main sensitivities + Array1D mainsens; + PCModel.ComputeMainSens(coef,mainsens); + write_datafile_1d(mainsens,"mainsens.dat"); + + /// Compute total sensitivities + Array1D totsens; + PCModel.ComputeTotSens(coef,totsens); + write_datafile_1d(totsens,"totsens.dat"); + + /// Compute joint sensitivities + Array2D jointsens; + PCModel.ComputeJointSens(coef,jointsens); + for(int id=0;id. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file pdf_cl.cpp +/// \author K. Sargsyan, C. Safta 2013 - +/// \brief Command-line utility for KDE given samples + +#include +#include +#include +#include +#include +#include + + +//#include "ftndefs.h" +#include +#include "Array1D.h" +#include "Array2D.h" + +#include "assert.h" + +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" + +using namespace std; + + + +/// default input file +#define FILE_IN "data_in.dat" +/// default number of grid pts in each dimension +#define GRID 100 +/// default number of clusters +#define N_CL 1 +/// default bandwidth scale factor +#define BFAC 1.0 + +/// Displays information about this program +int usage(){ + printf("usage: pdf_cl [-h] [-i ] [-k ] [-g ] [-l ] [-f ] [-x] \n"); + printf(" -h : print out this help message \n"); + printf(" -i : data file (default=%s) \n",FILE_IN); + printf(" -k : define number of clusters, 0 means find the optimal (default=%d) \n",N_CL); + printf(" -g : define number of grid pts in each dimension (default=%d) \n",GRID); + printf(" -l : define the file where the grid limits are specified \n"); + printf(" -f : bandwidth scaling factor (default=%e) \n",BFAC); + printf(" -x : define the file where the target points are specified \n"); + printf("================================================================================\n"); + printf("Input:: --\n"); + printf("Output:: File 'dens.dat'(makes sense to plot only for ndim=1,2)\n"); + printf("--------------------------------------------------------------------------------\n"); + printf("Comments:\n a) pdf computation is based on clustering and KDE.\n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + + +/// Program to compute PDF via KDE given samples +int main(int argc, char *argv[]) +{ + + /// Read the user input + int ndim,nsample,ngrid,ncl; + int c; + double bfac; + + char *filename = FILE_IN ; + char *targetfile; + char *limsfile; + + bool gflag = false; + bool xflag = false; + bool lflag = false; + + ngrid = GRID; + ncl = N_CL; + bfac = BFAC; + + while ((c=getopt(argc,(char **)argv,"hi:g:l:x:k:f:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'i': + filename = optarg; + break; + case 'g': + ngrid = strtol(optarg, (char **)NULL,0); + gflag = true; + break; + case 'l': + limsfile = optarg; + lflag = true; + break; + case 'x': + targetfile = optarg; + xflag = true; + break; + case 'k': + ncl = strtol(optarg, (char **)NULL,0); + break; + case 'f': + bfac = strtod(optarg, (char **)NULL); + break; + default : + break; + } + } + + /// Input checks + if (lflag && xflag){ + printf("Please do not specify both grid limits(-l) and a filename of the target points(-x)\n"); + exit(1); + } + + if (gflag && xflag){ + printf("Please do not specify both the number of grid points(-g) and a filename of the target points(-x)\n"); + exit(1); + } + + + Array2D data; + read_datafileVS(data,filename); + nsample = data.XSize(); + ndim = data.YSize(); + + int totpts; + Array2D points; + + + if (xflag) { + read_datafileVS(points,targetfile); + assert(ndim == (int)points.YSize()); + } + + /// Prepare grid + else{ + + Array1D data_1d(nsample,0.e0); + double min,max; + + Array2D grid(ngrid,ndim,0.e0) ; + + + Array2D lims ; + if (lflag) { + read_datafileVS(lims,limsfile); + assert(ndim == (int)lims.XSize()); + assert(2 == (int)lims.YSize()); + } + + for(int idim=0; idim dens(totpts,0.e0); + getPdf_cl(data,points,dens,ncl,bfac); + + /// Write PDF to file + FILE* fdens; + fdens=fopen("dens.dat","w"); + for (int it = 0; it < totpts; it++){ + for(int idim = 0; idim < ndim; idim++){ + fprintf(fdens,"%f ",points(it,idim)); + } + fprintf(fdens,"%f \n",dens(it)); + //if (gflag && (it+1)%ngrid==0) fprintf(fdens,"\n"); + } + fclose(fdens); + + return (0); + +} + + + diff --git a/cpp/app/regression/CMakeLists.txt b/cpp/app/regression/CMakeLists.txt new file mode 100644 index 00000000..99dc6afe --- /dev/null +++ b/cpp/app/regression/CMakeLists.txt @@ -0,0 +1,65 @@ +project (UQTk) + +add_executable (regression regression.cpp) + +target_link_libraries (regression uqtklreg ) +target_link_libraries (regression uqtkpce ) +target_link_libraries (regression uqtkbcs ) +target_link_libraries (regression uqtkquad ) +target_link_libraries (regression uqtktools) +target_link_libraries (regression uqtkarray) + +target_link_libraries (regression depdsfmt ) +target_link_libraries (regression deplbfgs ) +target_link_libraries (regression depcvode ) +target_link_libraries (regression depnvec ) +target_link_libraries (regression depslatec) +target_link_libraries (regression deplapack) +target_link_libraries (regression depblas ) +target_link_libraries (regression depfigtree ) +target_link_libraries (regression depann ) + + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (regression gfortran stdc++) + else() + target_link_libraries (regression ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (regression ifcore) + target_link_libraries (regression ifport) + else() + target_link_libraries (regression ${IntelLibPath}/libifcore.a) + target_link_libraries (regression ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (regression gfortran stdc++) + else() + target_link_libraries (regression ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/bcs ) +include_directories(../../lib/lreg ) + + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS regression DESTINATION bin) + diff --git a/cpp/app/regression/regression.cpp b/cpp/app/regression/regression.cpp new file mode 100644 index 00000000..05b20f0c --- /dev/null +++ b/cpp/app/regression/regression.cpp @@ -0,0 +1,400 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file regression.cpp +/// \author K. Sargsyan 2015 - +/// \brief Command-line utility for linear regression + +#include +#include +#include +#include +#include +#include + +#include "Array1D.h" +#include "Array2D.h" +#include "PCSet.h" +#include "lreg.h" +#include +#include "tools.h" +#include "arraytools.h" +#include "arrayio.h" + +using namespace std; + + +/// default x-file +#define XFILE "xdata.dat" +/// default y-file +#define YFILE "ydata.dat" +/// default basis type +#define BTYPE "PC" +/// default method +#define METH "lsq" +/// default flag to output mean (m), mean+std (ms) or mean+std+cov (msc) +#define MSC "m" +/// default int parameter +#define INTPAR 5 +/// default string parameter +#define STRPAR "LU" +/// default multiindex file +#define MINDEXFILE "mindex.dat" +/// default tolerance for bcs +#define ETADEFAULT 1.e-3 + + +/******************************************************************************/ +/// Displays information about this program +int usage(){ + printf("usage: regression [-h] [-x] [-y] [-b] [-r] [-m] [-t] "); + printf("[-o] [-l] [-s] [-p] [-e] [-w]\n"); + + printf(" -h : print out this help message \n"); + + printf(" -x : xdata filename, matrix Nxd (default=%s) \n",XFILE); + printf(" -y : ydata filename, matrix Nxe (default=%s) \n",YFILE); + printf(" -b : basistype - RBF, PC, PC_MI, POL, POL_MI (default=%s) \n",BTYPE); + printf(" -r : regression method - lsq, wbcs (default=%s) \n",METH); + printf(" -m : output mode - m (only mean), ms (mean and var), msc (mean and cov) (default=%s) \n",MSC); + printf(" -t : optional filename of x-values for validation/plotting \n"); + printf(" -o : integer parameter (order for PC and POL) (default=%d) \n",INTPAR); + printf(" -l : optional double parameter (for lsq: regularization lambda, if not given then finds the best) \n"); + printf(" : (for wbcs: regularization lambda, if not given then a file for weights has to be given in -w) \n"); + printf(" -s : string parameter (PCtype for PC and PC_MI) (default=%s) \n",STRPAR); + printf(" -c : tolerance for BCS algorithm (default=%e) \n",ETADEFAULT); + printf(" -p : multiindex file name (relevant for PC_MI and POL_MI) (default=%s) \n",MINDEXFILE); + printf(" -e : optional file name for RBF centers, if not given then centers are at data\n"); + printf(" -w : optional file name for weight vector in wbcs, if not given then -l has to be given\n"); + printf("================================================================================\n"); + printf("Input:: \n"); + printf("Output:: Files 'coeff.dat', 'lambdas.dat', Sigma2.dat'(if -m is ms or msc), 'Sig.dat'(if -m is ms or msc), ycheck.dat', ycheck_var.dat'(if -m is ms or msc), 'errors.dat'(if -r is lsq), 'selected.dat', 'mindex_new.dat' (if -r is wbcs)].\n"); + printf("--------------------------------------------------------------------------------\n"); + //printf("Comments: None yet.\n"); + //printf("Complexity: Not tested yet.\n"); + //printf("Todo: \n"); + printf("================================================================================\n"); + exit(0); + return 0; +} + +/******************************************************************************/ + +/******************************************************************************/ +/// Main program of linear regression given data +int main (int argc, char *argv[]) { + + + /// Set the default values + char* xfile = XFILE; + char* yfile = YFILE; + char* basistype = BTYPE; + char* mindexfile = MINDEXFILE; + int intpar = INTPAR; + char* strpar=STRPAR; + char* msc = MSC; + char* meth=METH; + + char* xcheckfile; + char* centerfile; + double dblpar; + char* regparamfile; + double eta = ETADEFAULT; //higher eta, fewer terms retained + + bool lflag=false; + bool tflag=false; + bool eflag=false; + bool wflag=false; + + /// Read the user input + int cc; + + while ((cc=getopt(argc,(char **)argv,"hx:y:b:r:m:t:o:l:c:s:p:e:w:"))!=-1){ + switch (cc) { + case 'h': + usage(); + break; + case 'x': + xfile = optarg; + break; + case 'y': + yfile = optarg; + break; + case 'b': + basistype = optarg; + break; + case 'r': + meth = optarg; + break; + case 'm': + msc = optarg; + break; + case 't': + xcheckfile = optarg; + tflag=true; + break; + case 'o': + intpar = strtol(optarg, (char **)NULL,0); + break; + case 'l': + dblpar = strtod(optarg, (char **)NULL); + lflag=true; + break; + case 'c': + eta = strtod(optarg, (char **)NULL); + break; + case 's': + strpar = optarg; + break; + case 'p': + mindexfile = optarg; + break; + case 'e': + centerfile = optarg; + eflag=true; + break; + case 'w': + regparamfile = optarg; + wflag=true; + break; + default : + break; + } + } + + /// Sanity checks + if (lflag and wflag){ + printf("regression:: can not provide both -l and -w. Exiting\n") ; + exit(1); + } + + if (string(meth)=="wbcs"){ + if (!lflag and !wflag){ + printf("regression:: please provide either -l or -w for wbcs method. Exiting.\n"); + exit(1); + } + } + + + /// Print the input information on screen + fprintf(stdout,"xfile = %s \n",xfile); + fprintf(stdout,"yfile = %s \n",yfile); + fprintf(stdout,"basistype = %s \n",basistype); + fprintf(stdout,"method = %s \n",meth); + fprintf(stdout,"intpar = %d \n",intpar); + if (lflag) + fprintf(stdout,"dblpar = %lg \n",dblpar); + fprintf(stdout,"strpar = %s \n",strpar); + fprintf(stdout,"msc = %s \n",msc); + if (tflag) + fprintf(stdout,"xcheckfile = %s \n",xcheckfile); + if (eflag) + fprintf(stdout,"centerfile = %s \n",centerfile); + if (wflag) + fprintf(stdout,"regparamfile = %s \n",regparamfile); + + /*----------------------------------------------------------------------------*/ + + + + /// Read data + Array2D xdata,xcheck; + read_datafileVS(xdata,xfile); + int nx=xdata.XSize(); + int ndim=xdata.YSize(); + Array2D ydata; + + read_datafileVS(ydata,yfile); + + /// Read validation check data, if any + if (tflag) + read_datafileVS(xcheck,xcheckfile); + else + xcheck=xdata; + + /// Declare the 'parent' regression object + Lreg* reg; + + /// Go through options, RBF, PC, PC_MI, POL, POL_MI + if (string(basistype)=="RBF"){ + + Array1D a,b; + getDomain(xdata,a,b); + + Array1D widths(ndim); + for (int i=0;i centers; + if (eflag){ + read_datafileVS(centers,centerfile); + } + else + centers=xdata; + + reg=new RBFreg(centers,widths); + } + + else if (string(basistype)=="PC"){ + int order=intpar; + reg=new PCreg(strpar,order,ndim); + } + + else if (string(basistype)=="PC_MI"){ + //assert(!oflag); + Array2D mindex; + read_datafileVS(mindex,mindexfile); + reg=new PCreg(strpar,mindex); + } + + else if (string(basistype)=="POL"){ + int order=intpar; + reg=new PLreg(order,ndim); + } + + else if (string(basistype)=="POL_MI"){ + //assert(!oflag); + Array2D mindex; + read_datafileVS(mindex,mindexfile); + reg=new PLreg(mindex); + } + else{ + printf("Basistype %s is not recognized, should be RBF, PC, PC_MI, POL or POL_MI. Exiting\n",basistype); + exit(0); + } + + + int nbas=reg->GetNbas(); + cout << "Dimensionality " << reg->GetNdim() << endl; + cout << "Number of bases " << reg->GetNbas() << endl; + + /// Initialize regression + reg->InitRegr(); + /// Set the regression model + reg->SetRegMode(string(msc)); + /// Setup data + reg->SetupData(xdata,ydata); + + /// Set the regularization parameters + Array1D regweights; + + if (lflag){ + if (dblpar>=0.0) + regweights.Resize(nbas,dblpar); + else + regweights.Resize(nbas,reg->LSQ_computeBestLambda()); + } + else if (wflag){ + regweights.Resize(nbas,0.0); + read_datafile_1d(regweights,regparamfile); + } + + else{ + if (string(meth)=="lsq"){ + regweights=reg->LSQ_computeBestLambdas(); + } + else if (string(meth)=="wbcs"){ + printf("For wbcs, either -l or -w has to be given. Exiting.\n"); + exit(1); + } + else{ + printf("Method not recognized, should be lsq or wbcs. Exiting.\n"); + exit(1); + } + } + + // TODO make sure all regweights are positive + reg->SetRegWeights(regweights); + write_datafile_1d(regweights,"lambdas.dat"); + + + + /// Go through methods, lsq, wbcs + Array1D selected; + if (string(meth)=="lsq"){ + reg->LSQ_BuildRegr(); + selected.Resize(nbas); + for (int i=0;iBCS_BuildRegr(selected,eta); + + } + else{ + printf("Method not recognized, should be lsq or wbcs. Exiting.\n"); + exit(1); + } + + write_datafile_1d(selected,"selected.dat"); + if (string(basistype)!="RBF"){ + Array2D mindex_new; + reg->GetMindex(mindex_new); + write_datafile(mindex_new,"mindex_new.dat"); + } + + + /// Write out coefficients + Array1D coef; + reg->GetCoef(coef); + write_datafile_1d(coef,"coeff.dat"); + + if (string(msc)!="m"){ + /// Get the data variance + double sigma2=reg->GetSigma2(); + Array1D sigma2_arr(1,sigma2); + write_datafile_1d(sigma2_arr,"sigma2.dat"); + cout << "Sigma2 = " << sigma2 << endl; + + Array2D coef_cov; + reg->GetCoefCov(coef_cov); + write_datafile(coef_cov,"Sig.dat"); + } + + /// Evaluate at validation points + Array1D ycheck,ycheck_var; + Array2D ycheck_cov; + reg->EvalRegr(xcheck,ycheck,ycheck_var,ycheck_cov); + write_datafile_1d(ycheck,"ycheck.dat"); + if (string(msc)!="m") + write_datafile_1d(ycheck_var,"ycheck_var.dat"); + + /// Print standard error measures for the lsq method + if (string(meth)=="lsq"){ + Array1D errors=reg->computeErrorMetrics(string(meth)); + cout << "LOO error : " << errors(0) << endl; + cout << "GCV error : " << errors(1) << endl; + write_datafile_1d(errors,"errors.dat"); + } + + delete reg; + + return 0; + +} diff --git a/cpp/app/sens/CMakeLists.txt b/cpp/app/sens/CMakeLists.txt new file mode 100644 index 00000000..7cad6c84 --- /dev/null +++ b/cpp/app/sens/CMakeLists.txt @@ -0,0 +1,70 @@ + +add_executable (sens sens.cpp) +add_executable (trdSpls trdSpls.cpp) + +target_link_libraries (trdSpls uqtkmcmc ) +target_link_libraries (trdSpls uqtkpce ) +target_link_libraries (trdSpls uqtkquad ) +target_link_libraries (trdSpls uqtktools) +target_link_libraries (trdSpls uqtkarray) + +target_link_libraries (trdSpls depdsfmt ) +target_link_libraries (trdSpls deplbfgs ) +target_link_libraries (trdSpls depcvode ) +target_link_libraries (trdSpls depnvec ) +target_link_libraries (trdSpls depslatec) +target_link_libraries (trdSpls deplapack) +target_link_libraries (trdSpls depblas ) +target_link_libraries (trdSpls depfigtree ) +target_link_libraries (trdSpls depann ) + + +target_link_libraries (sens uqtkarray) + +target_link_libraries (sens depdsfmt ) +target_link_libraries (sens deplapack) +target_link_libraries (sens depblas ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (sens gfortran stdc++) + target_link_libraries (trdSpls gfortran stdc++) + else() + target_link_libraries (sens ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + target_link_libraries (trdSpls ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel C++ + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (sens ifcore) + target_link_libraries (trdSpls ifcore) + else() + target_link_libraries (sens ${IntelLibPath}/libifcore.a) + target_link_libraries (trdSpls ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (sens gfortran stdc++) + target_link_libraries (trdSpls gfortran stdc++) + else() + target_link_libraries (sens ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + target_link_libraries (trdSpls ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libquadmath.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +include_directories(../../lib/include) +include_directories(../../lib/tools ) +include_directories(../../lib/quad ) +include_directories(../../lib/array ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/figtree) + +INSTALL(TARGETS sens DESTINATION bin) +INSTALL(TARGETS trdSpls DESTINATION bin) + diff --git a/cpp/app/sens/sens.cpp b/cpp/app/sens/sens.cpp new file mode 100644 index 00000000..0530429f --- /dev/null +++ b/cpp/app/sens/sens.cpp @@ -0,0 +1,373 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "assert.h" +#include + +using namespace std; + +#include "Array2D.h" + +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" +#include "error_handlers.h" +#include "ftndefs.h" +#include "depblas.h" +#include "deplapack.h" + +double arrayMean(int n, double *a) ; +double arrayVar (int n, double *a, double aMean, int ddof) ; + +#define VERB + +void usage() { + + printf("Computes Sobol sensitivity indices via sampling\n"); + printf("usage: sens [-h] -d -n [-w] [-x] [-a] [-b]\n"); + printf(" -h : print out this help message \n"); + printf(" -d : no. of dimensions (default=0) \n"); + printf(" -n : no. of samples (default=0) \n"); + printf(" -a : action (default=NONE); can be set to spl* or idx*\n"); + printf(" where * can be FO (first order), TO (total order), or Jnt (joint)\n"); + printf(" -u : filename for first set of nspl samples (default=NONE)\n"); + printf(" -v : filename for second set of nspl samples (default=NONE)\n"); + printf(" -x : filename for model evaluations (default=NONE)\n"); + printf(" -p : filename for selected parameters (default=NONE)\n"); + exit(0); + return; +} + +int main(int argc, char *argv[]) { + + int ndim=0, nspl=0, incr=0 ; + + char *sfile = (char *)"NONE" ; + char *pfile = (char *)"NONE" ; bool pflag =false ; + char *m1file = (char *)"NONE" ; bool m1flag=false ; + char *m2file = (char *)"NONE" ; bool m2flag=false ; + char *action = (char *)"NONE" ; + + dsfmt_t RandomState; /* random number structure */ + + /* Read user input */ + int c; + while ((c=getopt(argc,(char **)argv,"ha:x:p:u:v:d:n:"))!=-1){ + switch (c) { + case 'h': + usage(); + break; + case 'a': + action = optarg; + break; + case 'x': + sfile = optarg; + break; + case 'p': + pflag = true ; + pfile = optarg ; + break; + case 'u': + m1flag = true ; + m1file = optarg ; + break; + case 'v': + m2flag = true ; + m2file = optarg ; + break; + case 'd': + ndim = strtol(optarg, (char **)NULL,0); + break; + case 'n': + nspl = strtol(optarg, (char **)NULL,0); + break; + } + } + +#ifdef VERB + cout << "...No. of samples: "< > plist; + if ( pflag ){ + /* read list with custom parameter sub-lists */ + ifstream in( pfile ); + while ( in.good() ){ + int itmp; + string theLine=""; + vector pidx; + getline(in,theLine); + istringstream s(theLine); + while( s >> itmp ) pidx.push_back(itmp); + if (pidx.size() > 0) + plist.push_back(pidx); + } + in.close(); + } else { + /* no custom list of parameters -> + all parameters are treated the same */ + for ( int j=0; j pidx(1,j); + plist.push_back(pidx) ; + } + } + + /* Increment for scaling matrices */ + incr = 1; + + /* Read mat1 and mat2 matrices if necessary */ + Array2D mat1, mat2, matj; + double *pmat1=NULL, *pmat2=NULL; + if ( ( string(action) == string("splFO") ) || + ( string(action) == string("splTO") ) || + ( string(action) == string("splJnt") ) ) { + read_datafileVS(mat1,m1file); + read_datafileVS(mat2,m2file); + assert( ( (int)mat1.XSize() == nspl ) && ((int)mat1.YSize() == ndim) ); + assert( ( (int)mat2.XSize() == nspl ) && ((int)mat2.YSize() == ndim) ); + pmat1 = mat1.GetArrayPointer(); + pmat2 = mat2.GetArrayPointer(); + } + + if ( string(action) == string("splFO") ) { + + write_datafile(mat1, "splFO.txt"); + matj = mat2; + double *pmatj = matj.GetArrayPointer(); + for ( int j=0; j ymat; + read_datafileVS(ymat,sfile); + int nidx = ymat.XSize()/nspl-2; + + Array1D sFO(nidx); + + double *ymat1 = ymat.GetArrayPointer(); + double *ymat2 = ymat1+nspl*(nidx+1); + + /* Mean mat1*mat2 */ + Array1D ym12(nspl,0.0); + for ( int i=0; i ymat; + read_datafileVS(ymat, sfile); + int nidx = ymat.XSize()/nspl-2; + + Array1D sTO(nidx); + + double *ymat1 = ymat.GetArrayPointer(); + double Ey = arrayMean(nspl,ymat1); + double vv1 = arrayVar (nspl,ymat1, Ey, 1) ; + + Array1D ym12(nspl,0.0); + for ( int j=1; j ymat; + read_datafileVS(ymat,sfile); + Array1D sFO; + read_datafileVS(sFO, (char *) "idxFO.txt"); + int nidx = sFO.XSize(); + Array1D sJnt(nidx*(nidx-1)/2); + + double *ymat1 = ymat.GetArrayPointer(); + double *ymat2 = ymat1+nspl*(nidx*(nidx-1)/2+1); + + /* Mean mat1*mat2 */ + Array1D ym12(nspl,0.0); + for ( int i=0; i. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "assert.h" +#include + +using namespace std; + +#include "dsfmt_add.h" +#include "error_handlers.h" +#include "probability.h" + +#define DPI 6.28318530717959 +#define NPTS 129 +#define NSPL 10000 +#define SEED 0 +#define SFILE "samples.dat" +//#define SAVECDF + +void usage() { + printf("Generate random samples for truncated normal or log-normal distributions.\n"); + printf("usage: genSpls [-h] [-a] [-b] [-m] [-s] [-c] [-n] [-t] [-i] [-f] \n"); + printf(" -h : print out this help message \n"); + printf(" -a : lower bound of the sample range (no default) \n"); + printf(" -b : upper bound of the sample range (no default) \n"); + printf(" -m : mean of the distribution (no default) \n"); + printf(" -s : standard deviation of the distribution (no default) \n"); + printf(" -c : no. of points for the discretized CDF map (default=%d) \n",NPTS); + printf(" -n : no. of random samples (default=%d) \n",NSPL); + printf(" -i : rng seed (default=%d) \n",SEED); + printf(" -t : distribution type: \"n\" (normal) / \"ln\" (log-normal) (no default) \n"); + printf(" -f : file name for output samples (default=%s) \n",SFILE); + return; +} + +/* PDF of normal distribution */ +double ndist(double x, double mean, double sig) { + double s2 = sig*sig; + return ( exp(-pow(x-mean,2)/(2.0*s2))/sqrt(DPI*s2)); +} + +/* PDF of log-normal distribution */ +double logndist(double x, double mean, double sig) { + double s2 = sig*sig; + return ( exp(-pow(log(x)-mean,2)/(2.0*s2))/(x*sqrt(DPI*s2))); +} + +/* Create CDF map */ +void CDFmap(double xmin, double xmax, double mean, double sig, string type, + vector &x,vector &cdfmap) { + + int npts = x.size() ; + cdfmap.resize(npts,0.0); + if ( type == string("n") ) { + double cdfmin = normcdf((xmin-mean)/sig); + double cdfmax = normcdf((xmax-mean)/sig); + for ( int i=1; i= xmax) { printf("Error: Lower bound is greater than upper bound !\n"); exit(1);} + if (( type == string("n") ) && ( ( xmin >= mean ) || (xmax <= mean ) )){ + printf("Warning: Mean is outside the range !\n"); + } + if (( type == string("ln") ) && ( ( log(xmin) >= mean ) || (log(xmax) <= mean ) )){ + printf("Warning: Mean is outside the range !\n"); + } + + if ( ( type != string("n") ) && ( type != string("ln") ) && ( type != string("u") ) ) { + printf("Error: Distribution type should be either \"n\" or \"ln\" or \"u\" !\n"); exit(1); + } + +#ifdef USECDFMAP + vector x(npts); + vector cdfmap(npts); + if ( (type == string("n")) || (type == string("ln")) ) + CDFmap(xmin, xmax, mean, sig, type, x, cdfmap); +#endif + + /* generate and output samples */ + ofstream sout(sfile); + if(!sout){ printf("Error : Could not open file %s\n",sfile) ; exit(1) ;} + dsfmt_init_gen_rand(&RandomState,iseed); + for ( int i=0; i. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file Array1D.h +/// \brief 1D Array class for any type T + +#ifndef ARRAY1D_H_SEEN +#define ARRAY1D_H_SEEN + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "error_handlers.h" + +using namespace std; + +// template T max_test(T a, T b) { return a > b ? a : b; } + +/// \class Array1D +/// \brief Stores data of any type T in a 1D array +/// +/// This class also provides a Fortran-like access operator () +/// as well as a function to access the data in the array through a pointer that +/// can be passed to F77 or C routines. +/// \author Bert Debusschere +/// \date Apr 2005 - Nov 2007 +/// \note Inspired by Helgi Adalsteinsson's Array class implementation +/// \todo double check copy constructor +//column major for fortran blas +template +class Array1D{ +private: + +public: + // These two quantities used to be private but making them public + // allows for easy access to python interface as a "list" + int xsize_; // public (used to be private) size of vector + vector data_; // public (used to be private) copy of data vector + + /// Default constructor, which does not allocate any memory + Array1D(): xsize_(0) {}; + + /// \brief Constructor that allocates the memory + Array1D(const int& nx): xsize_(nx) { + data_.resize(xsize_); + } + + /// Constructor that allocates and initializes the data to a value t + Array1D(const int& nx, const T& t): xsize_(nx) { + data_.resize(xsize_, t); + } + + /// \brief Assignment operator copies the data structure by value + Array1D& operator=(const Array1D &obj) { + xsize_ = obj.xsize_; + data_ = obj.data_; + return *this; + } + + /// \brief Copy constructor + Array1D(const Array1D &obj): xsize_(obj.xsize_), data_(obj.data_) {}; + + /// Destructor that frees up the memory + ~Array1D() {data_.clear();} + + /// \brief Function to clear the memory + void Clear() { + xsize_ = 0; + data_.clear(); + } + + /// \brief Returns size in the x-direction + int XSize() const {return xsize_;} + + /// Returns length (i.e. size in the x-direction) + int Length() const {return xsize_;} + + /// \brief Resizes the array + void Resize(const int& nx) { + xsize_ = nx; + data_.resize(xsize_); + } + + /// \brief Resizes the array and sets ALL entries to the specified value + /// \warning All original data will get lost if this function is used! + void Resize(const int& nx, const T& t) { + data_.clear(); + xsize_ = nx; + data_.resize(xsize_, t); + } + + /// \brief Set all values in the array to the given value + void SetValue(const T& t){ + for(int i=0; i < data_.size(); i++){ + data_[i] = t; + } + } + + /// \brief Add element to the end of the vector + void PushBack(const T& t){ + xsize_ += 1; + data_.push_back(t); + } + + /// \brief Return a pointer to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + T* GetArrayPointer() { + return &(data_[0]); + } + + /// \brief Return a const point to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + const T* GetConstArrayPointer() const { + return &(data_[0]); + } + + // allows access element by element, e.g. this(i) gives data_[i] + T& operator()(int ix) {return data_[ix];} + const T& operator()(int ix) const {return data_[ix];} + + /// \brief Insert a given array to the position ix + /// \note ix=0 means insert at the beginning, ix=xsize_ means insert at the end + void insert(Array1D& insarr,int ix){ + if (ix<0 || ix>xsize_){ + throw Tantrum("Array1D:insert():: insert index out of bounds."); + } + int addsize = insarr.Length(); + xsize_+=addsize; + T* ptr=insarr.GetArrayPointer(); + data_.insert(data_.begin()+ix,ptr,ptr+addsize); + } + + /// \brief Insert a given value to the position ix + /// \note ix=0 means insert at the beginning, ix=xsize_ means insert at the end + void insert(const T& insval,int ix){ + if (ix<0 || ix>xsize_) + throw Tantrum("Array1D:insert():: insert index out of bounds."); + xsize_+=1; + data_.insert(data_.begin()+ix,insval); + } + + /// \brief Erase the value from the position ix + void erase(int ix){ + if (ix<0 || ix>=xsize_) + throw Tantrum("Array1D:erase():: erase index out of bounds."); + xsize_-=1; + data_.erase(data_.begin()+ix); + } + + /// \brief Dump contents of the array to a file in binary format + void DumpBinary(FILE* f_out) const { + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_,f_out); + } + + /// \brief Read contents of the array from a file in binary format + void ReadBinary(FILE* f_in){ + fread(&xsize_,sizeof(xsize_),1,f_in); + data_.resize(xsize_); + fread(this->GetArrayPointer(),sizeof(T),xsize_,f_in); + } + + /********************************************************** + // Methods for interfacing with python + **********************************************************/ + + // For calling [] in Python + T& operator[](int i) {return data_[i];} + + /// \brief Dump contents of the array to a file in binary format + // cannot be read with numpy's fromfile after creation + void DumpBinary(char *filename){ + FILE *f_out; + f_out = fopen(filename,"wb"); + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_,f_out); + fclose(f_out); + } + + // read binary file created with DumpBinary + // Cannot use numpy's from files + // only for use in c++ + void ReadBinary(char *filename){ + FILE *f_in; + f_in = fopen(filename,"rb"); + fread(&xsize_,sizeof(xsize_),1,f_in); + data_.resize(xsize_); + fread(this->GetArrayPointer(),sizeof(T),xsize_,f_in); + fclose(f_in); + } + + // Following two methods are not compatable with certain clang comilers + // creates binary file that can be read with numpy's fromfile + void DumpBinary4py(char *filename){ + ofstream f_out; + f_out.open(filename, ios::out | ios::binary); + f_out.write((char*)this->GetArrayPointer(),sizeof(T[xsize_])); // convert array pointer to char string + f_out.close(); + } + + // can read in DumpBinary4py output, but needs size of vector + // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements + void ReadBinary4py(char *filename, int n){ + xsize_ = n; + ifstream f_in; + f_in.open(filename, ios::in | ios::binary); + f_in.read((char*)this->GetArrayPointer(),sizeof(T[xsize_])); // convert array pointer to char string + f_in.close(); + } + + // Set user-defined list to data_ vector + // This will work even for string type + void setArray(vector inarray){ + data_ = inarray; + xsize_ = inarray.size(); + } + + // Returns data_ vector as a list in python + // Also acts as a print to see individual elements + vector flatten(){ + return data_; + } + + string type(){ + return "string"; + } +}; + +template<> +class Array1D { +private: + int xsize_; // private size of vector +public: + vector data_; // private copy of data vector + + /// Default constructor, which does not allocate any memory + Array1D(): xsize_(0) {}; + + /// \brief Constructor that allocates the memory + Array1D(const int& nx): xsize_(nx) { + data_.resize(xsize_); + } + + /// Constructor that allocates and initializes the data to a value t + Array1D(const int& nx, const int& t): xsize_(nx) { + data_.resize(xsize_, t); + } + + /// \brief Assignment operator copies the data structure by value + Array1D& operator=(const Array1D &obj) { + xsize_ = obj.xsize_; + data_ = obj.data_; + return *this; + } + + /// \brief Copy constructor + Array1D(const Array1D &obj): xsize_(obj.xsize_), data_(obj.data_) {}; + + /// Destructor that frees up the memory + ~Array1D() {data_.clear();} + + /// \brief Function to clear the memory + void Clear() { + xsize_ = 0; + data_.clear(); + } + + /// \brief Returns size in the x-direction + int XSize() const {return xsize_;} + + /// Returns length (i.e. size in the x-direction) + int Length() const {return xsize_;} + + /// \brief Resizes the array + void Resize(const int& nx) { + xsize_ = nx; + data_.resize(xsize_); + } + + /// \brief Resizes the array and sets ALL entries to the specified value + /// \warning All original data will get lost if this function is used! + void Resize(const int& nx, const int& t) { + data_.clear(); + xsize_ = nx; + data_.resize(xsize_, t); + } + + /// \brief Set all values in the array to the given value + void SetValue(const int& t){ + for(int i=0; i < (int)data_.size(); i++){ + data_[i] = t; + } + } + + /// \brief Add element to the end of the vector + void PushBack(const int& t){ + xsize_ += 1; + data_.push_back(t); + } + + /// \brief Return a pointer to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + int* GetArrayPointer() { + return &(data_[0]); + } + + /// \brief Return a const point to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + const int* GetConstArrayPointer() const { + return &(data_[0]); + } + + // allows access element by element, e.g. this(i) gives data_[i] + int& operator()(int ix) {return data_[ix];} + const int& operator()(int ix) const {return data_[ix];} + + /// \brief Insert a given array to the position ix + /// \note ix=0 means insert at the beginning, ix=xsize_ means insert at the end + void insert(Array1D& insarr,int ix){ + if (ix<0 || ix>xsize_){ + throw Tantrum("Array1D:insert():: insert index out of bounds."); + } + int addsize = insarr.Length(); + xsize_+=addsize; + int* ptr=insarr.GetArrayPointer(); + data_.insert(data_.begin()+ix,ptr,ptr+addsize); + } + + /// \brief Insert a given value to the position ix + /// \note ix=0 means insert at the beginning, ix=xsize_ means insert at the end + void insert(const int& insval,int ix){ + if (ix<0 || ix>xsize_) + throw Tantrum("Array1D:insert():: insert index out of bounds."); + xsize_+=1; + data_.insert(data_.begin()+ix,insval); + } + + /// \brief Erase the value from the position ix + void erase(int ix){ + if (ix<0 || ix>=xsize_) + throw Tantrum("Array1D:erase():: erase index out of bounds."); + xsize_-=1; + data_.erase(data_.begin()+ix); + } + + /// \brief Dump contents of the array to a file in binary format + void DumpBinary(FILE* f_out) const { + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(int),xsize_,f_out); + } + + /// \brief Read contents of the array from a file in binary format + void ReadBinary(FILE* f_in){ + fread(&xsize_,sizeof(xsize_),1,f_in); + data_.resize(xsize_); + fread(this->GetArrayPointer(),sizeof(int),xsize_,f_in); + } + + /********************************************************** + // Methods for interfacing with python + **********************************************************/ + + // For calling [] in Python + int& operator[](int i) {return data_[i];} + + /// \brief Dump contents of the array to a file in binary format + // cannot be read with numpy's fromfile after creation + void DumpBinary(char *filename){ + FILE *f_out; + f_out = fopen(filename,"wb"); + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(int),xsize_,f_out); + fclose(f_out); + } + + // read binary file created with DumpBinary + // Cannot use numpy's from files + // only for use in c++ + void ReadBinary(char *filename){ + FILE *f_in; + f_in = fopen(filename,"rb"); + fread(&xsize_,sizeof(xsize_),1,f_in); + data_.resize(xsize_); + fread(this->GetArrayPointer(),sizeof(int),xsize_,f_in); + fclose(f_in); + } + + // creates binary file that can be read with numpy's fromfile + void DumpBinary4py(char *filename){ + ofstream f_out; + f_out.open(filename, ios::out | ios::binary); + f_out.write((char*)this->GetArrayPointer(),xsize_*sizeof(int)); // convert array pointer to char string + f_out.close(); + } + + // can read in DumpBinary4py output, but needs size of vector + // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements + void ReadBinary4py(char *filename, int n){ + xsize_ = n; + ifstream f_in; + f_in.open(filename, ios::in | ios::binary); + f_in.read((char*)this->GetArrayPointer(),xsize_*sizeof(int)); // convert array pointer to char string + f_in.close(); + } + + // Set user-defined list to data_ vector + // This will work even for string type + void setArray(vector inarray){ + data_ = inarray; + xsize_ = inarray.size(); + } + + // // Sets user-defined 1d numpy array to data_ vector + void setnpintArray(long* inarray, int n){ + xsize_ = n; + data_.assign(inarray,inarray+n); + } + // This is not to be used for a string type + void getnpintArray(long* outarray, int n){ + // xsize_ = n; + // data_.assign(inarray,inarray+n); + copy(data_.begin(), data_.end(), outarray); + } + + // Returns data_ vector as a list in python + // Also acts as a print to see individual elements + vector flatten(){ + return data_; + } + + string type(){ + return "int"; + } + +}; + +template<> +class Array1D { +private: + int xsize_; // private size of vector +public: + vector data_; // private copy of data vector + + + /// Default constructor, which does not allocate any memory + Array1D(): xsize_(0) {}; + + /// \brief Constructor that allocates the memory + Array1D(const int& nx): xsize_(nx) { + data_.resize(xsize_); + } + + /// Constructor that allocates and initializes the data to a value t + Array1D(const int& nx, const double& t): xsize_(nx) { + data_.resize(xsize_, t); + } + + /// \brief Assignment operator copies the data structure by value + Array1D& operator=(const Array1D &obj) { + xsize_ = obj.xsize_; + data_ = obj.data_; + return *this; + } + + /// \brief Copy constructor + Array1D(const Array1D &obj): xsize_(obj.xsize_), data_(obj.data_) {}; + + /// Destructor that frees up the memory + ~Array1D() {data_.clear();} + + /// \brief Function to clear the memory + void Clear() { + xsize_ = 0; + data_.clear(); + } + + /// \brief Returns size in the x-direction + int XSize() const {return xsize_;} + + /// Returns length (i.e. size in the x-direction) + int Length() const {return xsize_;} + + /// \brief Resizes the array + void Resize(const int& nx) { + xsize_ = nx; + data_.resize(xsize_); + } + + /// \brief Resizes the array and sets ALL entries to the specified value + /// \warning All original data will get lost if this function is used! + void Resize(const int& nx, const double& t) { + data_.clear(); + xsize_ = nx; + data_.resize(xsize_, t); + } + + /// \brief Set all values in the array to the given value + void SetValue(const double& t){ + for(int i=0; i < (int)data_.size(); i++){ + data_[i] = t; + } + } + + /// \brief Add element to the end of the vector + void PushBack(const double& t){ + xsize_ += 1; + data_.push_back(t); + } + + /// \brief Return a pointer to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + double* GetArrayPointer() { + return &(data_[0]); + } + + /// \brief Return a const point to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + const double* GetConstArrayPointer() const { + return &(data_[0]); + } + + // allows access element by element, e.g. this(i) gives data_[i] + double& operator()(int ix) {return data_[ix];} + const double& operator()(int ix) const {return data_[ix];} + + /// \brief Insert a given array to the position ix + /// \note ix=0 means insert at the beginning, ix=xsize_ means insert at the end + void insert(Array1D& insarr,int ix){ + if (ix<0 || ix>xsize_){ + throw Tantrum("Array1D:insert():: insert index out of bounds."); + } + int addsize = insarr.Length(); + xsize_+=addsize; + double* ptr=insarr.GetArrayPointer(); + data_.insert(data_.begin()+ix,ptr,ptr+addsize); + } + + /// \brief Insert a given value to the position ix + /// \note ix=0 means insert at the beginning, ix=xsize_ means insert at the end + void insert(const double& insval,int ix){ + if (ix<0 || ix>xsize_) + throw Tantrum("Array1D:insert():: insert index out of bounds."); + xsize_+=1; + data_.insert(data_.begin()+ix,insval); + } + + /// \brief Erase the value from the position ix + void erase(int ix){ + if (ix<0 || ix>=xsize_) + throw Tantrum("Array1D:erase():: erase index out of bounds."); + xsize_-=1; + data_.erase(data_.begin()+ix); + } + + /// \brief Dump contents of the array to a file in binary format + void DumpBinary(FILE* f_out) const { + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(double),xsize_,f_out); + } + + /// \brief Read contents of the array from a file in binary format + void ReadBinary(FILE* f_in){ + fread(&xsize_,sizeof(xsize_),1,f_in); + data_.resize(xsize_); + fread(this->GetArrayPointer(),sizeof(double),xsize_,f_in); + } + + /********************************************************** + // Methods for interfacing with python + **********************************************************/ + + // For calling [] in Python + double& operator[](int i) {return data_[i];} + + /// \brief Dump contents of the array to a file in binary format + // cannot be read with numpy's fromfile after creation + void DumpBinary(char *filename){ + FILE *f_out; + f_out = fopen(filename,"wb"); + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(double),xsize_,f_out); + fclose(f_out); + } + + // read binary file created with DumpBinary + // Cannot use numpy's from files + // only for use in c++ + void ReadBinary(char *filename){ + FILE *f_in; + f_in = fopen(filename,"rb"); + fread(&xsize_,sizeof(xsize_),1,f_in); + data_.resize(xsize_); + fread(this->GetArrayPointer(),sizeof(double),xsize_,f_in); + fclose(f_in); + } + + // creates binary file that can be read with numpy's fromfile + void DumpBinary4py(char *filename){ + ofstream f_out; + f_out.open(filename, ios::out | ios::binary); + f_out.write((char*)this->GetArrayPointer(),xsize_*sizeof(double)); // convert array pointer to char string + f_out.close(); + } + + // can read in DumpBinary4py output, but needs size of vector + // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements + void ReadBinary4py(char *filename, int n){ + xsize_ = n; + ifstream f_in; + f_in.open(filename, ios::in | ios::binary); + f_in.read((char*)this->GetArrayPointer(),xsize_*sizeof(double)); // convert array pointer to char string + f_in.close(); + } + + // Set user-defined list to data_ vector + // This will work even for string type + void setArray(vector inarray){ + data_ = inarray; + xsize_ = inarray.size(); + } + + // Sets user-defined 1d numpy array to data_ vector + // This is not to be used for a string type + void setnpdblArray(double* inarray, int n){ + xsize_ = n; + data_.assign(inarray,inarray+n); + } + // Sets user-defined 1d numpy array to data_ vector + // This is not to be used for a string type + void getnpdblArray(double* outarray, int n){ + // xsize_ = n; + // data_.assign(inarray,inarray+n); + copy(data_.begin(), data_.end(), outarray); + } + + // Returns data_ vector as a list in python + // Also acts as a print to see individual elements + vector flatten(){ + return data_; + } + + string type(){ + return "double"; + } +}; + +#endif /* ARRAY1D_H_SEEN */ diff --git a/cpp/lib/array/Array2D.h b/cpp/lib/array/Array2D.h new file mode 100644 index 00000000..45acec29 --- /dev/null +++ b/cpp/lib/array/Array2D.h @@ -0,0 +1,397 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file Array2D.h +/// \brief 2D Array class for any type T + + +#ifndef ARRAY2D_H_SEEN +#define ARRAY2D_H_SEEN + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Array1D.h" + +using namespace std; + +/// \class Array2D +/// \brief Stores data of any type T in a 2D array +/// +/// This class also provides a Fortran-like access operator () +/// as well as a function to access the data in the array through a pointer that +/// can be passed to F77 or C routines. +/// \author Bert Debusschere +/// \date Jan 2005 +/// \note Inspired by Helgi Adalsteinsson's Array class implementation +/// \todo Define copy constructor +// COLUMN MAJOR FORMAT + +template +class Array2D{ +private: + +public: + // These two quantities used to be private but making them public + // allows for easy access to python interface as a "list" + int xsize_; + int ysize_; + vector data_; + Array1D arraycopy; + Array1D rowvec; + + /// \brief Default constructor, which does not allocate any memory + Array2D(): xsize_(0), ysize_(0) {}; + + /// \brief Constructor that allocates the memory + Array2D(const int& nx, const int& ny): xsize_(nx), ysize_(ny){ + data_.resize(xsize_*ysize_); + } + + /// \brief Constructor that allocates and initializes the data to a constant t + Array2D(const int& nx, const int& ny, const T& t): xsize_(nx), ysize_(ny){ + data_.resize(xsize_*ysize_ , t); + } + + /// \brief Copy constructor + Array2D(const Array2D &obj): xsize_(obj.xsize_), ysize_(obj.ysize_), data_(obj.data_) {}; + + /// \brief Destructor that frees up the memory + ~Array2D() {data_.clear();} + + /// \brief Function to clear the memory + void Clear() { + xsize_ = 0; + ysize_ = 0; + data_.clear(); + } + + /// \brief Returns size in the x-direction + int XSize() const {return xsize_;} + /// \brief Returns size in the y-direction + int YSize() const {return ysize_;} + + /// \brief Resizes the array + /// \warning In its current implementation, most of the original data + void Resize(const int& nx, const int& ny) { + xsize_ = nx; + ysize_ = ny; + data_.resize(xsize_*ysize_); + } + + /// \brief Resizes the array and sets ALL entries to the specified value + /// \warning All original data will get lost if this function is used! + void Resize(const int& nx, const int& ny, const T& t) { + data_.clear(); + xsize_ = nx; + ysize_ = ny; + data_.resize(xsize_*ysize_, t); + } + + /// \brief Set all values in the array to the given value + void SetValue(const T& t){ + for(int i=0; i < data_.size(); i++){ + data_[i] = t; + } + } + + /// \brief Return a pointer to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + T* GetArrayPointer() { + return &(data_[0]); + } + + /// \brief Return a cont point to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + const T* GetConstArrayPointer() const { + return &(data_[0]); + } + + /// \brief C-like () operator to access values in the 2D data array + // values accessed in a row-major format + T& operator()(int ix,int iy) {return data_[ix + xsize_*iy];} + const T& operator()(int ix,int iy) const {return data_[ix + xsize_*iy];} + + /// \brief Insert array insarr as a row into position ix + void insertRow(Array1D& insarr,int ix){ + if (ix<0 || ix>xsize_) + throw Tantrum("Array2D:insertRow():: insert index out of bounds."); + if ( insarr.Length() != ysize_ ) + throw Tantrum("Array2D:insertRow():: insert row size does not match."); + + vector data_old; + data_old=data_; + + xsize_ += 1; // new number of rows + data_.resize(xsize_*ysize_); + + for(int iy=0;iy& insarr,int ix){ + if (ix<0 || ix>xsize_) + throw Tantrum("Array2D:insertRow():: insert index out of bounds."); + if ( insarr.YSize() != ysize_ ) + throw Tantrum("Array2D:insertRow():: insert row size does not match."); + + vector data_old; + data_old=data_; + + int insx=insarr.XSize(); + + xsize_ += insx; + data_.resize(xsize_*ysize_); + + for(int iy=0;iy=xsize_) + throw Tantrum("Array2D:eraseRow():: erase index out of bounds."); + + vector data_old; + data_old=data_; + + xsize_-=1; + data_.resize(xsize_*ysize_); + + for(int iy=0;iy& insarr,int iy){ + if (iy<0 || iy>ysize_) + throw Tantrum("Array2D:insertCol():: insert index out of bounds."); + if ( insarr.Length() != xsize_ ) + throw Tantrum("Array2D:insertCol():: insert column size does not match."); + + + T* ptr=insarr.GetArrayPointer(); + data_.insert(data_.begin()+xsize_*iy,ptr,ptr+xsize_); + + ysize_+=1; + + } + + /// \brief Insert a 2d-array insarr into a column position iy + void insertCol(Array2D& insarr,int iy){ + if (iy<0 || iy>ysize_) + throw Tantrum("Array2D:insertCol():: insert index out of bounds."); + if ( insarr.XSize() != xsize_ ) + throw Tantrum("Array2D:insertRow():: insert column size does not match."); + + int insy=insarr.YSize(); + + T* ptr=insarr.GetArrayPointer(); + data_.insert(data_.begin()+xsize_*iy,ptr,ptr+xsize_*insy); + + ysize_+=insy; + } + + /// \brief Erase the column iy + void eraseCol(int iy){ + if (iy<0 || iy>=ysize_) + throw Tantrum("Array2D:eraseCol():: erase index out of bounds."); + + data_.erase(data_.begin()+xsize_*iy,data_.begin()+xsize_*(iy+1)); + + ysize_-=1; + + //if (ysize_==0) + // printf("eraseCol(): WARNING: the ysize is zeroed!"); + + } + + /// \brief Dump contents of the array to a file in binary format + void DumpBinary(FILE* f_out) const { + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(&ysize_,sizeof(ysize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_*ysize_,f_out); + } + + + /// \brief Read contents of the array from a file in binary format + void ReadBinary(FILE* f_in){ + fread(&xsize_,sizeof(xsize_),1,f_in); + fread(&ysize_,sizeof(ysize_),1,f_in); + data_.resize(xsize_*ysize_); + fread(this->GetArrayPointer(),sizeof(T),xsize_*ysize_,f_in); + } + + /******************************************************** + // Methods for interfacing with python + ********************************************************/ + + // assignment operator [] + // allows for calling Array2D using [i][j] notation + // make more efficient by setting two vectors equal + Array1D& operator[](int ix) { + // get the ith row + int stride = xsize_; + rowvec.Resize(ysize_); + for (int iy = 0; iy < ysize_; iy++){ + rowvec(iy) = data_[ix + stride*iy]; + } + return rowvec; + } + + void getRow(int row){ + arraycopy.Resize(ysize_,0); + int stride = xsize_; + for (int i = 0; i < ysize_; i++){ + arraycopy[i] = data_[i*stride + row]; + } + } + + // read binary file created with DumpBinary + // Cannot use numpy's from files + // only for use in c++ + void DumpBinary(char *filename){ + FILE *f_out; + f_out = fopen(filename,"wb"); + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(&ysize_,sizeof(ysize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_*ysize_,f_out); + fclose(f_out); + } + + // Only for use if DumpBinary was used + // can only be read in c++ + // can be opened with ReadBinary(FILE* file) above + void ReadBinary(char *filename){ + FILE *f_in; + f_in = fopen(filename,"rb"); + fread(&xsize_,sizeof(xsize_),1,f_in); + fread(&ysize_,sizeof(ysize_),1,f_in); + data_.resize(xsize_*ysize_); + fread(this->GetArrayPointer(),sizeof(T),xsize_*ysize_,f_in); + fclose(f_in); + } + + // creates binary file that can be read with numpy's fromfile + void DumpBinary4py(char *filename){ + ofstream f_out; + f_out.open(filename, ios::out | ios::binary); + f_out.write((char*)this->GetArrayPointer(),sizeof(T[xsize_*ysize_])); // convert array pointer to char string + f_out.close(); + } + + // can read in DumpBinary4py output, but needs size of vector + // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements + void ReadBinary4py(char *filename, int n1, int n2){ + xsize_ = n1; + ysize_ = n2; + ifstream f_in; + f_in.open(filename, ios::in | ios::binary); + f_in.read((char*)this->GetArrayPointer(),sizeof(T[xsize_*ysize_])); // convert array pointer to char string + f_in.close(); + } + + // Set user-defined list to data_ vector + // This will work even for string type + void setArray(vector inarray){ + data_ = inarray; + // xsize_ = inarray.size(); + } + + // Sets user-defined 2d numpy array to data_ vector + // This is not to be used for a string type + void setnpdblArray(double* inarray, int n1, int n2){ + xsize_ = n1; + ysize_ = n2; + data_.assign(inarray,inarray+n1*n2); + } + + // get numpy double array from data_ vector + void getnpdblArray(double* outarray, int n1, int n2){ + copy(data_.begin(), data_.end(), outarray); + } + + // Sets user-defined 2d numpy array to data_ vector + // This is not to be used for a string type + void setnpintArray(long* inarray, int n1, int n2){ + xsize_ = n1; + ysize_ = n2; + data_.assign(inarray,inarray+n1*n2); + } + + // get numpy double array from data_ vector + void getnpintArray(long* outarray, int n1, int n2){ + copy(data_.begin(), data_.end(), outarray); + } + + // Returns data_ vector as a list in python in row-major (?) + // Also acts as a print to see individual elements + vector flatten(){ + return data_; + } + + string type(){ + const char* s = typeid(data_[0]).name(); + if (string(s) == string("Ss") ){ + return "string"; + } + else if (strcmp(s,"i") == 0){ + return "int"; + } + else { + return "double"; + } + } +}; + +#endif /* ARRAY2D_H_SEEN */ diff --git a/cpp/lib/array/Array3D.h b/cpp/lib/array/Array3D.h new file mode 100644 index 00000000..7a55f6ec --- /dev/null +++ b/cpp/lib/array/Array3D.h @@ -0,0 +1,219 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file Array3D.h +/// \brief 3D Array class for any type T + + +#ifndef ARRAY3D_H_SEEN +#define ARRAY3D_H_SEEN + +#include +#include +#include +#include +#include +#include + +using namespace std; + +/// \class Array3D +/// \brief Stores data of any type T in a 3D array +/// +/// This class also provides a Fortran-like access operator () +/// as well as a function to access the data in the array through a pointer that +/// can be passed to F77 or C routines. +/// \author Bert Debusschere +/// \date Jan 2005 +/// \note Inspired by Helgi Adalsteinsson's Array class implementation +/// \todo Define copy constructor +/// \todo Several functions, e.g. insert/erase columns/rows, available in Array1D and Array2D, are missing. +template +class Array3D { + public: + /// \brief Default constructor, which does not allocate any memory + Array3D(): xsize_(0), ysize_(0), zsize_(0) {}; + + /// \brief Constructor that allocates the memory + Array3D(const size_t& nx, const size_t& ny, const size_t& nz): + xsize_(nx), ysize_(ny), zsize_(nz) { + data_.resize(xsize_*ysize_*zsize_); + } + + /// \brief Constructor that allocates and initializes the data + Array3D(const size_t& nx, const size_t& ny, const size_t& nz, const T& t): + xsize_(nx), ysize_(ny), zsize_(nz) { + data_.resize(xsize_*ysize_*zsize_ , t); + } + + /// \brief Destructor that frees up the memory + ~Array3D() {data_.clear();} + + /// \brief Function to clear the memory + void Clear() { + xsize_ = 0; + ysize_ = 0; + zsize_ = 0; + data_.clear(); + } + + /// \brief Returns size in the x-direction + size_t XSize() const {return xsize_;} + /// \brief Returns size in the y-direction + size_t YSize() const {return ysize_;} + /// \brief Returns size in the z-direction + size_t ZSize() const {return zsize_;} + + /// \brief Resizes the array + /// \warning In its current implementation, most of the original data + /// will get lost if the xsize or ysize changes as this changes the indexing for all entries. + /// \todo Write a better implementation that preserves the original data by + /// copying it to a temporary array and putting the elements back where they were before. + /// This would bring this resize() command more closely in line with vector::resize() + /// function in the original vector class. + void Resize(const size_t& nx, const size_t& ny, const size_t& nz) { + xsize_ = nx; + ysize_ = ny; + zsize_ = nz; + data_.resize(xsize_*ysize_*zsize_); + } + + /// \brief Resizes the array and sets ALL entries to the specified value + /// \warning All original data will get lost if this function is used! + /// \todo Write an implementation that is more closely follows the resize + /// command in the vector class, which keeps the original elements and only + /// initializes the new elements. + void Resize(const size_t& nx, const size_t& ny, const size_t& nz, const T& t) { + data_.clear(); + xsize_ = nx; + ysize_ = ny; + zsize_ = nz; + data_.resize(xsize_*ysize_*zsize_ , t); + } + + /// \brief Set all values in the array to the given value + void SetValue(const T& t){ + for(size_t i=0; i < data_.size(); i++){ + data_[i] = t; + } + } + + /// \brief Return a pointer to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + T* GetArrayPointer() { + return &(data_[0]); + } + + /// \brief Return a const pointer to the first element of the data in the + /// vector so we can use it access the data in array format (e.g. for + /// passing it to a Fortran program). + const T* GetConstArrayPointer() const { + return &(data_[0]); + } + + /// \brief Fortran-like () operator to access values in the 3D data array + /// + /// If "my_data" is an object of type Array3D, then its array values can + /// be accessed as my_data(ix,iy,iz), where ix, iy, iz are the indices in the + /// x, y, and z dimensions respectively. + T& operator()(size_t ix, size_t iy, size_t iz) {return data_[ix+xsize_*(iy+ysize_*iz)];} + + /// \brief Fortran-like () const operator to access values in the 3D data array + /// + /// If "my_data" is an object of type Array3D, then its array values can + /// be accessed as my_data(ix,iy,iz), where ix, iy, iz are the indices in the + /// x, y, and z dimensions respectively. + const T& operator()(size_t ix, size_t iy, size_t iz) const {return data_[ix+xsize_*(iy+ysize_*iz)];} + + /// \brief Dump contents of the array to a file in binary format + void DumpBinary(FILE* f_out) const { + fwrite(&xsize_,sizeof(xsize_),1,f_out); + fwrite(&ysize_,sizeof(ysize_),1,f_out); + fwrite(&zsize_,sizeof(zsize_),1,f_out); + fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_*ysize_*zsize_,f_out); + } + + /// \brief Dump contents of the array to a file in text format + /// Added by Maher Salloum + /// When post-processing (in matlab for example), one has to transpose each 2-D + /// sub-matrix imported from the text file. + void DumpText(std::ofstream& f_out) const { + vector::const_iterator it1; + vector::const_iterator it2; + it2=data_.begin(); + + for (int iz=0;iz(f_out," ")); + f_out << endl; + } + } + + } + + /// \brief Read contents of the array from a file in binary format + void ReadText(FILE* f_in){ + fread(&xsize_,sizeof(xsize_),1,f_in); + fread(&ysize_,sizeof(ysize_),1,f_in); + fread(&zsize_,sizeof(zsize_),1,f_in); + data_.resize(xsize_*ysize_*zsize_); + fread(this->GetArrayPointer(),sizeof(T),xsize_*ysize_*zsize_,f_in); + } + + /// \brief Read contents of the array from a file in text format + /// Added by Maher Salloum + void ReadBinary(std::ifstream& f_in){ + + typedef std::istream_iterator istream_iterator; + std::copy(istream_iterator(f_in),istream_iterator(),data_.begin()); + } + + + private: + + /// \brief Copy constructor, which is made private so it would not be used inadvertently + /// (until we define a proper copy constructor) + Array3D(const Array3D &obj) {}; + + /// \brief Number of elements in the x-dimension + size_t xsize_; + /// \brief Number of elements in the y-dimension + size_t ysize_; + /// \brief Number of elements in the z-dimension + size_t zsize_; + + /// \brief Data in the array with size = xsize_ * ysize_ * zsize_ + /// + /// The data is stored with the fastest running index in the x-dimension + /// then the y-dimension and the slowest one in the z-dimension. The indices + /// in every dimension run from 0 to their respective "size-1" + vector data_; +}; + +#endif /* ARRAY3D_H_SEEN */ diff --git a/cpp/lib/array/CMakeLists.txt b/cpp/lib/array/CMakeLists.txt new file mode 100644 index 00000000..8d78f659 --- /dev/null +++ b/cpp/lib/array/CMakeLists.txt @@ -0,0 +1,22 @@ +project(UQTk) + +SET(array_HEADERS + Array1D.h + Array2D.h + Array3D.h + arrayio.h + arraytools.h + ) + +add_library(uqtkarray arrayio.cpp arraytools.cpp) + +include_directories (../include) + +include_directories (../../../dep/blas) +include_directories (../../../dep/lapack) + +# Install the library +INSTALL(TARGETS uqtkarray DESTINATION lib) + +# Install the header files +INSTALL(FILES ${array_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/array/arrayio.cpp b/cpp/lib/array/arrayio.cpp new file mode 100644 index 00000000..8ead7acc --- /dev/null +++ b/cpp/lib/array/arrayio.cpp @@ -0,0 +1,603 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file arrayio.cpp +/// \brief Read/write capabilities from/to matrix or vector form arrays/files + +#include "arrayio.h" + +using namespace std; + + +// Read a datafile from filename in a matrix form and store it in a 2D array +template +void read_datafile(Array2D &data, const char *filename) +{ + int nx = data.XSize(); + int ny = data.YSize(); + + if (nx==0 || ny==0){ + printf("read_datafile() : the requested data array is empty\n") ; + exit(1) ; + } + ifstream in(filename); + + if(!in){ + printf("read_datafile() : the requested file %s does not exist\n",filename) ; + exit(1) ; + } + + string theLine=""; + int ix=0; + + while(in.good()){ + + getline(in,theLine); + + if (theLine=="") break; + if ( theLine.compare(0, 1, "#") == 0 ) continue ; + + istringstream s(theLine); + int iy = 0; + T tmp; + while(s >> tmp){ + data(ix,iy)=tmp; + iy++; + } + if ( iy != ny ) { + printf("Error at line %d while reading %s; number of columns should be %d\n", + ix+1, filename,ny); + exit(1); + } + ix++; + } + if ( ix != nx ) { + printf("Error while reading %s; number of rows should be %d\n",filename,nx); + exit(1); + } + + in.close(); + + return; +} +template void read_datafile(Array2D &data, const char *filename); +template void read_datafile(Array2D &data, const char *filename); + + +// Read a datafile from filename in a vector form and store it in a 2d +// array data of typename T +template +void read_datafileVS(Array2D &data, const char *filename) +{ + + ifstream in(filename); + + if(!in){ + printf("read_datafileVS() : the requested file %s does not exist\n",filename) ; + exit(1) ; + } + + string theLine=""; + + // figure out number of lines and columns + int nx, ny, ix = 0 ; + while(in.good()){ + getline(in,theLine); + + if ( theLine == "" ) break; + if ( theLine.compare(0,1,"#") == 0 ) continue ; + + istringstream s(theLine); + int iy = 0 ; + T tmp ; + while( s >> tmp ) iy++ ; + + if ( ( ix > 0 ) && ( iy != ny ) ) + { + printf("read_datafileVS() : Error at line %d !!!\n",ix+1) ; + printf(" no. of columns should be %d instead of %d\n",ny,iy) ; + exit(1) ; + } + + ny = iy ; + + ix++ ; + + } + + nx = ix ; + +#ifdef VERBOSE + printf("File \"%s\" contains %d rows and %d columns \n",filename,nx,ny) ; +#endif + // Resize, goto beginning, and read again + + if ( ( (int) data.XSize() != nx ) || ( (int) data.YSize() != ny ) ) + data.Resize(nx,ny) ; + + //in.close() ; + //in.open(filename); + in.clear() ; + in.seekg(0, ios::beg ) ; + ix = 0 ; + while( in.good() ){ + + getline(in,theLine); + + if ( theLine == "" ) break; + if ( theLine.compare(0,1,"#") == 0 ) continue ; + + istringstream s(theLine); + int iy = 0 ; + T tmp ; + while( s >> tmp ) { + data(ix,iy)=tmp; + iy++; + } + if ( iy != ny ) { + printf("read_datafileVS() : Error in file \"%s\" \n",filename); + printf(" -> at line %d while reading %s; number of columns should be %d\n", + ix+1, filename, ny); + exit(1) ; + } + ix++; + } + if ( ix != nx ) { + printf("read_datafileVS() : Error while reading \"%s\" -> number of rows should be %d\n", filename,nx) ; + exit(1) ; + } + + return ; + +} +template void read_datafileVS(Array2D &data, const char *filename); +template void read_datafileVS(Array2D &data, const char *filename); + +// Read a datafile from filename in a vector form and store it in a 2d +// array data of typename T +template +void read_datafileVS(std::vector &data, int &nrows, int &ncols, const char *filename) +{ + + ifstream in(filename); + + if(!in){ + printf("read_datafileVS() : the requested file %s does not exist\n",filename) ; + exit(1) ; + } + + string theLine=""; + + // figure out number of lines and columns + int ix = 0 ; + while(in.good()){ + getline(in,theLine); + + if ( theLine == "" ) break; + if ( theLine.compare(0,1,"#") == 0 ) continue ; + + istringstream s(theLine); + int iy = 0 ; + T tmp ; + while( s >> tmp ) iy++ ; + + if ( ( ix > 0 ) && ( iy != ncols ) ) + { + printf("read_datafileVS() : Error at line %d !!!\n",ix+1) ; + printf(" no. of columns should be %d instead of %d\n",ncols,iy) ; + exit(1) ; + } + + ncols = iy ; + + ix++ ; + + } + + nrows = ix ; + +#ifdef VERBOSE + printf("File \"%s\" contains %d rows and %d columns \n",filename,nrows,ncols) ; +#endif + // Resize, goto beginning, and read again + + data.resize(nrows*ncols,0.0); + + //in.close() ; + //in.open(filename); + in.clear() ; + in.seekg(0, ios::beg ) ; + ix = 0 ; + while( in.good() ){ + + getline(in,theLine); + + if ( theLine == "" ) break; + if ( theLine.compare(0,1,"#") == 0 ) continue ; + + istringstream s(theLine); + int iy = 0 ; + T tmp ; + while( s >> tmp ) { + data[iy*nrows+ix]=tmp; + iy++; + } + if ( iy != ncols ) { + printf("read_datafileVS() : Error in file \"%s\" \n",filename); + printf(" -> at line %d while reading %s; number of columns should be %d\n", + ix+1, filename, ncols); + exit(1) ; + } + ix++; + } + if ( ix != nrows ) { + printf("read_datafileVS() : Error while reading \"%s\" -> number of rows should be %d\n", filename,nrows) ; + exit(1) ; + } + + return ; + +} +template void read_datafileVS(std::vector &data, int &nrows, int &ncols, const char *filename); +template void read_datafileVS(std::vector &data, int &nrows, int &ncols, const char *filename); + +// Read a datafile from filename in a vector form and store it in a 1d +// array data of typename T +template +void read_datafile_1d(Array1D& data, const char* filename) +{ + int nx=data.XSize(); + + if (nx==0){ + printf("read_datafile_1d() : the requested data array is empty\n") ; + exit(1) ; + } + + int ny=1; + + ifstream in(filename); + + if(!in){ + printf("read_datafile_1d() : the requested file %s does not exist\n",filename) ; + exit(1) ; + } + + string theLine=""; + int ix=0; + + while( in.good() ){ + getline(in,theLine); + + if (theLine=="") break; + + istringstream s(theLine); + int iy=0; + T tmp; + // while(s>>tmp){ + s >> tmp; + data(ix) = tmp; + iy++; + if (s>>tmp) { + printf("Error at line %d while reading %s; number of columns should be %d\n", + ix+1, filename,ny); + exit(1); + } + ix++; + } + if ( ix != nx ) { + printf("Error while reading %s; number of rows should be %d\n", + filename,nx); + exit(1); + } + + return ; + +} +template void read_datafile_1d(Array1D &data, const char* filename); +template void read_datafile_1d(Array1D &data, const char* filename); + +// Read a datafile from filename in a vector form and store it in a 1d +// array data of typename T +template +void read_datafileVS(Array1D &data, const char *filename) +{ + + data.Clear(); + ifstream in(filename); + + if(!in){ + printf("read_datafileVS() : the requested file %s does not exist\n",filename) ; + exit(1) ; + } + + string theLine=""; + int ix=0; + + while(in.good()){ + getline(in,theLine); + + if (theLine=="") break; + + istringstream s(theLine); + T tmp; + s >> tmp; + data.PushBack(tmp); + if (s>>tmp) { + printf("Error at line %d while reading %s; number of columns should be 1\n", ix+1, filename); + exit(1); + } + ix++; + } + + return ; + +} +template void read_datafileVS(Array1D &data, const char *filename); +template void read_datafileVS(Array1D &data, const char *filename); + +// Write the contents of a 2d array data of typename T to file filename in a matrix form +template +void write_datafile_size(const Array2D &data, const char *filename) +{ + + int nx=data.XSize(); + int ny=data.YSize(); + + FILE* f_out; + if(!(f_out = fopen(filename,"w"))){ + printf("write_datafile_size: could not open file '%s'\n",filename); + exit(1); + } + + fprintf(f_out, "%d %d\n", nx, ny); + + if (fclose(f_out) ) { + printf("write_datafile: could not close file '%s'\n",filename); + exit(1); + } + + write_datafile(data, filename, "a"); + + return ; + +} +template void write_datafile_size(const Array2D &data, const char *filename); +template void write_datafile_size(const Array2D &data, const char *filename); + +// Write the contents of a 2d array data of typename T to file filename in a matrix form +template +void write_datafile(const Array2D &data, const char *filename) +{ + + int nx=data.XSize(); + int ny=data.YSize(); + + FILE* f_out; + if(!(f_out = fopen(filename,"w"))){ + printf("write_datafile: could not open file '%s'\n",filename); + exit(1); + } + + if ( typeid(T) == typeid(int) ) + for(int ix = 0 ; ix < nx ; ix++){ + for(int iy = 0 ; iy < ny ; iy++){ + fprintf(f_out, "%d ", data(ix,iy)); + } + fprintf(f_out, "\n"); + } + else if ( typeid(T) == typeid(double) ) + for(int ix = 0 ; ix < nx ; ix++){ + for(int iy = 0 ; iy < ny ; iy++){ + fprintf(f_out, "%24.16lg ", data(ix,iy)); + } + fprintf(f_out, "\n"); + } + else { + printf("write_datafile: template not implemented\n"); + exit(1); + } + + if(fclose(f_out)){ + printf("write_datafile: could not close file '%s'\n",filename); + exit(1); + } + +#ifdef VERBOSE + printf("Data written to '%s' in a matrix form [%d X %d]\n", filename,nx,ny); +#endif + + return ; + +} +template void write_datafile(const Array2D &data, const char *filename); +template void write_datafile(const Array2D &data, const char *filename); + +// Write the contents of a 2d array data of typename T to file filename in a matrix form +template +void write_datafile(const Array2D &data, const char *filename, const char *action) +{ + + int nx=data.XSize(); + int ny=data.YSize(); + + if ( ( string(action) != string("w") ) && ( string(action) != string("a") ) ) { + printf("write_datafile: unknown file action '%s'\n",action); + exit(1); + } + + FILE* f_out; + if(!(f_out = fopen(filename,action))){ + printf("write_datafile: could not open file '%s'\n",filename); + exit(1); + } + + if ( typeid(T) == typeid(int) ) + for(int ix = 0 ; ix < nx ; ix++){ + for(int iy = 0 ; iy < ny ; iy++){ + fprintf(f_out, "%d ", data(ix,iy)); + } + fprintf(f_out, "\n"); + } + else if ( typeid(T) == typeid(double) ) + for(int ix = 0 ; ix < nx ; ix++){ + for(int iy = 0 ; iy < ny ; iy++){ + fprintf(f_out, "%24.16lg ", data(ix,iy)); + } + fprintf(f_out, "\n"); + } + else { + printf("write_datafile: template not implemented\n"); + exit(1); + } + + if(fclose(f_out)){ + printf("write_datafile: could not close file '%s'\n",filename); + exit(1); + } + +#ifdef VERBOSE + printf("Data written to '%s' in a matrix form [%d X %d]\n", filename,nx,ny); +#endif + + return ; + +} +template void write_datafile(const Array2D &data, const char *filename, const char *action); +template void write_datafile(const Array2D &data, const char *filename, const char *action); + +// Write the contents of a vector array with data of typename T to file filename in a matrix form +template +void write_datafile(const std::vector &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action) +{ + + if ( ( string(storage) != string("C") ) && ( string(storage) != string("R") ) ) { + printf("write_datafile: unknown storage type '%s'\n",action); + exit(1); + } + + if ( ( string(action) != string("w") ) && ( string(action) != string("a") ) ) { + printf("write_datafile: unknown file action '%s'\n",action); + exit(1); + } + + FILE *f_out; + if(!(f_out = fopen(filename,action))){ + printf("write_datafile: could not open file '%s'\n",filename); + exit(1); + } + + if ( typeid(T) == typeid(int) ) { + if ( string(storage) == string("C") ) { + for(int ix = 0 ; ix < nrows ; ix++) { + for(int iy = 0 ; iy < ncols ; iy++) { + fprintf(f_out, "%d ", data[iy*nrows+ix]); + } + fprintf(f_out, "\n"); + } + } else { + for(int ix = 0 ; ix < nrows ; ix++) { + for(int iy = 0 ; iy < ncols ; iy++) { + fprintf(f_out, "%d ", data[ix*ncols+iy]); + } + fprintf(f_out, "\n"); + } + } + } // end of typeid int + else if ( typeid(T) == typeid(double) ) { + if ( string(storage) == string("C") ) { + for(int ix = 0 ; ix < nrows ; ix++) { + for(int iy = 0 ; iy < ncols ; iy++) { + fprintf(f_out, "%24.16lg ", data[iy*nrows+ix]); + } + fprintf(f_out, "\n"); + } + } else { + for(int ix = 0 ; ix < nrows ; ix++) { + for(int iy = 0 ; iy < ncols ; iy++) { + fprintf(f_out, "%24.16lg ", data[ix*ncols+iy]); + } + fprintf(f_out, "\n"); + } + } + } // end of typeid double + else { + printf("write_datafile: template not implemented\n"); + exit(1); + } + + if(fclose(f_out)){ + printf("write_datafile: could not close file '%s'\n",filename); + exit(1); + } + +#ifdef VERBOSE + printf("Data written to '%s' in a matrix form [%d X %d]\n", filename,nrows,ncols); +#endif + + return ; + +} +template void write_datafile(const std::vector &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action); +template void write_datafile(const std::vector &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action); + +// Write the contents of a 1d array data of typename T to file filename in a vector form +template +void write_datafile_1d(const Array1D& data, const char* filename) +{ + + int nx=data.XSize(); + + FILE* f_out; + if(!(f_out = fopen(filename,"w"))){ + printf("write_datafile_1d: could not open file '%s'\n",filename); + exit(1); + } + + if ( typeid(T) == typeid(int) ) + for(int ix = 0 ; ix < nx ; ix++) + fprintf(f_out, "%d\n", data(ix)); + else if ( typeid(T) == typeid(double) ) + for(int ix = 0 ; ix < nx ; ix++) + fprintf(f_out, "%24.16lg\n",data(ix)); + else { + printf("write_datafile_1d: could not open file '%s'\n",filename); + exit(1); + } + + if(fclose(f_out)){ + printf("write_datafile_1d: template not implemented\n"); + exit(1); + } + +#ifdef VERBOSE + printf("Data written to '%s' in a matrix form [%d X 1]\n", filename,nx); +#endif + + return; + +} +template void write_datafile_1d(const Array1D &data, const char *filename); +template void write_datafile_1d(const Array1D &data, const char *filename); diff --git a/cpp/lib/array/arrayio.h b/cpp/lib/array/arrayio.h new file mode 100644 index 00000000..ed1a989a --- /dev/null +++ b/cpp/lib/array/arrayio.h @@ -0,0 +1,98 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file arrayio.h +/// \brief Header file for array read/write utilities + +#ifndef ARRAYIO_H +#define ARRAYIO_H + +#include +#include +#include +#include + +#include "Array1D.h" +#include "Array2D.h" + + +/// \brief Read a datafile from filename in a matrix form +/// and store it in the 2d array data of typename T +/// \note The array data needs to have the correct sizes +template void read_datafile(Array2D &data, const char *filename); + +/// \brief Read a datafile from filename in a matrix form +/// and store it in the 2d array data if typename T +/// \note The array data is resized to match the file contents +/// \note This function makes two passes: the first pass figures the no. or rows and columns, +/// then the data array is appropriately resized, and the filename is read during second pass +template void read_datafileVS(Array2D &data, const char *filename); + +/// \brief Read a datafile from filename in a matrix form +/// and store it in a std::vector in column-major storage scheme +/// \note The vector is resized to match the file contents +/// \note This function makes two passes: the first pass figures the no. or rows and columns, +/// then the data vector is appropriately resized, and the filename is read during second pass +template void read_datafileVS(std::vector &data, int &nrows, int &ncols, const char *filename); + +/// \brief Read a data from filename in a vector form +/// and store it in a 1d array data of typename T +/// \note The array data needs to have the correct size +template void read_datafile_1d(Array1D& data, const char* filename); + +/// \brief Read a datafile from filename in a vector form +/// and store it in the 1d array data of typename T +/// \note The array data is resized to match the file contents +/// \note This function makes two passes: the first pass figures the no. or rows and columns, +/// then the data array is appropriately resized, and the filename is read during second pass +template void read_datafileVS(Array1D &data, const char *filename); + +/// \brief Write/append the contents of a 2d array data of typename T +/// to file filename in a matrix form +template +void write_datafile(const Array2D &data, const char *filename, const char *action); + +/// \brief Write the contents of a 2d array data of typename T +/// to file filename in a matrix form +template +void write_datafile(const Array2D &data, const char *filename); + +/// \brief Write the contents of a vector of typename T +/// to file filename in a matrix form +template +void write_datafile(const std::vector &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action); + +/// \brief Write to file filename the number of rows and number of +/// columns on the first line, followed by the contents of a 2d array +/// data of typename T in a matrix form. +template +void write_datafile_size(const Array2D &data, const char *filename); + +/// \brief Write the contents of a 1d array data of typename T +/// to file filename in a vector form +template void write_datafile_1d(const Array1D& data, const char* filename); + +#endif // ARRAYIO_H diff --git a/cpp/lib/array/arraytools.cpp b/cpp/lib/array/arraytools.cpp new file mode 100644 index 00000000..921578b3 --- /dev/null +++ b/cpp/lib/array/arraytools.cpp @@ -0,0 +1,2373 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file arraytools.cpp +/// \brief Tools to manipulate Array 1D and 2D objects. Some tools mimick MATLAB functionalities. + + +#include "stdlib.h" +#include "stdio.h" +#include "math.h" +#include "assert.h" +#include +#include +#include + +#include "arraytools.h" +#include "ftndefs.h" +#include "gen_defs.h" +#include "depblas.h" +#include "deplapack.h" + +using namespace std; + +// Store a given 1d array in a 2d array with a single second dimension +template +void array1Dto2D(Array1D &arr_1d, Array2D &arr) +{ + int nd=arr_1d.XSize(); + arr.Resize(nd,1); + + for(int i=0;i &arr_1d, Array2D &arr); +template void array1Dto2D(Array1D &arr_1d, Array2D &arr); + +// Store a given 2d array with a single second dimension in a 1d array +template +void array2Dto1D(Array2D &arr_2d, Array1D &arr) +{ + int nd = arr_2d.XSize(); + int one = arr_2d.YSize(); + + // Size check + CHECKEQ(one,1); + + arr.Resize(nd); + + for(int i=0;i &arr_2d,Array1D &arr); +template void array2Dto1D(Array2D &arr_2d,Array1D &arr); + +// Paste two 1d arrays of same size into a single 2d array with second dimension equal to two +template +void paste(Array1D& arr1,Array1D& arr2,Array2D& arr) +{ + int n=arr1.XSize(); + int m=arr2.XSize(); + + // Size check + CHECKEQ(n,m); + + arr.Resize(n,2); + for(int i=0;i &arr1, Array1D &arr2, Array2D &arr); +template void paste(Array1D &arr1, Array1D &arr2, Array2D &arr); + +// Generates multigrid as a cartesian product of each column of grid +template +void generate_multigrid(Array2D& multigrid,Array2D& grid) +{ + int ngrid=grid.XSize(); + int ndim=grid.YSize(); + + int totgrid= (int) pow(ngrid,ndim); + multigrid.Resize(totgrid,ndim); + + // Work arrays + Array2D pIndex(totgrid,ndim,0); + + // Indexing + for (int it=0;it-1;jdim--){ + dnum = dnum + pIndex(it,jdim+1)*pow(ngrid,jdim+1); + pIndex(it,jdim) =(int) (it-dnum)/pow(ngrid,jdim); + } + } + + // Fill in the array + for (int it=0;it &multigrid, Array2D &grid); +template void generate_multigrid(Array2D &multigrid, Array2D &grid); + +// Paste two 2D arrays next to each other (horizontal stack) +void paste(Array2D& x, Array2D& y, Array2D& xy) +{ + + int nsample = x.XSize(); + + // Size check + CHECKEQ(nsample, (int) y.XSize()); + + + int ndim1 = x.YSize(); + int ndim2 = y.YSize(); + int ndim = ndim1+ndim2; + + int ntot1 = nsample*ndim1 ; + int ntot2 = nsample*ndim2 ; + int incr = 1 ; + + xy.Resize(nsample,ndim); + FTN_NAME(dcopy)(&ntot1,x.GetArrayPointer(),&incr,xy.GetArrayPointer(), &incr); + FTN_NAME(dcopy)(&ntot2,y.GetArrayPointer(),&incr,xy.GetArrayPointer()+ntot1,&incr); + + //// Older implementation + // for (int i=0;i& x, Array2D& y, Array2D& xy) +{ + int ndim=x.YSize(); + + // Size check + CHECKEQ(ndim,(int) y.YSize()); + + int nsample1=x.XSize(); + int nsample2=y.XSize(); + int nsample=nsample1+nsample2; + xy.Resize(nsample,ndim); + + + for (int i=0;i& x, Array1D& y, Array1D& xy) +{ + int ns1 = x.XSize(); + int ns2 = y.XSize(); + + int ns12 = ns1+ns2; + int incr = 1; + + xy.Resize(ns12,0.e0); + + FTN_NAME(dcopy)(&ns1,x.GetArrayPointer(),&incr,xy.GetArrayPointer(), &incr); + FTN_NAME(dcopy)(&ns2,y.GetArrayPointer(),&incr,xy.GetArrayPointer()+ns1,&incr); + + // for (int i=0;i& x, Array1D& y, Array1D& xy) +{ + int ns1=x.XSize(); + int ns2=y.XSize(); + + int ns12=ns1+ns2; + + xy.Resize(ns12,0); + + for (int i=0; i& x, Array1D& y) +{ + int ns1 = x.XSize(); + int ns2 = y.XSize(); + + int ns12 = ns1+ns2; + int incr = 1; + + x.Resize(ns12); + //for (int i=ns1;i& x, Array1D& y) +{ + int ns1 = x.XSize(); + int ns2 = y.XSize(); + int ns12= ns1+ns2; + + x.Resize(ns12); + for (int i=ns1;i +void transpose(Array2D &x, Array2D &xt) +{ + int nx = x.XSize(); + int ny = x.YSize(); + + xt.Resize(ny, nx); + + for (int ix=0; ix &x, Array2D &xt); +template void transpose(Array2D &x, Array2D &xt); + +// Unfold/flatten a 2d array into a 1d array (double format) +void flatten(Array2D& arr_2, Array1D& arr_1) +{ + int nx=arr_2.XSize(); + int ny=arr_2.YSize(); + + int nxy=nx*ny; + + arr_1.Resize(nxy,0.e0); + + for(int i=0;i& x1, Array2D& x2) +{ + int nx=x2.XSize(); + int ny=x2.YSize(); + int nxy=nx*ny; + + // Size check + CHECKEQ(nxy,(int) x1.XSize()); + + for(int i=0;i& arr,int i,int j) +{ + + double h=arr(i); + arr(i)=arr(j); + arr(j)=h; + + return; +} + +// Swap i-th and j-th rows of the 2d array arr +void swap(Array2D& arr,int i,int j) +{ + int n=arr.YSize(); + double tmp; + for (int d=0;d& arr_1, int i, int j) +{ + // Size check + CHECKEQ(nx*ny,(int) arr_1.XSize()); + + return arr_1(j+i*ny); +} + +// Retrieves row 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d' +template +void getRow(Array2D &arr2d, int k, Array1D &arr1d) +{ + + arr1d.Clear(); + for(int i=0; i<(int)arr2d.YSize(); i++) + arr1d.PushBack(arr2d(k,i)); + + return; + +} +template void getRow(Array2D &arr2d, int k, Array1D &arr1d); +template void getRow(Array2D &arr2d, int k, Array1D &arr1d); + +// Retrieves column 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d' +template +void getCol(Array2D& arr2d, int k, Array1D& arr1d) +{ + arr1d.Clear(); + for(int i=0;i<(int)arr2d.XSize();i++) + arr1d.PushBack(arr2d(i,k)); + + return; +} +template void getCol(Array2D &arr2d, int k, Array1D &arr1d); +template void getCol(Array2D &arr2d, int k, Array1D &arr1d); + +// Adds 'val' to the first n elements of an array pointer (double or int) +template +void addVal(int n, T *arr1d, T val) +{ + for(int i=0; i< n; i++) arr1d[i] += val; + + return; +} +template void addVal(int n, double *arr1d, double val); +template void addVal(int n, int *arr1d, int val); + +// Adds 'val' to all elements of 1D array arr1d (double or int) +template +void addVal(Array1D &arr1d, T val) { + for(int i=0; i< (int)arr1d.XSize(); i++) arr1d(i) += val; + + return; +} +template void addVal(Array1D &arr1d, double val); +template void addVal(Array1D &arr1d, int val); + +// Adds 'val' to all elements of 2D array arr2d (double or int) +template +void addVal(Array2D &arr2d, T val) { + for(int j=0; j< (int)arr2d.YSize(); j++) + for(int i=0; i< (int)arr2d.XSize(); i++) + arr2d(i,j) += val; + return; +} +template void addVal(Array2D &arr2d, double val); +template void addVal(Array2D &arr2d, int val); + +// Extracts from 'vector', elements corresponding to indices 'ind' and returns them in 'subvector' (double or int) +template +void subVector(Array1D &vector, Array1D &ind, Array1D &subvector) +{ + + int n = vector.XSize(); + int k = ind.XSize(); + + subvector.Resize(k, (T) 0); + for (int ik=0; ik=n ){ + printf("subVector()::Index ind(%d)=%d is not allowed. Exiting.\n",ik,ind(ik)); + exit(1); + } + subvector(ik)=vector(ind(ik)); + + } + + return; + +} +template void subVector(Array1D &vector, Array1D &ind, Array1D &subvector); +template void subVector(Array1D &vector, Array1D &ind, Array1D &subvector); + +// Extracts from 'matrix' rows corresponding to indices 'ind' and returns them in 'submatrix' (double or int) +template +void subMatrix_row(Array2D &matrix, Array1D &ind, Array2D &submatrix) { + int n=matrix.XSize(); + int m=matrix.YSize(); + int k=ind.XSize(); + + submatrix.Resize(k,m, (T) 0); + for (int ik=0;ik=n){ + printf("subMatrix()::Index ind(%d)=%d is not allowed. Exiting.\n",ik,ind(ik)); + exit(1); + } + for (int im=0;im &matrix, Array1D &ind, Array2D &submatrix); +template void subMatrix_row(Array2D &matrix, Array1D &ind, Array2D &submatrix); + +// Extracts from 'matrix' columns corresponding to indices 'ind' and returns them in 'submatrix' (double or int) +template +void subMatrix_col(Array2D &matrix, Array1D &ind, Array2D &submatrix) { + + int n=matrix.XSize(); + int m=matrix.YSize(); + int k=ind.XSize(); + + submatrix.Resize(n,k, (T) 0); + for (int ik=0;ik=m){ + printf("subMatrix()::Index ind(%d)=%d is not allowed. Exiting.\n",ik,ind(ik)); + exit(1); + } + for (int in=0;in &matrix, Array1D &ind, Array2D &submatrix); +template void subMatrix_col(Array2D &matrix, Array1D &ind, Array2D &submatrix); + +// Adds scaled row or column to all rows / columns of a matrix (double or int) +template +void matPvec(Array2D &matrix, const Array1D &rc, T alpha, char *RC) { + + int nrows = matrix.XSize(); + int ncols = matrix.YSize(); + + if ( std::string(RC) == std::string("C")) { + if (nrows != (int) rc.Length()) { + cout << "arraytools.cpp::matPvec(): Mismatch in array sizes: "< rcLoc = rc; + if ( (double) alpha-1.0 != 0.0 ) { + scaleinplace(rcLoc,alpha); + } + + if ( std::string(RC) == std::string("C")) { + for (int i2=0; i2 &matrix, const Array1D &rc, double alpha, char *RC); +template void matPvec(Array2D &matrix, const Array1D &rc, int alpha, char *RC); + +// Returns maximum value in 'vector' and its location in *indx (double or int) +template +T maxVal(const Array1D &vector, int *indx) +{ + + T maxVal_ = vector(0); + (*indx) = 0 ; + for(int i=1; i < (int) vector.XSize(); i++) + if (vector(i) > maxVal_) { + maxVal_ = vector(i); + (*indx) = i ; + } + return maxVal_; + +} +template double maxVal(const Array1D &vector, int *indx); +template int maxVal(const Array1D &vector, int *indx); + +// Returns in C elements of A that are not in B; C is sorted in ascending order +void setdiff(Array1D &A, Array1D &B, Array1D &C) +{ + C.Clear() ; + bool fnd; + for ( int i = 0; i < (int) A.XSize() ; i++ ) + { + fnd = false; + for ( int j = 0; j < (int) B.XSize() ; j++ ) + if ( A(i) == B(j) ) fnd = true ; + if ( !fnd) C.PushBack(A(i)); + } + + /* order C in ascending order */ + shell_sort(C); + return ; + +} + +// Returns in C elements of A that are not in B; C is sorted in ascending order +// Assumes A is sorted +void setdiff_s(Array1D &A, Array1D &B, Array1D &C) +{ + shell_sort(B); + + C.Clear() ; + int j=0; + + for ( int i = 0; i < (int) A.XSize() ; i++ ) + { + while(A(i)>B(j)){ + j++; + } + if ( A(i) < B(j) ) + C.PushBack(A(i)); + } + + return ; + +} + +// Sorts integer array +void shell_sort (int *a, int n) { + + int j ; + for (int h = n/2; h>0; h = h/2) { + for ( int i = h; i < n; i++) { + + int k = a[i]; + for ( j = i; j >= h && k < a[j - h]; j -= h) + a[j] = a[j - h]; + + a[j] = k; + + } + } + + return ; + +} + +// Sorts integer array in ascending order +void shell_sort(Array1D& array) +{ + int flag = 1, length = array.XSize(), i; + int temp; + int d=length; + while( flag || (d>1)){ // boolean flag (true when not equal to 0) + flag = 0; // reset flag to 0 to check for future swaps + d = (d+1) / 2; + for (i = 0; i < (length - d); i++){ + if (array(i + d) < array(i)){ + temp = array(i + d); // swap items at positions i+d and d + array(i + d)= array(i); + array(i) = temp; + flag = 1; // indicate that a swap has occurred + } + } + } + return; +} + +// Sorts double array in ascending order +void shell_sort(Array1D& array) +{ + int flag = 1, length = array.XSize(), i; + double temp; + int d=length; + while( flag || (d>1)) // boolean flag (true when not equal to 0) + { + flag = 0; // reset flag to 0 to check for future swaps + d = (d+1) / 2; + for (i = 0; i < (length - d); i++){ + if (array(i + d) < array(i)) + { + temp = array(i + d); // swap items at positions i+d and d + array(i + d)= array(i); + array(i) = temp; + flag = 1; // indicate that a swap has occurred + } + } + } + + return; +} + +// Sorts double array in ascending order according to a given column +void shell_sort_col(Array2D& array,int col, Array1D& newInd, Array1D& oldInd) +{ + + int flag = 1, length = array.XSize(), ncol=array.YSize(),i,j; + double temp; + int d=length, tmp; + + + newInd.Resize(length,0); + + while( flag || (d>1)){ // boolean flag (true when not equal to 0) + flag = 0; // reset flag to 0 to check for future swaps + d = (d+1) / 2; + for (i = 0; i < (length - d); i++){ + if (array(i + d,col) < array(i,col)) + { + for (j=0;j& array,Array1D& newInd, Array1D& oldInd) +{ + int flag = 1, length = array.XSize(), ncol=array.YSize(),i,j; + double temp; + int d=length, tmp; + + newInd.Resize(length,0); + + while( flag || (d>1)){ // boolean flag (true when not equal to 0) + flag = 0; // reset flag to 0 to check for future swaps + d = (d+1) / 2; + for (i = 0; i < (length - d); i++){ + bool swflag=false; + for(int col=0;col 1e-10 ){ + if (fabs(array(i + d,col) - array(i,col) ) > 1e-10 && array(i + d,col) < array(i,col)){ + swflag=true; break; + } + else if (fabs(array(i + d,col) - array(i,col) ) > 1e-10 && array(i + d,col) > array(i,col)){ + swflag=false; break; + } + else {} + } + + if (swflag){ + for (j=0;j& arr, int l, int r) +{ + if (l>=r) return; + int i = l-1, j = r, p = l-1, q = r; + double v = arr(r); + if (r <= l) return; + for (;;) + { + while (arr(++i) < v) ; + while (v < arr(--j)) if (j == l) break; + if (i >= j) break; + swap(arr,i,j); + if (arr(i) == v) { p++; swap(arr,p,i); } + if (v == arr(j)) { q--; swap(arr,j,q); } + } + swap(arr,i,r); j = i-1; i = i+1; + for (int k = l; k < p; k++, j--) swap(arr,k,j); + for (int k = r-1; k > q; k--, i++) swap(arr,i,k); + quicksort3(arr, l, j); + quicksort3(arr, i, r); + + return; +} + +// Quick-sort with 3-way partitioning of 2d array between indices l and r, according to column col +void quicksort3(Array2D& arr,int l, int r,int col) +{ + if (l>=r) return; + int i = l-1, j = r, p = l-1, q = r; + double v = arr(r,col); + if (r <= l) return; + for (;;) + { + while (arr(++i,col) < v) ; + while (v < arr(--j,col)) if (j == l) break; + if (i >= j) break; + swap(arr,i,j); + if (arr(i,col) == v) { p++; swap(arr,p,i); } + if (v == arr(j,col)) { q--; swap(arr,j,q); } + } + swap(arr,i,r); j = i-1; i = i+1; + for (int k = l; k < p; k++, j--) swap(arr,k,j); + for (int k = r-1; k > q; k--, i++) swap(arr,i,k); + + quicksort3(arr, l, j,col); + quicksort3(arr, i, r,col); + return; + +} + +// Quick-sort with 3-way partitioning of 2d array between indices l and r, and sorting is done comparing rows (by first element, then by second, etc...) +void quicksort3(Array2D& arr, int l, int r) +{ + if (l>=r) return; + int i = l-1, j = r, p = l-1, q = r; + Array1D v; + getRow(arr,r,v); + if (r <= l) return; + Array1D arri,arrj; + for (;;) + { + do{getRow(arr,++i,arri);} while (is_less(arri,v)); + do{getRow(arr,--j,arrj); if (j == l) break;}while (is_less(v,arrj)); + if (i >= j) break; + swap(arr,i,j); + getRow(arr,i,arri); + if (is_equal(arri,v)) { p++; swap(arr,p,i); } + getRow(arr,j,arrj); + if (is_equal(v,arrj)) { q--; swap(arr,j,q); } + } + swap(arr,i,r); j = i-1; i = i+1; + for (int k = l; k < p; k++, j--) swap(arr,k,j); + for (int k = r-1; k > q; k--, i++) swap(arr,i,k); + + quicksort3(arr, l, j); + quicksort3(arr, i, r); + + return; +} + +// Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order +// It also returns the original locations of these entries in 1D arrays 'iA' and 'iB', respectively +void intersect(Array1D &A, Array1D &B, Array1D &C,Array1D &iA,Array1D &iB) +{ + C.Clear() ; + iA.Clear() ; + iB.Clear() ; + for ( int i = 0; i < (int) A.XSize() ; i++ ) + for ( int j = 0; j < (int) B.XSize() ; j++ ) + if ( A(i) == B(j) ) + { + C.PushBack(A(i)); + iA.PushBack(i); + iB.PushBack(j); + } + + /* order C in ascending order */ + bool chgOrd=true; + while (chgOrd) + { + chgOrd=false; + for ( int i = 0; i < (int) C.XSize()-1 ; i++ ) + { + if (C(i)>C(i+1)) + { + chgOrd=true; + int itmp ; + itmp = C(i); C(i) = C(i+1); C(i+1) =itmp ; + itmp = iA(i); iA(i) = iA(i+1); iA(i+1)=itmp ; + itmp = iB(i); iB(i) = iB(i+1); iB(i+1)=itmp ; + } + } + } + return ; + +} + +// Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order +void intersect(Array1D &A, Array1D &B, Array1D &C) +{ + C.Clear() ; + for ( int i = 0; i < (int) A.XSize() ; i++ ) + for ( int j = 0; j < (int) B.XSize() ; j++ ) + if ( A(i) == B(j) ) + C.PushBack(A(i)); + + /* order C in ascending order */ + bool chgOrd=true; + while (chgOrd) + { + chgOrd=false; + for ( int i = 0; i < (int) C.XSize()-1 ; i++ ) + { + if (C(i)>C(i+1)) + { + chgOrd=true; + int itmp ; + itmp = C(i); C(i) = C(i+1); C(i+1) =itmp ; + } + } + } + return ; + +} + +// Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" ), +// larger or equal ( type="ge" ), smaller ( type="lt" ), smaller or equal ( type="le" ) than lmbda +template +void find(Array1D &theta, T lmbda, string type, Array1D &indx) +{ + indx.Clear(); + if ( type == "gt" ) { + for ( int i = 0; i<(int) theta.XSize(); i++) + if ( theta(i) > lmbda ) indx.PushBack(i) ; + return ; + } + if ( type == "ge" ) { + for ( int i = 0; i<(int) theta.XSize(); i++) + if ( theta(i) >= lmbda ) indx.PushBack(i) ; + return ; + } + if ( type == "lt" ) { + for ( int i = 0; i<(int) theta.XSize(); i++) + if ( theta(i) < lmbda ) indx.PushBack(i) ; + return ; + } + if ( type == "le" ) { + for ( int i = 0; i<(int) theta.XSize(); i++) + if ( theta(i) <= lmbda ) indx.PushBack(i) ; + return ; + } + if ( type == "eq" ) { + for ( int i = 0; i<(int) theta.XSize(); i++) + if ( theta(i) == lmbda ) indx.PushBack(i) ; + return ; + } + return ; +} +template void find(Array1D &theta, double lmbda, string type, Array1D &indx); +template void find(Array1D &theta, int lmbda, string type, Array1D &indx); + +// Implements y = a A x +void prodAlphaMatVec(Array2D& A, Array1D& x, double alpha, Array1D& y) +{ + + int n=A.XSize(); + int m=A.YSize(); + + // Size check + CHECKEQ(m, (int) x.XSize()); + + y.Resize(n,0.e0); + + char trans='n'; + double beta=0.e0; + int xinc=1; + int yinc=1; + FTN_NAME(dgemv)(&trans, &n, &m, &alpha, A.GetArrayPointer(), &n, x.GetArrayPointer(), &xinc, &beta, y.GetArrayPointer(), &yinc ); + + /* older implementation + for (int i=0;i& A, Array1D& x, double alpha, Array1D& y) +{ + + int n=A.YSize(); + int m=A.XSize(); + + // Size check + CHECKEQ(m, (int) x.XSize()); + + + y.Resize(n,0.e0); + + char trans='t'; + double beta=0.e0; + int xinc=1; + int yinc=1; + FTN_NAME(dgemv)(&trans, &m, &n, &alpha, A.GetArrayPointer(), &m, x.GetArrayPointer(), &xinc, &beta, y.GetArrayPointer(), &yinc ); + + /* + for (int i=0;i& A, Array2D& B, double alpha, Array2D& C) +{ + + int n=A.YSize(); + int m=A.XSize(); + int k=B.YSize(); + + // Size check + CHECKEQ(n, (int) B.XSize()); + + + C.Resize(m,k,0.e0); + + char transa='n'; + char transb='n'; + + double beta=0.e0; + + + FTN_NAME(dgemm)(&transa, &transb, &m, &k, &n, &alpha, A.GetArrayPointer(), &m, B.GetArrayPointer(), &n, &beta, C.GetArrayPointer(), &m ); + + /* + for (int j=0;j& A, Array2D& B, double alpha, Array2D& C) +{ + + int n=A.XSize(); + int m=A.YSize(); + int k=B.YSize(); + + // Size check + CHECKEQ(n, (int) B.XSize()); + + + C.Resize(m,k,0.e0); + + char transa='t'; + char transb='n'; + + double beta=0.e0; + + + FTN_NAME(dgemm)(&transa, &transb, &m, &k, &n, &alpha, A.GetArrayPointer(), &n, B.GetArrayPointer(), &n, &beta, C.GetArrayPointer(), &m ); + + /* + for (int j=0;j& x, double alpha, Array1D& y, int ip) +{ + // Size check + CHECKEQ( (int) x.XSize(), (int) y.XSize() ); + + for (int i = 0; i < (int) x.XSize(); i++) + x(i) += alpha*pow(y(i),ip) ; + + return ; + +} + +// Returns a^T B c +double prod_vecTmatvec(Array1D& a, Array2D& B, Array1D& c) +{ + double prod=0.e0; + + Array1D tmp; + prodAlphaMatTVec(B,a,1.0,tmp); + prod=dot(tmp,c); + + return prod; +} + +// Returns A^T A +Array2D MatTMat(Array2D& A) +{ + int n=A.XSize(); + int k=A.YSize(); + + Array2D B(k,k,0.e0); + for (int i=0;i +void delRow(Array2D& A, int irow) +{ + + int n = A.XSize() ; + int m = A.YSize() ; + + if ( n <= 1 || m == 0 ) return ; + + Array2D B(n-1,m) ; + for ( int i = 0; i < irow; i++ ) + for ( int j = 0; j < m; j++) + B(i,j) = A(i,j) ; + for ( int i = irow+1; i < n; i++ ) + for ( int j = 0; j < m; j++) + B(i-1,j) = A(i,j) ; + + A.Resize(n-1,m); + for ( int i = 0; i < n-1; i++ ) + for ( int j = 0; j < m; j++) + A(i,j) = B(i,j) ; + + return ; + +} +template void delRow(Array2D &A, int irow); +template void delRow(Array2D &A, int irow); + +// Deletes a column from a matrix +template +void delCol(Array2D &A, int icol) +{ + + int n = A.XSize() ; + int m = A.YSize() ; + + if ( n == 0 || m <= 1 ) return ; + + Array2D B(n,m-1) ; + for ( int i = 0; i < n; i++ ) + for ( int j = 0; j < icol; j++) + B(i,j) = A(i,j) ; + for ( int i = 0; i < n; i++ ) + for ( int j = icol+1; j < m; j++) + B(i,j-1) = A(i,j) ; + + A.Resize(n,m-1); + for ( int i = 0; i < n; i++ ) + for ( int j = 0; j < m-1; j++) + A(i,j) = B(i,j) ; + + return ; + +} +template void delCol(Array2D &A, int icol); +template void delCol(Array2D &A, int icol); + +// Deletes an element from an array +template +void delCol(Array1D &x, int icol) +{ + + int n = x.XSize() ; + + if ( n == 0 ) return ; + + Array1D y(n-1) ; + for ( int i = 0; i &x, int icol) ; +template void delCol(Array1D &x, int icol) ; + +// Padds 2D double array 'A' with the row 'x' +void paddMatRow(Array2D& A, Array1D& x) +{ + + int n = A.XSize() ; + int m = A.YSize() ; + + // Size check + CHECKEQ(m, (int) x.XSize()); + + Array2D B ; + B=A; + A.Resize(n+1,m); + for ( int i = 0; i < m; i++ ) + { + for ( int j = 0; j < n; j++) + A(j,i) = B(j,i) ; + A(n,i) = x(i) ; + } + + return ; + +} + +// Padds 2D array 'A' with the column 'x' +void paddMatCol(Array2D& A, Array1D& x) +{ + + int n = A.XSize() ; + int m = A.YSize() ; + + // Size check + CHECKEQ(n, (int) x.XSize()); + + + Array2D B ; + B=A; + A.Resize(n,m+1); + for ( int i = 0; i < n; i++ ) + { + for ( int j = 0; j < m; j++) + A(i,j) = B(i,j) ; + A(i,m) = x(i) ; + } + + return ; + +} + +// Padds 2D int array 'A' with the row 'x' +void paddMatRow(Array2D& A, Array1D& x) +{ + + int n = A.XSize() ; + int m = A.YSize() ; + + // Size check + CHECKEQ(m, (int) x.XSize()); + + Array2D B ; + B=A; + A.Resize(n+1,m); + for ( int i = 0; i < m; i++ ) + { + for ( int j = 0; j < n; j++) + A(j,i) = B(j,i) ; + A(n,i) = x(i) ; + } + + return ; + +} + +// Padds 2D int array 'A' with the column 'x' +void paddMatCol(Array2D& A, Array1D& x) +{ + + int n = A.XSize() ; + int m = A.YSize() ; + + // Size check + CHECKEQ(n, (int) x.XSize()); + + + + Array2D B ; + B=A; + A.Resize(n,m+1); + for ( int i = 0; i < n; i++ ) + { + for ( int j = 0; j < m; j++) + A(i,j) = B(i,j) ; + A(i,m) = x(i) ; + } + + return ; + +} + +// Padds square matrix A with a row and column x, and adds an element A_{n+1,n+1} to obtain a larger square matrix +void paddMatColScal(Array2D& A, Array1D& x, double scal) +{ + + int n = x.XSize() ; + + // Size check + CHECKEQ(n, (int) A.YSize() ); + CHECKEQ(n, (int) A.XSize()); + + + Array2D B ; + B=A; + A.Resize(n+1,n+1); + for ( int i = 0; i < n; i++ ) + { + for ( int j = 0; j < n; j++) + A(i,j) = B(i,j) ; + A(i,n) = A(n,i)=x(i) ; + } + A(n,n) = scal ; + + return ; + +} + +// Checks if two 1d int arrays are equal +bool is_equal(Array1D& a, Array1D& b){ + + int n=a.XSize(); + int m=b.XSize(); + if (n!=m) + return false; + + for (int i=0;i& a, Array1D& b) +{ + + int n=a.XSize(); + int m=b.XSize(); + if (n!=m) + return false; + + for (int i=0;i1.e-10) + return false; + + } + + return true; +} + +// Checks if one 1d int array is less than another (by first element, then by second, etc...) +bool is_less(Array1D& a, Array1D& b) +{ + + int n=a.XSize(); + int m=b.XSize(); + + // Size check + CHECKEQ(n,m); + + for (int i=0;ib(i)) + return false; + else if (a(i)& a, Array1D& b) +{ + + int n=a.XSize(); + int m=b.XSize(); + + // Size check + CHECKEQ(n,m); + + for (int i=0;i1.e-10) + //{ + if (a(i)>b(i)) + return false; + else if (a(i)& vec, Array2D& array) +{ + int dd=array.XSize(); + int dim=vec.XSize(); + + // Size check + CHECKEQ(dim,(int) array.YSize()); + + for(int i=0;i& arr) +{ + int i,ir,j,l,mid; + double a; + + int n=arr.XSize(); + l=0; + ir=n-1; + for(;;){ + if (ir<=l+1){ + if (ir==l+1 && arr(ir)> 1; + swap(arr,mid,l+1); + if (arr(l)>arr(ir)) + swap(arr,l,ir); + if (arr(l+1)>arr(ir)) + swap(arr,l+1,ir); + if (arr(l)>arr(l+1)) + swap(arr,l,l+1); + i=l+1; + j=ir; + a=arr(l+1); + for(;;){ + do i++; while (arr(i)a); + if (j=k) ir=j-1; + if (j<=k) l=i; + } + } +} + + +// Log-determinant of a real symmetric positive-definite matrix +double logdeterm(Array2D& mat) +{ + Array2D A; + A=mat; + + int nd=A.XSize(); + int chol_info=0; + char lu='L'; + double logDet=0.0; + + // Cholesky factorization, done in-place + + //for(int i=0;i& mat) +{ + + int nd=mat.XSize(); + double trace = 0.0; + + for(int i = 0; i < nd; i++) trace += mat(i,i); + + return trace; +} + +// Evaluates the natural logarithm of a multivariate normal distribution +double evalLogMVN(Array1D& x,Array1D& mu,Array2D& Sigma) +{ + // Check that the dimesnions match + if(Sigma.XSize() != Sigma.YSize()) + throw Tantrum((string) "Error in evalMVN: passed matrix is not square"); + + // Check that the dimesnions match + if(Sigma.XSize() != x.XSize()) + throw Tantrum((string) "Error in evalMVN: dimension mismatch in passed matrix and vector"); + + // Check that the dimesnions match + if(Sigma.XSize() != mu.XSize()) + throw Tantrum((string) "Error in evalMVN: dimension mismatch in passed matrix and vector"); + + int dim = Sigma.XSize(); + + // Compute pi + double pi=4.0*atan(1.0); + + // Compute the inverse of the covariance matrix + Array2D invSigma(dim,dim); + invSigma = INV(Sigma); + + // Compute the argument of the exponential + Array1D diff(dim,0.0); + Array1D matvec; + for (int i=0; i diag(Array1D& diagonal_array) +{ + + int nx=diagonal_array.Length(); + Array2D diagonal_matrix(nx,nx,0.e0); + for (int i=0;i copy(Array1D& in_array){ + int n = in_array.Length(); + Array1D out(n,0e0); + out = in_array; + return out; +} + +// Returns a copy of an array +Array2D copy(Array2D& in_array){ + int m = in_array.XSize(); + int n = in_array.YSize(); + Array2D out(m,n,0e0); + out = in_array; + return out; +} + +// Deletes matrix columns or rows. +Array2D mtxdel(Array2D& A, int index, int dim){ + // deletes column when dim = 1 + // deletes row when dim = 0 + int n = A.XSize() ; + int m = A.YSize() ; + + if ( n == 0 || m <= 1 ) return A; + + if (dim == 1){ + Array2D B(n,m-1) ; + for ( int i = 0; i < n; i++ ) + for ( int j = 0; j < index; j++) + B(i,j) = A(i,j) ; + for ( int i = 0; i < n; i++ ) + for ( int j = index+1; j < m; j++) + B(i,j-1) = A(i,j) ; + return B; + } + + if (dim == 0){ + Array2D B(n-1,m) ; + for ( int i = 0; i < index; i++ ) + for ( int j = 0; j < m; j++) + B(i,j) = A(i,j) ; + for ( int i = index+1; i < n; i++ ) + for ( int j = 0; j < m; j++) + B(i-1,j) = A(i,j) ; + return B; + } +} + +// add two vectors +Array1D add(Array1D& x, Array1D& y){ + + int nx = x.Length(); + int ny = y.Length(); + + if ( nx != ny ) + { + printf("add() : Error : no. of elements in x and size of y are not the same : %d %d\n", + nx,ny); + exit(1); + } + + Array1D ytemp = copy(y); + double alpha = 1; + int incr = 1; + FTN_NAME(daxpy)(&ny, &alpha, x.GetArrayPointer(), &incr, ytemp.GetArrayPointer(), &incr); + + return ytemp; +} + +// add two matrices of the same size +Array2D add(Array2D& x, Array2D& y){ + + int nx = x.XSize(); + int ny = y.XSize(); + + // Size check + CHECKEQ(nx,ny); + + int nx2 = x.YSize(); + int ny2 = y.YSize(); + + // Size check + CHECKEQ(nx2,ny2); + + Array2D temp(nx,nx2,0.0); + for (int i = 0; i < nx; i++){ + for (int j = 0; j < nx2; j++){ + temp(i,j) = x(i,j) + y(i,j); + } + } + + return temp; +} + +// add two matrices of the same size +void addinplace(Array2D& x, Array2D& y){ + + int nx = x.XSize(); + int ny = y.XSize(); + + // Size check + CHECKEQ(nx,ny); + + int nx2 = x.YSize(); + int ny2 = y.YSize(); + + // Size check + CHECKEQ(nx2,ny2); + + + // Array2D temp(nx,ny,0.0); + for (int i = 0; i < nx; i++){ + for (int j = 0; j < nx2; j++){ + x(i,j) = x(i,j) + y(i,j); + } + } + + return; +} + +// add two vectors of the same size +void addinplace(Array1D& x, Array1D& y){ + + int nx = x.XSize(); + int ny = y.XSize(); + + // Size check + CHECKEQ(nx,ny); + + for (int i = 0; i < nx; i++){ + x(i) = x(i) + y(i); + } + + return; +} + + +// subtract two vectors +Array1D subtract(Array1D& x, Array1D& y){ + + int nx = x.Length(); + int ny = y.Length(); + + // Size check + CHECKEQ(nx,ny); + + Array1D xtemp = copy(x); + double alpha = -1.0; + int incr = 1; + FTN_NAME(daxpy)(&ny, &alpha, y.GetArrayPointer(), &incr, xtemp.GetArrayPointer(), &incr); + + + return xtemp; +} + +// subtract two matrices of the same size +Array2D subtract(Array2D& x, Array2D& y){ + + int nx = x.XSize(); + int ny = y.XSize(); + + // Size check + CHECKEQ(nx,ny); + + int nx2 = x.YSize(); + int ny2 = y.YSize(); + + // Size check + CHECKEQ(nx2,ny2); + + Array2D temp(nx,nx2,0.0); + for (int i = 0; i < nx; i++){ + for (int j = 0; j < nx2; j++){ + temp(i,j) = x(i,j) - y(i,j); + } + } + + return temp; +} + + +// add two matrices of the same size +void subtractinplace(Array2D& x, Array2D& y){ + + int nx = x.XSize(); + int ny = y.XSize(); + + // Size check + CHECKEQ(nx,ny); + + int nx2 = x.YSize(); + int ny2 = y.YSize(); + + // Size check + CHECKEQ(nx2,ny2); + + + // Array2D temp(nx,ny,0.0); + for (int i = 0; i < nx; i++){ + for (int j = 0; j < nx2; j++){ + x(i,j) = x(i,j) - y(i,j); + } + } + + return; +} + +// add two vectors of the same size +void subtractinplace(Array1D& x, Array1D& y){ + + int nx = x.XSize(); + int ny = y.XSize(); + + // Size check + CHECKEQ(nx,ny); + + for (int i = 0; i < nx; i++){ + x(i) = x(i) - y(i); + } + + return; +} + +// multiply Array1D by double +Array1D scale(Array1D& x, double alpha){ + + int incr = 1; + int n = x.XSize(); + + Array1D temp = x; + FTN_NAME(dscal)(&n, &alpha, temp.GetArrayPointer(), &incr); + + return temp; + +} + +// multiply Array2D by double +Array2D scale(Array2D& x, double alpha){ + + int incr = 1; + int n = x.XSize(); + int m = x.YSize(); + int nm = n*m; + + Array2D temp = x; + FTN_NAME(dscal)(&nm, &alpha, temp.GetArrayPointer(), &incr); + + return temp; + +} + +// multiply Array1D by double, in place +void scaleinplace(Array1D& x, double alpha){ + + int n = x.Length(); + int incr = 1; + FTN_NAME(dscal)(&n, &alpha, x.GetArrayPointer(), &incr); + + return ; + +} + +// multiply Array1D by int, in place +void scaleinplace(Array1D& x, int alpha){ + + int n = x.Length(); + for ( int i=0; i& x, double alpha){ + + int incr = 1; + int n = x.XSize(); + int m = x.YSize(); + int nm = n*m; + + FTN_NAME(dscal)(&nm, &alpha, x.GetArrayPointer(), &incr); + return ; + +} + +// multiply Array2D by int, in place +void scaleinplace(Array2D& x, int alpha){ + + int incr = 1; + int n = x.XSize(); + int m = x.YSize(); + for ( int j=0; j dotmult(Array2D& A, Array2D& B){ + + int n = A.XSize(); + int m = B.XSize(); + + // Size check + CHECKEQ(n,m); + + int n1 = A.YSize(); + int m1 = B.YSize(); + + // Size check + CHECKEQ(n1,m1); + + Array2D C(n,n1,0.0); + for (int i = 0; i < n; i++){ + for (int j = 0; j < n1; j++){ + C(i,j) = A(i,j) * B(i,j); + } + } + + return C; +} + +// Returns the elementwise multiplication of two 1D Arrays +Array1D dotmult(Array1D& A, Array1D& B){ + + int n = A.XSize(); + int m = B.XSize(); + + // Size check + CHECKEQ(n,m); + + Array1D C(n,0.0); + for (int i = 0; i < n; i++){ + C(i) = A(i) * B(i); + } + + return C; +} + +// Returns the elementwise division of two 2D Arrays +Array2D dotdivide(Array2D& A, Array2D& B){ + + int n = A.XSize(); + int m = B.XSize(); + + // Size check + CHECKEQ(n,m); + + int n1 = A.YSize(); + int m1 = B.YSize(); + + // Size check + CHECKEQ(n1,m1); + + Array2D C(n,n1,0.0); + for (int i = 0; i < n; i++){ + for (int j = 0; j < n1; j++){ + C(i,j) = A(i,j) / B(i,j); + } + } + + return C; +} + +// Returns the elementwise division of two 1D Arrays +Array1D dotdivide(Array1D& A, Array1D& B){ + + int n = A.XSize(); + int m = B.XSize(); + + // Size check + CHECKEQ(n,m); + + Array1D C(n,0.0); + for (int i = 0; i < n; i++){ + C(i) = A(i) / B(i); + } + + return C; +} + +// Get norm of array 1d +double norm(Array1D& x){ + int n = x.Length(); + int incr = 1; + return dnrm2_(&n, x.GetArrayPointer(), &incr); +} + +// Returns weighted vector distance-squared +double dist_sq(Array1D& x, Array1D& y, Array1D& w) +{ + double dist=0., t; + int ndim=x.XSize();//=y.XSize();//=w.XSize(); + + for (int idim=0;idim Trans(Array2D &A){ + + int n=A.XSize(); + int m=A.YSize(); + + Array2D B(m,n,0e0); + + for (int i = 0; i < m; i++){ + for (int j = 0; j < n; j++){ + B(i,j) = A(j,i); + } + } + return B; +} + +// get dot product between two vectors +double dot(Array1D& v1, Array1D& v2){ + int n1 = v1.Length(); + int n2 = v2.Length(); + + // Size check + CHECKEQ(n1,n2); + + int incr = 1; + return FTN_NAME(ddot)(&n1, v1.GetArrayPointer(), &incr, v2.GetArrayPointer(), &incr); +} + +// get matrix vector product +Array1D dot(Array2D& A, Array1D& x){ + int n=A.XSize(); + int m=A.YSize(); + + // Size check + CHECKEQ(m, (int) x.XSize()); + + + Array1D y(n,0e0); + + char trans='n'; + double beta=0.e0; + int xinc=1; + int yinc=1; + double alpha = 1; + FTN_NAME(dgemv)(&trans, &n, &m, &alpha, A.GetArrayPointer(), &n, x.GetArrayPointer(), &xinc, &beta, y.GetArrayPointer(), &yinc ); + + return y; +} + +// get matrix vector product +Array1D dot(Array1D& x, Array2D& A){ + int n=A.XSize(); + int m=A.YSize(); + + // Size check + CHECKEQ(n, (int) x.XSize()); + + + Array1D y(n,0e0); + + char trans='n'; + double beta=0.e0; + int xinc=1; + int yinc=1; + double alpha = 1; + FTN_NAME(dgemv)(&trans, &n, &m, &alpha, A.GetArrayPointer(), &n, x.GetArrayPointer(), &xinc, &beta, y.GetArrayPointer(), &yinc ); + + return y; +} + +// get matrix matrix product +Array2D dot(Array2D& A, Array2D& B){ + + int m=A.XSize(); + int k=A.YSize(); + int n=B.YSize(); + + // Size check + CHECKEQ(k, (int) B.XSize()); + + + + Array2D C(m,n,0.e0); + + char transa='n'; + char transb='n'; + double beta = 0.e0; + double alpha = 1.e0; + + + FTN_NAME(dgemm)(&transa, &transb, &m, &n, &k, &alpha, A.GetArrayPointer(), &m, B.GetArrayPointer(), &k, &beta, C.GetArrayPointer(), &m ); + + + return C; +} + +// get matrix^T matrix product +Array2D dotT(Array2D& A, Array2D& B){ + + // transose A before doing matrix matrix operation + int n=A.XSize(); + int m=A.YSize(); + int k=B.YSize(); + + // Size check + CHECKEQ(n, (int) B.XSize()); + + Array2D C(m,k,0.e0); + + char transa='t'; + char transb='n'; + double beta=0.e0; + double alpha = 1; + + + FTN_NAME(dgemm)(&transa, &transb, &m, &k, &n, &alpha, A.GetArrayPointer(), &n, B.GetArrayPointer(), &n, &beta, C.GetArrayPointer(), &m ); + + + return C; +} + +// inverse of a real square matrix +Array2D INV(Array2D &A){ + + int m = A.XSize(); + int n = A.YSize(); + int LUinfo; + Array1D IPIV(m,0); + + Array2D B = A; + + // Get pivot indices from LU factorization + FTN_NAME(dgetrf)(&m, &n, B.GetArrayPointer(), &n, IPIV.GetArrayPointer(), &LUinfo); + + Array1D work(min(m,n),0e0); + int lwork = -1; + int info; + + // get work space first + FTN_NAME(dgetri)(&m, B.GetArrayPointer(), &m, IPIV.GetArrayPointer(), work.GetArrayPointer(), &lwork, &info); + + int nwork = work(0); + lwork = -min(-1,-nwork); // find maximum + work.Resize(lwork,0e0); + + // Get inverse + FTN_NAME(dgetri)(&m, B.GetArrayPointer(), &m, IPIV.GetArrayPointer(), work.GetArrayPointer(), &lwork, &info); + + return B; +} + +// Solving AX=H where A is real, symmetric and positive definite +Array2D AinvH(Array2D &A,Array2D &H){ + + int n = A.XSize(); + CHECKEQ(n,A.YSize()); + CHECKEQ(n,H.XSize()); + int k=H.YSize(); + int info; + + char uplo='L'; + Array2D L = A; + Array2D X = H; + + FTN_NAME(dposv)( &uplo, &n,&k, L.GetArrayPointer(), &n, X.GetArrayPointer(), &n, &info ); + + return X; +} + +// Solving Ax=b where A is real, symmetric and positive definite +Array1D Ainvb(Array2D &A,Array1D &b){ + + int n = A.XSize(); + CHECKEQ(n,A.YSize()); + CHECKEQ(n,b.XSize()); + int k=1; + int info; + + char uplo='L'; + Array2D L = A; + Array1D x = b; + + FTN_NAME(dposv)( &uplo, &n,&k, L.GetArrayPointer(), &n, x.GetArrayPointer(), &n, &info ); + + return x; +} +// Least squares solution for overdetermined system +// A must be "taller than wide" +void LSTSQ(Array2D &A, Array1D &b, Array1D &x){ + + int m = A.XSize(); + int n = A.YSize(); + + x.Resize(n,0); + + Array2D B = A; + + Array1D work(min(m,n),0e0); + int lwork = -1; + int info; + char trans = 'N'; + int nrhs = 1; + + // get work space + FTN_NAME(dgels)(&trans, &m, &n, &nrhs, B.GetArrayPointer(), &m, b.GetArrayPointer(), &m, work.GetArrayPointer(), &lwork, &info); + + int nwork = work(0); + lwork = -min(-1,-nwork); // find maximum + work.Resize(lwork,0e0); + + // now get least squares solution + FTN_NAME(dgels)(&trans, &m, &n, &nrhs, B.GetArrayPointer(), &m, b.GetArrayPointer(), &m, work.GetArrayPointer(), &lwork, &info); + + for (int i = 0; i < n; i++){ + x(i) = b(i); + } + return; +} + +// QR factorization +void QR(Array2D& B, Array2D& Q, Array2D& R ){ + + + Q = B; + + int m = Q.XSize(); + int n = Q.YSize(); + int r = m - n; + + // Q.Resize(m,m,0.0); + R.Resize(m,n,0.0); + + // resize Q + Array1D z(m,0.0); + if (r >= 1){ + for (int i = 0; i < r; i++){ + Q.insertCol(z,n+i); + } + } + int nnew = Q.YSize(); + + //*** GET R MATRIX + + Array1D tau(min(m,nnew),1); + Array1D work(min(m,nnew),0e0); + int lwork = -1; + int info; + + // get work space first + FTN_NAME(dgeqrf)(&m, &nnew, Q.GetArrayPointer(), &m, tau.GetArrayPointer(), work.GetArrayPointer(), &lwork, &info); + + int nwork = work(0); + lwork = -min(-1,-nwork); // find maximum + work.Resize(lwork,0e0); + + // now run real QR factorization + FTN_NAME(dgeqrf)(&m, &nnew, Q.GetArrayPointer(), &m, tau.GetArrayPointer(), work.GetArrayPointer(), &lwork, &info); + + // copy upper diagonal contents of A to R + for (int i = 0; i < n; i++){ + for (int j = i; j < n; j++){ + R(i,j) = Q(i,j); + } + } + + /**********************/ + int k = tau.Length(); + lwork = -1; + + FTN_NAME(dorgqr)(&m, &nnew, &k, Q.GetArrayPointer(), &m, tau.GetArrayPointer(), work.GetArrayPointer(), &lwork, &info); + + nwork = work(0); + lwork = -min(-1,-nwork); // find maximum + work.Resize(lwork,0e0); + + + FTN_NAME(dorgqr)(&m, &nnew, &k, Q.GetArrayPointer(), &m, tau.GetArrayPointer(), work.GetArrayPointer(), &lwork, &info); + + return; +} + +// SVD calculation +void SVD(Array2D& A,Array2D& U,Array1D& S,Array2D& VT){ + + int m = A.XSize(); + int n = A.YSize(); + + Array2D B = A; + + U.Resize(m,m,0.0); + S.Resize(min(m,n),0.0); + VT.Resize(n,n,0.0); + + char jobu = 'A'; + char jobvt = 'A'; + int lwork = -1; + int info; + Array1D work(min(m,n),0e0); + + // determine optimal length for work first + // DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO ) + FTN_NAME(dgesvd)(&jobu, &jobvt, &m, &n, B.GetArrayPointer(), &m, S.GetArrayPointer(), U.GetArrayPointer(), &m, VT.GetArrayPointer(), &n, work.GetArrayPointer(), &lwork, &info); + + int nwork = work(0); + lwork = -min(-1,-nwork); // find maximum + work.Resize(lwork,0e0); + + FTN_NAME(dgesvd)( &jobu, &jobvt, &m, &n, B.GetArrayPointer(), &m, S.GetArrayPointer(), U.GetArrayPointer(), &m, VT.GetArrayPointer(), &n, work.GetArrayPointer(), &lwork, &info); + + return; +} + +// Print array to screen +void printarray(Array1D& x){ + int n = x.Length(); + cout << endl; + cout << "====================================================" << endl; + cout << "n-dim double Array " << endl; + cout << "with n = " << n << endl; + cout << "----------------------------------------------------" << endl; + cout << "[( "; + int cutoff = 25; + if (n < cutoff){ + for (int i = 0; i < x.Length(); i++){ + cout << x(i) << ", "; + } + cout << ")]" << endl; + } + else{ + for (int i = 0; i < cutoff; i++){ + cout << x(i) << ", "; + } + cout << " ... "; + cout << ")]" << endl; + } +} + +// Print array to screen +void printarray(Array1D& x){ + int n = x.Length(); + cout << endl; + cout << "====================================================" << endl; + cout << "n-dim integer Array " << endl; + cout << "with n = " << n << endl; + cout << "----------------------------------------------------" << endl; + cout << "[( "; + for (int i = 0; i < x.Length(); i++){ + cout << x(i) << ", "; + } + cout << ")]" << endl; + return; +} + +// Print array to screen +void printarray(Array2D& x){ + int m = x.XSize(); + int n = x.YSize(); + cout << "====================================================" << endl; + cout << "mxn double Array " << endl; + cout << "with m = " << m << ", and n = " << n << endl; + cout << "----------------------------------------------------" << endl; + for(int ip=0; ip < m; ip++){ + cout << setw(5) << ip+1 << " | "; + for(int idim=0; idim < n; idim++){ + cout << setw(10) << x(ip,idim) << " "; + } + cout << endl; + } + return; +} + +// Print array to screen +void printarray(Array2D& x){ + int m = x.XSize(); + int n = x.YSize(); + cout << "====================================================" << endl; + cout << "mxn integer Array " << endl; + cout << "with m = " << m << ", and n = " << n << endl; + cout << "----------------------------------------------------" << endl; + for(int ip=0; ip < m; ip++){ + cout << setw(5) << ip+1 << " | "; + for(int idim=0; idim < n; idim++){ + cout << setw(10) << x(ip,idim) << " "; + } + cout << endl; + } + return; +} diff --git a/cpp/lib/array/arraytools.h b/cpp/lib/array/arraytools.h new file mode 100644 index 00000000..dcd7a8ee --- /dev/null +++ b/cpp/lib/array/arraytools.h @@ -0,0 +1,352 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file arraytools.h +/// \brief Header file for array tools +/// \todo Some functions are not optimal in terms of array access. +/// \todo Some functions should be templated and or moved to array class + +#ifndef ARRAYTOOLS_H +#define ARRAYTOOLS_H + +#include +#include "Array1D.h" +#include "Array2D.h" + +/// \brief Store a given 1d array in a 2d array with a single second dimension +template void array1Dto2D(Array1D& arr_1d,Array2D& arr); + +/// \brief Store a given 2d array with a single second dimension in a 1d array +template void array2Dto1D(Array2D& arr_2d,Array1D& arr); + +/// \brief Paste two 1d arrays of same size into a single 2d array with second dimension equal to two +template void paste(Array1D& arr1,Array1D& arr2,Array2D& arr); + +/// \brief Generates multigrid as a cartesian product of each column of grid +/// \todo Should ideally be written in a recursive manner, similar to computeMultiIndexTP() in tools/multiindex.cpp +template void generate_multigrid(Array2D& multigrid,Array2D& grid); + +/// \brief Paste two 2D arrays next to each other (horizontal stack) +void paste(Array2D& x, Array2D& y, Array2D& xy); + +/// \brief Merge 2d double arrays (vertical stack) +void merge(Array2D& x, Array2D& y, Array2D& xy); +/// \brief Merge 1d double arrays +void merge(Array1D& x, Array1D& y, Array1D& xy); +/// \brief Merge 1d int arrays +void merge(Array1D& x, Array1D& y, Array1D& xy); + +/// \brief Append array y to array x in place (double format) +void append(Array1D& x, Array1D& y); +/// \brief Append array y to array x in place (int format) +void append(Array1D& x, Array1D& y); + +/// \brief Transpose a 2d double or int array x and return the result in xt +template void transpose(Array2D &x, Array2D &xt); + +/// \brief Unfold/flatten a 2d array into a 1d array (double format) +void flatten(Array2D& arr_2, Array1D& arr_1); + +/// \brief Fold a 1d array into a 2d array (double format) +/// \note The dimension of the 1d array needs to be equal to +/// the product of the dimensions of the 2d array +void fold_1dto2d(Array1D& x1, Array2D& x2); + +/// \brief Swap i-th and j-th elements of the array arr +void swap(Array1D& arr,int i,int j); + +/// \brief Swap i-th and j-th rows of the 2d array arr +void swap(Array2D& arr,int i,int j); + +/// \brief Access element \f$j+i\times ny\f$ from 1D array 'arr_1' +double access(int nx, int ny, Array1D& arr_1, int i, int j); + +/// \brief Retrieves row 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d' +template void getRow(Array2D &arr2d, int k, Array1D &arr1d); + +/// \brief Retrieves column 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d' +template void getCol(Array2D &arr2d, int k, Array1D &arr1d); + +/// \brief Adds 'val' to the first n elements of an array pointer (double or int) +template void addVal(int n, T *arr1d, T val) ; + +/// \brief Adds 'val' to all elements of 1D array arr1d (double or int) +template void addVal(Array1D &arr1d, T val) ; + +/// \brief Adds 'val' to all elements of 2D array arr2d (double or int) +template void addVal(Array2D &arr2d, T val) ; + +/// \brief Extracts from 'vector', elements corresponding to indices 'ind' and returns them in 'subvector' (double or int) +template void subVector(Array1D &vector, Array1D &ind, Array1D &subvector); + +/// \brief Extracts from 'matrix' rows corresponding to indices 'ind' and returns them in 'submatrix' (double or int) +template void subMatrix_row(Array2D &matrix, Array1D &ind, Array2D &submatrix); + +/// \brief Extracts from 'matrix' columns corresponding to indices 'ind' and returns them in 'submatrix' (double or int) +template void subMatrix_col(Array2D &matrix, Array1D &ind, Array2D &submatrix); + +/// \brief Adds scaled row or column to all rows / columns of a matrix (double or int) +/// \note RC is a character "R" or "C" for row or column, correspondingly +template void matPvec(Array2D &matrix, const Array1D &rc, T alpha, char *RC); + +/// \brief Returns maximum value in 'vector' and its location in *indx (double or int) +template T maxVal(const Array1D& vector, int *indx) ; + +/// \brief Returns \f$ C=A\backslash B\f$ (C=Elements of A that are not in B); C is sorted in ascending order +void setdiff(Array1D &A, Array1D &B, Array1D &C) ; + +/// \brief Returns \f$ C=A\backslash B\f$ ( C=Elements of A that are not in B); C is sorted in ascending order +/// \note Assumes A is sorted and uses a faster algorithm than setdiff +/// \todo In future, this should sort A too and replace setdiff +/// \note B is sorted on output as well +void setdiff_s(Array1D &A, Array1D &B, Array1D &C) ; + +/// \brief Sorts integer array +void shell_sort (int *a, int n) ; +/// \brief Sorts integer array in ascending order +void shell_sort(Array1D& array); +/// \brief Sorts double array in ascending order +void shell_sort(Array1D& array); +/// \brief Sorts double array in ascending order according to a given column +void shell_sort_col(Array2D& array,int col,Array1D& newInd, Array1D& oldInd); +/// \brief Sorts double array in ascending order according to first column, then second column breaks the tie, and so on +void shell_sort_all(Array2D& array,Array1D& newInd, Array1D& oldInd); +/// \brief Quick-sort with 3-way partitioning of array between indices l and r +void quicksort3(Array1D& arr, int l, int r); +/// \brief Quick-sort with 3-way partitioning of 2d array between indices l and r, according to column col +void quicksort3(Array2D& arr,int left, int right,int col); +/// \brief Quick-sort with 3-way partitioning of 2d array between indices l and r, and sorting is done comparing rows (by first element, then by second, etc...) +void quicksort3(Array2D& arr,int left, int right); + +/// \brief Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order. It also +/// returns the original locations of these entries in 1D arrays 'iA' and 'iB', respectively +/// \note Currently, duplicated entries in either 'A' and 'B' will be duplicated in 'C' +void intersect(Array1D &A, Array1D &B, Array1D &C, Array1D &iA,Array1D &iB) ; +/// \brief Find common entries in 1D arrays 'A' and 'B' and return them in 'C', sorted in ascending order +/// \note Currently, duplicated entries in either 'A' and 'B' will be duplicated in 'C' +void intersect(Array1D &A, Array1D &B, Array1D &C) ; + +/// \brief Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" ), +/// larger or equal ( type="ge" ), smaller ( type="lt" ), smaller or equal ( type="le" ) than lmbda +template void find(Array1D &theta, T lmbda, string type, Array1D &indx) ; + +/// \brief Returns \f$y=\alpha Ax\f$, where 'A' is a \f$\left[n\times m\right]\f$ 2D array, 'x' is +/// 1D array of size \f$m\f$ and 'alpha' is a scalar. The 1D array 'y' has \f$n\f$ elements +void prodAlphaMatVec (Array2D& A, Array1D& x, double alpha, Array1D& y) ; +/// \brief Returns \f$y=\alpha A^Tx\f$, where 'A' is a \f$\left[m\times n\right]\f$ 2D array, 'x' is +/// 1D array of size \f$m\f$ and 'alpha' is a scalar. The 1D array 'y' has \f$n\f$ elements +void prodAlphaMatTVec(Array2D& A, Array1D& x, double alpha, Array1D& y) ; +/// \brief Returns \f$C=\alpha AB\f$, where 'A' and 'B' are \f$\left[m\times n\right]\f$ 2D arrays +/// and 'alpha' is a scalar. The 2D array 'C' has \f$m\times m\f$ elements +void prodAlphaMatMat(Array2D& A, Array2D& B, double alpha, Array2D& C); +/// \brief Returns \f$C=\alpha A^TB\f$, where 'A' and 'B' are \f$\left[m\times n\right]\f$ 2D arrays +/// and 'alpha' is a scalar. The 2D array 'C' has \f$m\times m\f$ elements +void prodAlphaMatTMat(Array2D& A, Array2D& B, double alpha, Array2D& C) ; +/// \brief Implements \f$x_i=x_i+\alpha y_i^ip\f$, where 'x' and 'y' are 1D arrays with \f$n\f$ elements +void addVecAlphaVecPow(Array1D& x, double alpha, Array1D& y, int ip) ; +/// \brief Returns \f$a^T B c\f$ +double prod_vecTmatvec(Array1D& a, Array2D& B, Array1D& c); +/// \brief Returns \f$A^T A\f$, where 'A' is a \f$\left[n\times k\right]\f$ 2D array +Array2D MatTMat(Array2D& A) ; + + +/// \brief Deletes row 'irow' from 2D array 'A' +/// \todo This should move to Array2D class +template void delRow(Array2D& A, int irow) ; + +/// \brief Deletes column 'icol' from 2D array 'A' +/// \todo This should move to Array2D class +template void delCol(Array2D &A, int icol) ; + +/// \brief Deletes element 'icol' from 1D array 'A' +/// \todo This should move to Array1D class +template void delCol(Array1D &x, int icol) ; + +/// \brief Padds 2D array 'A' with the row 'x' +/// \note the number of elements in 'x' should be the same as the number of columns of 'A' +void paddMatRow(Array2D& A, Array1D& x) ; +/// \brief Padds 2D array 'A' with the column 'x' +/// \note the number of elements in 'x' should be the same as the number of rows in 'A' +void paddMatCol(Array2D& A, Array1D& x) ; +/// \brief Padds 2D array 'A' with the row 'x' +/// \note the number of elements in 'x' should be the same as the number of columns of 'A' +void paddMatRow(Array2D& A, Array1D& x) ; +/// \brief Padds 2D array 'A' with the column 'x' +/// \note the number of elements in 'x' should be the same as the number of rows in 'A' +void paddMatCol(Array2D& A, Array1D& x) ; +/// \brief Padds square 2D array 'A' \f$\left[n\times n\right]\f$ with the elements of 'x' and 'scal' as follows: +/// \f$A_{n+1,i}=A_{i,n+1}=x_i\f$ and \f$A_{n+1,n+1}=scal\f$ +void paddMatColScal(Array2D& A, Array1D& x, double scal) ; + +/// \brief Checks if two 1d int arrays are equal +bool is_equal(Array1D& a, Array1D& b); +/// \brief Checks if two 1d double arrays are equal +bool is_equal(Array1D& a, Array1D& b); +/// \brief Checks if one 1d int array is less than another (by first element, then by second, etc...) +bool is_less(Array1D& a, Array1D& b); +/// \brief Checks if one 1d double array is less than another (by first element, then by second, etc...) +bool is_less(Array1D& a, Array1D& b); + +/// \brief Checks if vec matches with any of the rows of array +/// Returns the row number, or -1 if vec is not equal to any of the rows of array +int vecIsInArray(Array1D& vec, Array2D& array); + +/// \brief Select the k-th smallest element of an array arr +double select_kth(int k, Array1D& arr); + +/// \brief Log-determinant of a real symmetric positive-definite matrix +/// \todo Check and catch the symmetric and positiv-definite conditions. +double logdeterm(Array2D& mat); + +/// \brief Trace of a matrix +double trace(Array2D& mat); + +/// \brief Evaluates the natural logarithm of a multivariate normal distribution +double evalLogMVN(Array1D& x,Array1D& mu,Array2D& Sigma); + +/// \brief Returns a diagonal matrix with a given diagonal +Array2D diag(Array1D& diagonal_array); +/********************************************************** +NEW ROUTINES - Kenny +***********************************************************/ + +/// \brief Returns a copy of 1D array +Array1D copy(Array1D&); + +/// \brief Return a copy of 2D Array +Array2D copy(Array2D&); + +/// \brief Deletes matrix columns or rows. Index specifies which column or row and dim = 1 deletes column, dim = 0 deletes the row +Array2D mtxdel(Array2D&, int index, int dim); + +/// \brief Add two 1D Arrays and returns sum (must be of the same shape) +Array1D add(Array1D&, Array1D&); + +/// \brief Add two 2D Arrays and returns sum (must be of same shape) +Array2D add(Array2D&, Array2D&); + +/// \brief Add two 2D Arrays in place. Summation is returned as x. +void addinplace(Array2D& x, Array2D& y); + +/// \brief Add two 1D Arrays in place. Summation is returned as x. +void addinplace(Array1D& x, Array1D& y); + +/// \brief Returns subtraction of two 1D Arrays (must be of the same shape) +Array1D subtract(Array1D&, Array1D&); + +/// \brief Returns subtraction of two 2D Arrays (must be of the same shape) +Array2D subtract(Array2D&, Array2D&); + +/// \brief Subtract two 2D Arrays in place. Difference is returned as x. +void subtractinplace(Array2D& x, Array2D& y); + +/// \brief Subtract two 1D Arrays in place. Difference is returned as x. +void subtractinplace(Array1D& x, Array1D& y); + +/// \brief Returns 1D Arrays scaled by a double +Array1D scale(Array1D&, double); + +/// \brief Returns 2D Array scaled by a double +Array2D scale(Array2D&, double); + +/// \brief Multiply Array1D by double in place +void scaleinplace(Array1D&, double); + +/// \brief Multiply Array1D by int in place +void scaleinplace(Array1D&, int); + +/// \brief Multiply Array2D by double in place +void scaleinplace(Array2D&, double); + +/// \brief Multiply Array2D by int in place +void scaleinplace(Array2D&, int); + +/// \brief Returns the elementwise multiplication of two 2D Arrays +Array2D dotmult(Array2D&A,Array2D&B ); + +/// \brief Returns the elementwise multiplication of two 1D Arrays +Array1D dotmult(Array1D&A,Array1D&B ); + +/// \brief Returns the elementwise division of two 2D Arrays +Array2D dotdivide(Array2D&A,Array2D&B ); + +/// \brief Returns the elementwise division of two 1D Arrays +Array1D dotdivide(Array1D&A,Array1D&B ); + +/// \brief Returns norm of 1D Array (Euclidean) +double norm(Array1D&); + +/// \brief Weighted vector distance-squared +double dist_sq(Array1D& x, Array1D& y, Array1D& w); + +/// \brief Returns the transpose of a 2D Array +Array2D Trans(Array2D&); + +/// \brief Returns the dot product of two 1D Arrays (must be of the same length) +double dot(Array1D&, Array1D&); + +/// \brief Returns the matrix vector product +Array1D dot(Array2D&, Array1D&); + +/// \brief Returns the matrix matrix product +Array2D dot(Array2D&, Array2D&); + +/// \brief Returns the matrix matrix^T product +Array2D dotT(Array2D&, Array2D&); + +/// \brief Returns the inverse of a square 2D Array +Array2D INV(Array2D &A); + +/// \brief Solves linear system AX=H, i.e. returns A^(-1)*H, where A is real, symmetric and positive definite +Array2D AinvH(Array2D &A,Array2D &H); + +/// \brief Solves linear system Ax=b, i.e. return A^(-1)*b where A is real, symmetric and positive definite +Array1D Ainvb(Array2D &A,Array1D &b); + +/// \brief Least squares solution for overdetermined system. Note that A must be "taller than wide". Solution is returned in x. +void LSTSQ(Array2D &A, Array1D &b, Array1D &x); + +/// \brief Computes the QR factorization of a 2D Array (need not be square) +void QR(Array2D&B,Array2D&Q,Array2D&R); + +/// \brief Computes the SVD calculation of a 2D Array (need not be square) +void SVD(Array2D&A,Array2D&U,Array1D&S,Array2D&VT); + +/// \brief Prints 1D double Array to screen (alternative to for loop using cout) +void printarray(Array1D&); + +/// \brief Prints 1D int Array to screen (alternative to for loop using cout) +void printarray(Array1D&); + +/// \brief Prints 2D double Array to screen (alternative to for loop using cout) +void printarray(Array2D&); + +/// \brief Prints 2D int Array to screen (alternative to for loop using cout) +void printarray(Array2D&); + + +//--------------------------------------------------------------------------------------- +#endif // ARRAYTOOLS_H diff --git a/cpp/lib/bcs/CMakeLists.txt b/cpp/lib/bcs/CMakeLists.txt new file mode 100644 index 00000000..7991f687 --- /dev/null +++ b/cpp/lib/bcs/CMakeLists.txt @@ -0,0 +1,25 @@ +project(UQTk) + +SET(bcs_HEADERS + bcs.h + ) + +add_library(uqtkbcs bcs.cpp) + +include_directories (../include) +include_directories (../array) +include_directories (../tools) +include_directories (../quad) + +include_directories (../../../dep/slatec) +include_directories (../../../dep/lapack) +include_directories (../../../dep/dsfmt) +include_directories (../../../dep/figtree) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtkbcs DESTINATION lib) + +# Install the header files +INSTALL(FILES ${bcs_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/bcs/bcs.cpp b/cpp/lib/bcs/bcs.cpp new file mode 100644 index 00000000..d1198ebf --- /dev/null +++ b/cpp/lib/bcs/bcs.cpp @@ -0,0 +1,869 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file bcs.cpp +/// \brief Implemenations of Bayesian compressive sensing algorithm. + +#include "stdlib.h" +#include "stdio.h" +#include "math.h" +#include "assert.h" +#include +#include + +#include "bcs.h" +#include "tools.h" +#include "ftndefs.h" +#include "deplapack.h" +#include "arrayio.h" +#include "arraytools.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// ____ ____ ____ +// | __ ) / ___| / ___| +// | _ \ | | \___ \ +// | |_) | | |___ ___) | +// |____/ \____| |____/ +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +/// \brief The implementation of the Bayesian Compressive Sensing algorithm using Laplace Priors +/// \note This function has been written relying on the algorithm and MATLAB code presented in +/// http://ivpl.eecs.northwestern.edu/research/projects/bayesian-compressive-sensing-using-laplace-priors +/// and references therein +/// \todo The array manipulations are not optimized - perhaps they need to be reconsidered using, +/// say, fortran matrix-vector manipulation routines + +// Parameters: +// % sigma2: initial noise variance (default : std(t)^2/1e6) +// % eta: threshold for stopping the algorithm (default : 1e-8) +// % lambda_init : To set lambda equal to a fixed nonegative value. +// % if lambda_init = [], lambda will be computed automatically, which is the suggested method. +// % lambda_init = 0 corresponds to the BCS algorithm in [2], see [1] for technical details. +// % +// % Inputs for Adaptive CS (this part is left unchanged from the BCS code, see [2]) +// % adaptive: generate basis for adaptive CS (default: 0) +// % optimal: use the rigorous implementation of adaptive CS (default: 1) +// % scale: diagonal loading parameter (default: 0.1) +// % Outputs: +// % weights: sparse weights +// % used: the positions of sparse weights +// % sigma2: re-estimated noise variance +// % errbars: one standard deviation around the sparse weights +// % basis: if adaptive==1, then basis = the next projection vector, see [2] +// % alpha: sparse hyperparameters (1/gamma), see [1] +// % lambda: parameter controlling the sparsity , see [1] + +void BCS(Array2D &PHI, Array1D &y, double &sigma2, + double eta, Array1D &lambda_init, + int adaptive, int optimal, double scale, int verbose, + Array1D &weights, Array1D &used, + Array1D &errbars, Array1D &basis, + Array1D &alpha, double &lambda) +{ + int n = (int) PHI.XSize() ; + int m = (int) PHI.YSize() ; + + + /* find initial alpha */ + Array2D PHIT ; + + transpose(PHI,PHIT); + + Array1D PHIy ; + prodAlphaMatVec(PHIT, y, 1.0, PHIy); + + Array1D PHI2(m,0.0); + for (int j = 0; j ratio(m,0.0); + for (int j = 0; jindex(1,indx); + alpha.Resize(1) ; + alpha(0)= PHI2(index(0))/(maxr-sigma2); + //printf("alpha=%e\n",alpha(0)); + + /* Compute initial mu, Sig, S, Q */ + Array2D phi(n,1,0.0); + for (int i = 0; i Sig(1,1,1.0/Hessian) ; + double dtmp1=Sig(0,0)*PHIy(index(0))/sigma2; + Array1D mu(1,dtmp1); + Array1D left(m,0.0),phitmp(n); + for ( int i=0; i S(m), Q(m); + for (int j=0; j selected; + selected=index; + Array1D deleted ; + Array1D ML(MAX_IT,0) ; + + int count ; + for ( count=0; count s,q; + s=S; q=Q; + for ( int i = 0; i< (int) index.XSize(); i++) + { + s(index(i)) = alpha(i)*S(index(i))/(alpha(i)-S(index(i))); + q(index(i)) = alpha(i)*Q(index(i))/(alpha(i)-S(index(i))); + + } + + if (lambda_init.XSize() == 0) + { + double suma=0.0; + for ( int i = 0; i< (int) alpha.XSize(); i++) suma += 1.0/alpha(i); + lambda = 2*( index.XSize() - 1 ) / suma; + } + else + lambda = lambda_init(0); + + Array1D A(m,0.0), B(m,0.0), C(m,0.0); + Array1D theta(m,0.0), discriminant(m,0.0), nextAlphas(m,0.0) ; + for ( int i=0; i ml(m,-1.0e20); + Array1D ig0 ; + + find(theta, lambda, string("gt"), ig0) ; + + /* indices for reestimation */ + Array1D ire,foo,which ; + intersect(ig0,index,ire,foo,which); + + if (ire.XSize() > 0) + { + Array1D Alpha(ire.XSize(),0.0); + Array1D delta(ire.XSize(),0.0); + for ( int i=0; i< (int) ire.XSize(); i++ ) + { + Alpha(i) = nextAlphas(ire(i)); + delta(i) = (alpha(which(i))-Alpha(i))/(Alpha(i)*alpha(which(i))); + double As=Alpha(i) / (Alpha(i) + s(ire(i))); + double as=alpha(which(i)) / (alpha(which(i)) + s(ire(i))); + if (As<=0.0) As=1e-20; + if (as<=0.0) as=1e-20; + ml(ire(i)) = pow(q(ire(i)),2)/ (Alpha(i) + s(ire(i))) + + log(As) - lambda/ Alpha(i) + - pow(q(ire(i)),2)/ (alpha(which(i)) + s(ire(i))) + - log(as) + + lambda/alpha(which(i)); + } + } + + /* indices for adding */ + Array1D iad ; + + setdiff(ig0, ire, iad) ; + + if ( iad.XSize() > 0 ) + { + Array1D Alpha(iad.XSize(),0.0); + for ( int i=0; i< (int) iad.XSize(); i++ ) + { + Alpha(i) = nextAlphas(iad(i)); + ml(iad(i)) = log(Alpha(i) / (Alpha(i) + s(iad(i))) ) + +pow(q(iad(i)),2) / (Alpha(i) + s(iad(i))) - lambda/Alpha(i); + } + intersect(deleted, iad, which); + + for ( int i=0; i< (int) which.XSize(); i++ ) + ml(which(i)) = -1.0e20; + } + + Array1D indxM(m,0); for ( int i=0; i is0; + + setdiff_s(indxM,ig0,is0); + + /* indices for deleting */ + Array1D ide; + intersect(is0,index,ide,foo,which); + + if ( ide.XSize() > 0 ) + { + if ( index.XSize() == 1 ) + for ( int i=0; i< (int) ide.XSize(); i++ ) + ml(ide(i)) = -1.0e200; + else + for ( int i=0; i< (int) ide.XSize(); i++ ) + ml(ide(i)) = -pow(q(ide(i)),2) / (alpha(which(i)) + s(ide(i))) + -log( alpha(which(i)) /(alpha(which(i)) + s(ide(i)))) + +lambda/alpha(which(i)); + } + + int idx ; + ML(count) = maxVal(ml,&idx); + + + /* check convergence */ + if (count > 1) + if ( fabs(ML(count)-ML(count-1)) < fabs(ML(count)-ML(0))*eta ) + break; + + /* + update alphas + Choose the basis which results in the largest increase in the + likelihood + */ + + find(index,idx,string("eq"),which); + + + if ( theta(idx) > lambda ) + { + if ( which.XSize() > 0 ) + { + /* reestimate a basis */ + double Alpha = nextAlphas(idx); + double Sigii = Sig(which(0),which(0)); + double mui = mu(which(0)); + Array1D Sigi(Sig.XSize(),0.0) ; + for ( int i=0; i<(int) Sig.XSize(); i++ ) Sigi(i) = Sig(i,which(0)); + double delta = Alpha-alpha(which(0)); + double ki = delta/(1+Sigii*delta); + for ( int i = 0; i < (int) mu.XSize() ; i++ ) + mu(i) = mu(i)-ki*mui*Sigi(i); + for ( int j = 0; j < (int) Sig.YSize() ; j++ ) + for ( int i = 0; i < (int) Sig.XSize() ; i++ ) + Sig(i,j) = Sig(i,j)-ki*Sigi(i)*Sigi(j); + Array1D tmp1, comm; + + prodAlphaMatVec (phi,Sigi,1.0, tmp1); + prodAlphaMatTVec(PHI,tmp1,1.0/sigma2,comm); + addVecAlphaVecPow(S,ki, comm,2); + addVecAlphaVecPow(Q,ki*mui,comm,1); + alpha(which(0)) = Alpha; + + if ( verbose > 0 ) + printf("Reestimate %d..\n",idx); + } + else + { + /* add a basis */ + double Alpha = nextAlphas(idx); + Array1D phii(PHI.XSize(),0.0); + for ( int i = 0; i< (int) phii.XSize(); i++ ) phii(i) = PHI(i,idx); + double Sigii = 1.0/(Alpha+S(idx)); + double mui = Sigii*Q(idx); + Array1D comm1,tmp1; + + prodAlphaMatTVec(phi,phii,1.0/sigma2,tmp1); + + prodAlphaMatVec (Sig,tmp1,1.0, comm1); + Array1D ei; + ei=phii; + + + prodAlphaMatVec(phi,comm1,-1.0,tmp1);// !!! slowdown later + + addVecAlphaVecPow(ei,1.0,tmp1,1); + + Array1D off(comm1.XSize(),0.0); + addVecAlphaVecPow(off,-Sigii,comm1,1); + + for ( int j = 0; j< (int) Sig.YSize(); j++ ) + for ( int i = 0; i< (int) Sig.XSize(); i++ ) + Sig(i,j) += Sigii*comm1(i)*comm1(j) ; + paddMatColScal(Sig,off,Sigii) ; + + for ( int i = 0; i< (int) mu.XSize(); i++ ) mu(i) -= mui*comm1(i); + mu.PushBack(mui); + + Array1D comm2(m,0.0); + prodAlphaMatTVec(PHI,ei,1.0/sigma2,comm2);// !!!early slowdown here + + + addVecAlphaVecPow(S,-Sigii,comm2,2); + + addVecAlphaVecPow(Q,-mui,comm2,1); + + index.PushBack(idx); + alpha.PushBack(Alpha); + + phi.insertCol(phii,phi.YSize()); + + if ( verbose > 0 ) + printf("Add %d.. \n",idx) ; + } + } + else + { + if ( ( which.XSize() > 0 ) && ( index.XSize()> 1 ) ) + { + /* delete a basis */ + deleted.PushBack(idx); + double Sigii = Sig(which(0),which(0)); + double mui = mu(which(0)); + Array1D Sigi ; + getCol(Sig,which(0),Sigi) ; + for ( int j = 0; j< (int) Sig.YSize(); j++ ) + for ( int i = 0; i< (int) Sig.XSize(); i++ ) + Sig(i,j) -= Sigi(i)*Sigi(j)/Sigii ; + + delCol(Sig,which(0)); + delRow(Sig,which(0)); + addVecAlphaVecPow(mu,-mui/Sigii,Sigi,1); + delCol(mu,which(0)); + + Array1D comm,tmp1 ; + prodAlphaMatVec(phi,Sigi,1.0/sigma2,tmp1); + prodAlphaMatTVec(PHI,tmp1,1.0,comm); + addVecAlphaVecPow(S,1.0/Sigii,comm,2); + addVecAlphaVecPow(Q,mui/Sigii,comm,1); + + delCol(index,which(0)); + delCol(alpha,which(0)); + delCol(phi, which(0)); + + if ( verbose > 0 ) + printf("Delete %d.. \n",idx); + } + else if ((which.XSize() > 0 ) && (index.XSize() == 1)) + { + printf("Something is wrong, trying to delete the only coefficient\n"); + printf("that has been added.\n"); + break; + } + } + + selected.PushBack(idx); + } // End of iteration loop + + weights = mu ; + used = index ; + + /* re-estimated sigma2 */ + double sum1=0.0, sum3 = 0.0; + for ( int i = 0; i<(int) y.XSize(); i++) + { + double sum2 = 0.0 ; + for ( int j = 0; j<(int) phi.YSize(); j++) + sum2 += phi(i,j)*mu(j) ; + sum1 += pow(y(i)-sum2,2) ; + } + for ( int i = 0; i<(int) alpha.XSize(); i++) + sum3 += alpha(i)*Sig(i,i) ; + sigma2 = sum1/((double) (n-index.XSize())+sum3) ; + + errbars.Resize(Sig.XSize()) ; + for ( int i = 0; i<(int) errbars.XSize(); i++) errbars(i) = sqrt(Sig(i,i)); + + /* generate a basis for adaptive CS? */ + if ( adaptive == 1 ) + { + if ( optimal == 1 ) + { + int nSig = Sig.XSize() ; + double VL,VU ; + int IL=nSig,IU=nSig; + double ABSTOL = -1.0 ; + int nEigVals, info, ifail ; + double eigVal ; + basis.Resize(nSig) ; + int lWrk = 8*nSig ; + double *dwrk = new double[lWrk] ; + int *iwrk = new int [lWrk] ; + FTN_NAME(dsyevx)((char *)"V", (char *)"I", (char *)"L", &nSig, Sig.GetArrayPointer(), &nSig, + &VL, &VU, &IL, &IU, &ABSTOL, + &nEigVals, &eigVal, basis.GetArrayPointer(), + &nSig, dwrk, &lWrk, iwrk, &ifail, &info ) ; + delete [] dwrk ; + delete [] iwrk ; + if ( info != 0 ) + printf("WARNING : DSYEVX failed with info=%d\n",info) ; + } + else + { + Array2D tmp1; + prodAlphaMatTMat(phi,phi,1.0/sigma2,tmp1); + double tmp1m = 0.0 ; + for ( int i = 0; i < (int) tmp1.XSize() ; i++ ) + tmp1m += tmp1(i,i); + tmp1m /= ( (double) tmp1.XSize() ) ; + Array2D Sig_inv ; + Sig_inv = tmp1 ; + for ( int i = 0 ; i < (int) Sig_inv.XSize() ; i++ ) + Sig_inv(i,i) += scale*tmp1m; + + int nSig = Sig_inv.XSize() ; + double VL,VU ; + int IL=1,IU=1; + double ABSTOL = -1.0 ; + int nEigVals, info, ifail ; + double eigVal ; + basis.Resize(nSig) ; + int lWrk = 8*nSig ; + double *dwrk = new double[lWrk] ; + int *iwrk = new int [lWrk] ; + FTN_NAME(dsyevx)((char *)"V", (char *)"I", (char *)"L", &nSig, Sig_inv.GetArrayPointer(), &nSig, + &VL, &VU, &IL, &IU, &ABSTOL, + &nEigVals, &eigVal, basis.GetArrayPointer(), + &nSig, dwrk, &lWrk, iwrk, &ifail, &info ) ; + delete [] dwrk ; + delete [] iwrk ; + if ( info != 0 ) + printf("WARNING : DSYEVX failed with info=%d\n",info) ; + } + + } + printf("BCS algorithm converged, # iterations : %d \n",count); + return ; + +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// __ __ ____ ____ ____ +// \ \ / / | __ ) / ___| / ___| +// \ \ /\ / / | _ \ | | \___ \ +// \ V V / | |_) | | |___ ___) | +// \_/\_/ |____/ \____| |____/ +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/// \brief The implementation of the Bayesian Compressive Sensing algorithm using Laplace Priors +/// \note This function has been written relying on the algorithm and MATLAB code presented in +/// http://ivpl.eecs.northwestern.edu/research/projects/bayesian-compressive-sensing-using-laplace-priors +/// and references therein +/// \todo The array manipulations are not optimized - perhaps they need to be reconsidered using, +/// say, fortran matrix-vector manipulation routines + +// Parameters: +// % sigma2: initial noise variance (default : std(t)^2/1e2) +// % eta: threshold for stopping the algorithm (default : 1e-8) +// % lambda_init : An array of regularization weights. +// % +// % Inputs for Adaptive CS (this part is left unchanged from the BCS code, see [2]) +// % adaptive: generate basis for adpative CS? (default: 0) +// % optimal: use the rigorous implementation of adaptive CS? (default: 1) +// % scale: diagonal loading parameter (default: 0.1) +// % Outputs: +// % weights: sparse weights +// % used: the positions of sparse weights +// % sigma2: re-estimated noise variance +// % errbars: one standard deviation around the sparse weights +// % basis: if adaptive==1, then basis = the next projection vector, see [2] +// % alpha: sparse hyperparameters (1/gamma), see [1] +// % lambda: parameter controlling the sparsity , see [1] + +void WBCS(Array2D &PHI, Array1D &y, double &sigma2, + double eta, Array1D &lambda_init, + int adaptive, int optimal, double scale, int verbose, + Array1D &weights, Array1D &used, + Array1D &errbars, Array1D &basis, + Array1D &alpha, double &lambda, Array2D &Sig) +{ + // Get the measurement matrix size + int n = (int) PHI.XSize() ; + int m = (int) PHI.YSize() ; + + // Set initial alpha + Array2D PHIT ; + transpose(PHI,PHIT); + Array1D PHIy ; + prodAlphaMatVec(PHIT, y, 1.0, PHIy); + Array1D PHI2(m,0.0); + for (int j = 0; j ratio(m,0.0); + for (int j = 0; jindex(1,indx); + alpha.Resize(1) ; + alpha(0)= PHI2(index(0))/(maxr-sigma2); + + // Compute initial mu, Sig, S, Q + Array2D phi(n,1,0.0); + for (int i = 0; i Sig(1,1,1.0/Hessian) ; + Sig.Resize(1,1,1./Hessian); + double dtmp1=Sig(0,0)*PHIy(index(0))/sigma2; + Array1D mu(1,dtmp1); + Array1D left(m,0.0),phitmp(n); + for ( int i=0; i S(m), Q(m); + for (int j=0; j selected; + selected=index; + Array1D deleted ; + Array1D ML(MAX_IT,0) ; + + // Go through the iterations + int count ; + for ( count=0; count s,q; + s=S; q=Q; + for ( int i = 0; i< (int) index.XSize(); i++){ + s(index(i)) = alpha(i)*S(index(i))/(alpha(i)-S(index(i))); + q(index(i)) = alpha(i)*Q(index(i))/(alpha(i)-S(index(i))); + } + + Array1D A(m,0.0), B(m,0.0), C(m,0.0); + Array1D theta(m,0.0), discriminant(m,0.0), nextAlphas(m,0.0) , theta_lambda(m,0.0); + for ( int i=0; i ml(m,-1.0e20); + Array1D ig0 ; + + find(theta_lambda, 0.0, string("gt"), ig0) ; + if (ig0.XSize()==0) + ig0.PushBack(0.0); + + + // Indices for reestimation + Array1D ire,foo,which ; + intersect(ig0,index,ire,foo,which); + + if (ire.XSize() > 0){ + Array1D Alpha(ire.XSize(),0.0); + Array1D delta(ire.XSize(),0.0); + for ( int i=0; i< (int) ire.XSize(); i++ ){ + Alpha(i) = nextAlphas(ire(i)); + delta(i) = (alpha(which(i))-Alpha(i))/(Alpha(i)*alpha(which(i))); + double As=Alpha(i) / (Alpha(i) + s(ire(i))); + double as=alpha(which(i)) / (alpha(which(i)) + s(ire(i))); + if (As<=0.0) As=1e-20; + if (as<=0.0) as=1e-20; + ml(ire(i)) = pow(q(ire(i)),2)/ (Alpha(i) + s(ire(i))) + + log(As) - lambda_init(ire(i))/ Alpha(i) + - pow(q(ire(i)),2)/ (alpha(which(i)) + s(ire(i))) + - log(as) + + lambda_init(ire(i))/alpha(which(i)); + } + } + + // Indices for adding + Array1D iad ; + + setdiff(ig0, ire, iad) ; + + if ( iad.XSize() > 0 ){ + Array1D Alpha(iad.XSize(),0.0); + for ( int i=0; i< (int) iad.XSize(); i++ ){ + Alpha(i) = nextAlphas(iad(i)); + ml(iad(i)) = log(Alpha(i) / (Alpha(i) + s(iad(i))) ) + + pow(q(iad(i)),2) / (Alpha(i) + s(iad(i))) + - lambda_init(iad(i))/Alpha(i); + } + intersect(deleted, iad, which); + for ( int i=0; i< (int) which.XSize(); i++ ) + ml(which(i)) = -1.0e20; + } + + Array1D indxM(m,0); for ( int i=0; i is0; + + setdiff_s(indxM,ig0,is0); + + + // Indices for deleting + Array1D ide; + intersect(is0,index,ide,foo,which); + + if ( ide.XSize() > 0 ){ + if ( index.XSize() == 1 ) + for ( int i=0; i< (int) ide.XSize(); i++ ) + ml(ide(i)) = -1.0e200; + else + for ( int i=0; i< (int) ide.XSize(); i++ ) + ml(ide(i)) = -pow(q(ide(i)),2) / (alpha(which(i)) + s(ide(i))) + -log( alpha(which(i)) /(alpha(which(i)) + s(ide(i)))) + +lambda_init(ide(i))/alpha(which(i)); + } + + int idx ; + ML(count) = maxVal(ml,&idx); + + + // Check convergence + if (count > 1) + if ( fabs(ML(count)-ML(count-1)) < fabs(ML(count)-ML(0))*eta ) + break; + + // Update alphas + // Choose the basis which results in the largest increase in the likelihood + find(index,idx,string("eq"),which); + + if ( theta(idx) > lambda_init(idx) ){ + + if ( which.XSize() > 0 ){ + /* reestimate a basis */ + double Alpha = nextAlphas(idx); + double Sigii = Sig(which(0),which(0)); + double mui = mu(which(0)); + Array1D Sigi(Sig.XSize(),0.0) ; + for ( int i=0; i<(int) Sig.XSize(); i++ ) Sigi(i) = Sig(i,which(0)); + double delta = Alpha-alpha(which(0)); + double ki = delta/(1+Sigii*delta); + for ( int i = 0; i < (int) mu.XSize() ; i++ ) + mu(i) = mu(i)-ki*mui*Sigi(i); + for ( int j = 0; j < (int) Sig.YSize() ; j++ ) + for ( int i = 0; i < (int) Sig.XSize() ; i++ ) + Sig(i,j) = Sig(i,j)-ki*Sigi(i)*Sigi(j); + + Array1D tmp1, comm; + + prodAlphaMatVec (phi,Sigi,1.0, tmp1); + prodAlphaMatTVec(PHI,tmp1,1.0/sigma2,comm); + addVecAlphaVecPow(S,ki, comm,2); + addVecAlphaVecPow(Q,ki*mui,comm,1); + alpha(which(0)) = Alpha; + + if ( verbose > 0 ) + printf("Reestimate %d..\n",idx); + } + + else { + /* add a basis */ + double Alpha = nextAlphas(idx); + Array1D phii(PHI.XSize(),0.0); + for ( int i = 0; i< (int) phii.XSize(); i++ ) phii(i) = PHI(i,idx); + double Sigii = 1.0/(Alpha+S(idx)); + double mui = Sigii*Q(idx); + Array1D comm1,tmp1; + + prodAlphaMatTVec(phi,phii,1.0/sigma2,tmp1); + prodAlphaMatVec (Sig,tmp1,1.0, comm1); + Array1D ei; + ei=phii; + + prodAlphaMatVec(phi,comm1,-1.0,tmp1); + addVecAlphaVecPow(ei,1.0,tmp1,1); + + Array1D off(comm1.XSize(),0.0); + addVecAlphaVecPow(off,-Sigii,comm1,1); + + for ( int j = 0; j< (int) Sig.YSize(); j++ ) + for ( int i = 0; i< (int) Sig.XSize(); i++ ) + Sig(i,j) += Sigii*comm1(i)*comm1(j) ; + + paddMatColScal(Sig,off,Sigii) ; + + for ( int i = 0; i< (int) mu.XSize(); i++ ) mu(i) -= mui*comm1(i); + mu.PushBack(mui); + + Array1D comm2(m,0.0); + prodAlphaMatTVec(PHI,ei,1.0/sigma2,comm2); + + addVecAlphaVecPow(S,-Sigii,comm2,2); + addVecAlphaVecPow(Q,-mui,comm2,1); + + index.PushBack(idx); + alpha.PushBack(Alpha); + + phi.insertCol(phii,phi.YSize()); + + if ( verbose > 0 ) + printf("Add %d.. \n",idx) ; + } + } + + else{ + + if ( ( which.XSize() > 0 ) && ( index.XSize()> 1 ) ){ + /* delete a basis */ + deleted.PushBack(idx); + double Sigii = Sig(which(0),which(0)); + double mui = mu(which(0)); + Array1D Sigi ; + getCol(Sig,which(0),Sigi) ; + for ( int j = 0; j< (int) Sig.YSize(); j++ ) + for ( int i = 0; i< (int) Sig.XSize(); i++ ) + Sig(i,j) -= Sigi(i)*Sigi(j)/Sigii ; + + delCol(Sig,which(0)); + delRow(Sig,which(0)); + addVecAlphaVecPow(mu,-mui/Sigii,Sigi,1); + delCol(mu,which(0)); + + Array1D comm,tmp1 ; + prodAlphaMatVec(phi,Sigi,1.0/sigma2,tmp1); + prodAlphaMatTVec(PHI,tmp1,1.0,comm); + addVecAlphaVecPow(S,1.0/Sigii,comm,2); + addVecAlphaVecPow(Q,mui/Sigii,comm,1); + + delCol(index,which(0)); + delCol(alpha,which(0)); + delCol(phi, which(0)); + + if ( verbose > 0 ) + printf("Delete %d.. \n",idx); + } + + else if ((which.XSize() > 0 ) && (index.XSize() == 1)){ + printf("Something is wrong, trying to delete the only coefficient\n"); + printf("that has been added.\n"); + break; + } + } + + selected.PushBack(idx); + } // End of iteration loop + + weights = mu ; + used = index ; + + // Re-estimated sigma2 + double sum1=0.0, sum3 = 0.0; + for ( int i = 0; i<(int) y.XSize(); i++){ + double sum2 = 0.0 ; + for ( int j = 0; j<(int) phi.YSize(); j++) + sum2 += phi(i,j)*mu(j) ; + sum1 += pow(y(i)-sum2,2) ; + } + + for ( int i = 0; i<(int) alpha.XSize(); i++) + sum3 += alpha(i)*Sig(i,i) ; + + sigma2 = sum1/((double) (n-index.XSize())+sum3) ; + errbars.Resize(Sig.XSize()) ; + for ( int i = 0; i<(int) errbars.XSize(); i++) errbars(i) = sqrt(Sig(i,i)); + + // Generate a basis for adaptive CS + if ( adaptive == 1 ){ + + if ( optimal == 1 ){ + int nSig = Sig.XSize() ; + double VL,VU ; + int IL=nSig,IU=nSig; + double ABSTOL = -1.0 ; + int nEigVals, info, ifail ; + double eigVal ; + basis.Resize(nSig) ; + int lWrk = 8*nSig ; + double *dwrk = new double[lWrk] ; + int *iwrk = new int [lWrk] ; + FTN_NAME(dsyevx)((char *)"V", (char *)"I", (char *)"L", &nSig, Sig.GetArrayPointer(), &nSig, + &VL, &VU, &IL, &IU, &ABSTOL, + &nEigVals, &eigVal, basis.GetArrayPointer(), + &nSig, dwrk, &lWrk, iwrk, &ifail, &info ) ; + delete [] dwrk ; + delete [] iwrk ; + if ( info != 0 ) + printf("WARNING : DSYEVX failed with info=%d\n",info) ; + } + + else{ + Array2D tmp1; + prodAlphaMatTMat(phi,phi,1.0/sigma2,tmp1); + double tmp1m = 0.0 ; + for ( int i = 0; i < (int) tmp1.XSize() ; i++ ) + tmp1m += tmp1(i,i); + tmp1m /= ( (double) tmp1.XSize() ) ; + Array2D Sig_inv ; + Sig_inv = tmp1 ; + for ( int i = 0 ; i < (int) Sig_inv.XSize() ; i++ ) + Sig_inv(i,i) += scale*tmp1m; + + int nSig = Sig_inv.XSize() ; + double VL,VU ; + int IL=1,IU=1; + double ABSTOL = -1.0 ; + int nEigVals, info, ifail ; + double eigVal ; + basis.Resize(nSig) ; + int lWrk = 8*nSig ; + double *dwrk = new double[lWrk] ; + int *iwrk = new int [lWrk] ; + FTN_NAME(dsyevx)((char *)"V", (char *)"I", (char *)"L", &nSig, Sig_inv.GetArrayPointer(), &nSig, + &VL, &VU, &IL, &IU, &ABSTOL, + &nEigVals, &eigVal, basis.GetArrayPointer(), + &nSig, dwrk, &lWrk, iwrk, &ifail, &info ) ; + delete [] dwrk ; + delete [] iwrk ; + if ( info != 0 ) + printf("WARNING : DSYEVX failed with info=%d\n",info) ; + } + + } + printf("BCS algorithm converged, # iterations : %d \n",count); + return ; + +} + + + + diff --git a/cpp/lib/bcs/bcs.h b/cpp/lib/bcs/bcs.h new file mode 100644 index 00000000..03d24dd6 --- /dev/null +++ b/cpp/lib/bcs/bcs.h @@ -0,0 +1,63 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file bcs.h +/// \brief Header for the implemenations of Bayesian compressive sensing algorithm. + +#ifndef BCS_H +#define BCS_H + +#include "Array1D.h" +#include "Array2D.h" + + +#define MAX_IT 1000 + + +/// \brief Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, +/// stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, +/// produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, +/// next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda. +void WBCS(Array2D &PHI, Array1D &y, double &sigma2, + double eta, Array1D &lambda_init, + int adaptive, int optimal, double scale, int verbose, + Array1D &weights, Array1D &used, + Array1D &errbars, Array1D &basis, + Array1D &alpha, double &lambda, Array2D &Sig); + +/// \brief Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, +/// stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, +/// produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, +/// next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda. +void BCS(Array2D &PHI, Array1D &y, double &sigma2, + double eta, Array1D &lambda_init, + int adaptive, int optimal, double scale, int verbose, + Array1D &weights, Array1D &used, + Array1D &errbars, Array1D &basis, + Array1D &alpha, double &lambda) ; + + +#endif // BCS_H diff --git a/cpp/lib/dfi/CMakeLists.txt b/cpp/lib/dfi/CMakeLists.txt new file mode 100644 index 00000000..38353792 --- /dev/null +++ b/cpp/lib/dfi/CMakeLists.txt @@ -0,0 +1,29 @@ + +SET(dfi_HEADERS + dfi.h + ) + +add_library(uqtkdfi dfi.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) +include_directories (../mcmc ) +include_directories (../dfi ) + +include_directories (../../../dep/slatec) +include_directories (../../../dep/blas) +include_directories (../../../dep/lapack) +include_directories (../../../dep/dsfmt ) +include_directories (../../../dep/figtree ) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories (../../../dep/lbfgs ) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtkdfi DESTINATION lib) + +# Install the header files +INSTALL(FILES ${dfi_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/dfi/dfi.cpp b/cpp/lib/dfi/dfi.cpp new file mode 100644 index 00000000..366de29a --- /dev/null +++ b/cpp/lib/dfi/dfi.cpp @@ -0,0 +1,156 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2013) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include +#include "error_handlers.h" +#include "Array1D.h" +#include "Array2D.h" +#include "quad.h" +#include "tools.h" +#include "arraytools.h" +#include "mcmc.h" +#include "gen_defs.h" +#include "lbfgs_routines.h" +#include "deplapack.h" +#include "depblas.h" + +#include "dfi.h" + +/********************************************* +Define the inner dfi mcmc chain +*********************************************/ +DFIInner::DFIInner(DFISetupBase& d){ + // Constructor sets up the logposterior + // from the DFISetupBase class + d_ = &d; + + this->nCalls = 30000; + this->nBurn = 10000; + +} +double DFIInner::eval(Array1D& beta){ + // evaluates logposterior as determined by DFISetupBase + return d_->f(beta,z_,sigma_); +} +void DFIInner::getSamples(){ + // ndim must be set before running this routine + // must also set initial start of chain beta0 + MCMC inner_chain(*this); + inner_chain.setWriteFlag(0); + inner_chain.setChainDim(ndim); + inner_chain.initMethod("am"); + inner_chain.initAdaptSteps(1000,1000,10000); + // inner_chain.initChainPropCovDiag(gammas_); //optional + + samples_.Clear(); + samples_.Resize(nCalls); + inner_chain.setOutputInfo("bin","chain.bin",nCalls,nCalls); + inner_chain.resetChainState(); + inner_chain.runChain(nCalls,beta0_); + inner_chain.getFullChain(samples_); + +} +double DFIInner::S(){ + // call user defined function of the inner samples + this->getSamples(); + return d_->S(samples_); +} + +/************************************************* +Main DFI Outer class +*************************************************/ +DFI::DFI(DFIInner& dfi_inner){ + dfi_inner_ = &dfi_inner; + + nBeta = dfi_inner_->ndim; + // sdim = dfi_inner_->sigma_.Length(); + // zdim = dfi_inner_->z_.Length(); +} +double DFI::eval(Array1D& zs){ + // get dimensions + int ndim = zdim + sdim; + + // unravel z and s + z_.Resize(zdim,0.0); + for (int i = 0; i < zdim; i++){ + z_(i) = zs(i); + } + int scount = 0; + sigma_.Resize(sdim,0.0); + for (int i = zdim; i < ndim; i++){ + sigma_(scount) = zs(i); + scount += 1; + } + dfi_inner_->z_ = z_; + dfi_inner_->sigma_ = sigma_; + + // get inner samples then evaluate S(z) + dfi_inner_->getSamples(); + + // flag to return -inf if sigma is <= 0 + int sigma_flag = 0; + for (int k = 0; k < sdim; k++){ + if (sigma_(k) <= 0){ + sigma_flag = 1; + } + } + + if (sigma_flag == 1){ + return -1e12; + } + else{ + return dfi_inner_->S(); + } +} +void DFI::runChain(int nCalls, Array1D gammas, Array1D start, int seed, int node){ + + MCMC outer_chain(*this); + outer_chain.setWriteFlag(1); + outer_chain.setSeed(seed); + outer_chain.setChainDim(start.Length()); + outer_chain.initMethod("ss"); + outer_chain.initChainPropCovDiag(gammas); + + char fn[100]; + snprintf(fn,sizeof fn,"outerchain%03i.txt",node); + outer_chain.setOutputInfo("txt",fn,5,1); + + outer_chain.runChain(nCalls,start); +} + +void DFI::getMLE(Array1D& xstart){ + + MCMC outer_chain(*this); + outer_chain.setChainDim(xstart.Length()); + outer_chain.runOptim(xstart); + // xstart(0) = 10000; + + return; +} +//******************************************************************** +//******************************************************************** + diff --git a/cpp/lib/dfi/dfi.h b/cpp/lib/dfi/dfi.h new file mode 100644 index 00000000..350e7f91 --- /dev/null +++ b/cpp/lib/dfi/dfi.h @@ -0,0 +1,95 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2013) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef UQTKDFI_H_SEEN +#define UQTKDFI_H_SEEN + + +#include "dsfmt_add.h" +#include "mcmc.h" + +class DFISetupBase{ +public: + + virtual double f(Array1D&, Array1D&, Array1D&){}; + virtual double S(Array1D inner_samples){}; +}; + +class DFIInner: public LikelihoodBase{ +public: + DFIInner(DFISetupBase& d); + DFIInner(){}; + ~DFIInner(){}; + + // params for running the inner chain + int ndim, nBurn, nCalls; // dim of inner chain + Array1D beta0_; // initial start + Array1D gammas_; // initial proposal covariance + Array1D samples_; // holds beta samples from inner chain + + DFISetupBase* d_; // class which holds logposterior + Array1D z_; // internal z data (change in outer loop) + Array1D sigma_; // internal sigma (change in outer loop) + + // variables for holding mean and variance + Array1D means_; + Array1D stds_; + Array1D quants; + + double eval(Array1D&); // evaluate logposterior + void getSamples(); // get Array1D of samples + + // params for summary statistics + Array1D means0; + Array1D stds0; + double delta1, delta2; + double S(); // comparison of summary statistics + +}; + +class DFI: public LikelihoodBase{ +public: + int zdim; + int sdim; + int nBeta; + + DFIInner* dfi_inner_; + int nCalls; + + DFI(DFIInner&); + ~DFI(){}; + + // params for eval function + Array1D z_; + Array1D sigma_; + + double eval(Array1D&); + void runChain(int nCalls, Array1D gammas, Array1D start, int seed, int node); + + void getMLE(Array1D& xstart); +}; + +#endif /* UQTKDFI_H_SEEN */ diff --git a/cpp/lib/gproc/CMakeLists.txt b/cpp/lib/gproc/CMakeLists.txt new file mode 100644 index 00000000..d46bc5cb --- /dev/null +++ b/cpp/lib/gproc/CMakeLists.txt @@ -0,0 +1,29 @@ +project(UQTk) + +SET(gproc_HEADERS + gproc.h + ) + +add_library(uqtkgproc gproc.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) +include_directories (../pce ) +include_directories (../bcs ) + + +include_directories (../../../dep/lapack) +include_directories (../../../dep/blas) +include_directories (../../../dep/lbfgs) +include_directories (../../../dep/dsfmt) +include_directories (../../../dep/figtree) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtkgproc DESTINATION lib) + +# Install the header files +INSTALL(FILES ${gproc_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/gproc/gproc.cpp b/cpp/lib/gproc/gproc.cpp new file mode 100644 index 00000000..1a27be2c --- /dev/null +++ b/cpp/lib/gproc/gproc.cpp @@ -0,0 +1,564 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file gproc.cpp +/// \author K. Sargsyan 2014 - +/// \brief Gaussian Process class + +#include +#include +#include + +#include "gproc.h" +#include "error_handlers.h" +#include "gen_defs.h" +#include "arraytools.h" +#include "arrayio.h" + +#include "tools.h" +#include "lbfgs_routines.h" + +#include + +/// Function to compute negative log posterior (needed to maximize with respect to roughness parameter) +/// \todo Find a more elegant way to do this within the class +double neglogPostParam(int ndim, double* m, void* classpointer); + +// Constructor given PC basis and covariance type and parameters +Gproc::Gproc(const string covtype, PCSet *PCModel, Array1D& param) +{ + // Set the PC regression + PCModel_=PCModel; + npc_=PCModel_->GetNumberPCTerms(); + printf("gproc : Number of PC terms : %d\n",npc_); + + + ndim_=PCModel_->GetNDim(); + param_=param; + covType_=covtype; + + return; +} + +// Setup the prior - currently hardwired to the common practice values +void Gproc::SetupPrior() +{ + // Inverse prior on regression coefficients is set to zero + Vinv_.Resize(npc_,npc_,0.e0); //V^-1 + // Prior mean on coefficients is set to zero + z_.Resize(npc_,0.e0); //z + // Parameters of data noise prior: setting to zero corresponds to 1/sigma prior + al_=0.e0; + be_=0.e0; + + // If data noise is explicitely given, use this construction below + // sig2f_=0.0; + // if (sig2f_!=0.0) + // be_=al_*sig2f_; + + return; +} + +// Setup x- and y- data, together with the variance +void Gproc::SetupData(Array2D& xdata, Array1D& ydata,Array1D& datavar) +{ + xdata_=xdata; + ydata_=ydata; + npt_=xdata.XSize(); + assert(npt_=datavar.XSize()); + dataVar_=datavar; + + return; +} + +// Building Gaussian Process +void Gproc::BuildGP() +{ + cout << "Building GP" << endl; + int npts=xdata_.XSize(); + int ndim=xdata_.YSize(); + assert(ndim==ndim_); + + // Fill in the projection matrix H_ + printf("Computing projection matrix\n"); + PCModel_->EvalBasisAtCustPts(xdata_,H_); + transpose(H_,Ht_); + + // Fill in the covariance matrix A_ + printf("Filling in data covariance matrix of size %d x %d\n", npts,npts); + computeDataCov_(xdata_,param_,A_); + printf("Done.\n"); + + printf("Solving Ax=y for A of size %d x %d, and y of size %d\n", npts,npts,npts); + // Matrix manipulations to arrive to the answer(this should be done more efficiently) + Ainvd_=Ainvb(A_,ydata_); + printf("Done.\n"); + + prodAlphaMatVec(Ht_,Ainvd_, 1.0, HtAinvd_) ; + + printf("Solving AX=H for A of size %d x %d, and H of size %d x %d\n", npts,npts,npts,H_.YSize()); + AinvH_=AinvH(A_, H_); + printf("Done.\n"); + + // Further linear algebra + prodAlphaMatMat(Ht_,AinvH_, 1.0, HtAinvH_) ; + Array2D tmp; + tmp=add(Vinv_,HtAinvH_); + Vst_=INV(tmp); + Array1D temp; + prodAlphaMatVec(Vinv_, z_, 1.0, Vinvz_) ; + temp=add(Vinvz_,HtAinvd_); + prodAlphaMatVec(Vst_, temp, 1.0, bhat_) ; + prodAlphaMatVec(H_, bhat_, 1.0, Hbhat_) ; + yHbhat_=subtract(ydata_,Hbhat_); + + AinvyHbhat_=Ainvb(A_,yHbhat_); + + // Get the sigma_^2_hat, i.e. best value for the data noise + sig2hat_=2.*be_; + sig2hat_+=prod_vecTmatvec(z_,Vinv_,z_); + //sig2hat_+=prod_vecTmatvec(ydata_,Ainv_,ydata_); + sig2hat_+=dot(ydata_,Ainvd_); + + Vstinv_=INV(Vst_); + sig2hat_-=prod_vecTmatvec(bhat_,Vstinv_,bhat_); + sig2hat_ /= (npts+2.*al_-npc_-2.); + + return; +} + +// An older implementation that relies on explicit matrix inversion (is kept for further timing tests) +void Gproc::BuildGP_inv() +{ + cout << "Building GP" << endl; + int npts=xdata_.XSize(); + int ndim=xdata_.YSize(); + assert(ndim==ndim_); + + // Fill in the projection matrix H_ + printf("Computing projection matrix\n"); + PCModel_->EvalBasisAtCustPts(xdata_,H_); + transpose(H_,Ht_); + + // Fill in the covariance matrix A_ + printf("Computing data covariance matrix\n"); + computeDataCov_(xdata_,param_,A_); + + + cout << "gproc : Computing the inverse of the covariance matrix at the data points...." << endl; + Ainv_=INV(A_); + cout << "gproc : Done computing the inverse." << endl; + + + // Matrix manipulations to arrive to the answer (this should be done more efficiently) + prodAlphaMatVec(Ainv_, ydata_, 1.0, Ainvd_) ; + prodAlphaMatVec(Ht_,Ainvd_, 1.0, HtAinvd_) ; + prodAlphaMatMat(Ainv_,H_, 1.0, AinvH_) ; + prodAlphaMatMat(Ht_,AinvH_, 1.0, HtAinvH_) ; + Array2D tmp; + tmp=add(Vinv_,HtAinvH_); + Vst_=INV(tmp); + Array1D temp; + prodAlphaMatVec(Vinv_, z_, 1.0, Vinvz_) ; + temp=add(Vinvz_,HtAinvd_); + prodAlphaMatVec(Vst_, temp, 1.0, bhat_) ; + prodAlphaMatVec(H_, bhat_, 1.0, Hbhat_) ; + yHbhat_=subtract(ydata_,Hbhat_); + prodAlphaMatVec(Ainv_, yHbhat_, 1.0, AinvyHbhat_) ; + + // Get the sigma_^2_hat + sig2hat_=2.*be_; + sig2hat_+=prod_vecTmatvec(z_,Vinv_,z_); + sig2hat_+=prod_vecTmatvec(ydata_,Ainv_,ydata_); + Vstinv_=INV(Vst_); + sig2hat_-=prod_vecTmatvec(bhat_,Vstinv_,bhat_); + sig2hat_ /= (npts+2.*al_-npc_-2.); + + return; +} + +// Evaluate GP after it is built, given x-data +void Gproc::EvalGP(Array2D& xgrid, string msc, Array1D& mst) +{ + assert(ndim_==xgrid.YSize()); + int totgrid=xgrid.XSize(); + int npts=xdata_.XSize(); + + // Get the mean values at the grid points + PCModel_->EvalPCAtCustPoints(mst,xgrid,bhat_); + + + Array2D ttmat(totgrid,npts); + printf("Evaluating GP mean... \n"); + for (int igr=0;igr xcurr; + getRow(xgrid, igr, xcurr); + for (int ipts=0;ipts xdata_i; + getRow(xdata_, ipts, xdata_i); + ttmat(igr,ipts)=covariance(xcurr,xdata_i,param_); + } + } + + Array1D mst_corr; + prodAlphaMatVec(ttmat, AinvyHbhat_, 1.0, mst_corr); + addinplace(mst,mst_corr); + + // If standard deviation is also requested + if (msc=="ms"){ + var_.Resize(totgrid,0.e0); + Array2D ttmat_t; + transpose(ttmat,ttmat_t); + Array2D tmp=AinvH(A_,ttmat_t); + + printf("Evaluating GP variance... \n"); + for(int it=0;it xcurr; + getRow(xgrid, it, xcurr); + + Array1D tt; + getRow(ttmat,it, tt); + + Array1D tmpp; + getCol(tmp,it,tmpp); + double correction1=dot(tmpp,tt); + + Array1D ttAinvH; + prodAlphaMatTVec(AinvH_,tt,1.0,ttAinvH); + + // Fill in appropriate matrices + Array2D H_atgrid; + PCModel_->EvalBasisAtCustPts(xgrid,H_atgrid); + + Array1D ht; + getRow(H_atgrid,it,ht); + + Array1D httAinvH; + httAinvH=subtract(ht,ttAinvH); + + double correction2=prod_vecTmatvec(httAinvH,Vst_,httAinvH); + + + var_(it)=(sig2hat_*(covariance(xcurr,xcurr,param_)-correction1+correction2)); + + } + } + + // If covariances are also requested + else if (msc=="msc"){ + Array2D ttmat_t; + transpose(ttmat,ttmat_t); + Array2D tmp=AinvH(A_,ttmat_t); + Array2D cov_corr1; + prodAlphaMatMat(ttmat, tmp, 1.0, cov_corr1); + + // Fill in appropriate matrices + Array2D H_atgrid; + PCModel_->EvalBasisAtCustPts(xgrid,H_atgrid); + + Array2D ttmatAinvH; + prodAlphaMatMat(ttmat,AinvH_,1.0,ttmatAinvH); + + Array2D h_ttmatAinvH; + h_ttmatAinvH=subtract(H_atgrid,ttmatAinvH); + Array2D h_ttmatAinvH_t; + transpose(h_ttmatAinvH,h_ttmatAinvH_t); + + Array2D tmpp; + prodAlphaMatMat(Vst_,h_ttmatAinvH_t,1.0,tmpp); + Array2D cov_corr2; + prodAlphaMatMat(h_ttmatAinvH,tmpp,1.0, cov_corr2); + + cov_.Resize(totgrid,totgrid,0.e0); + var_.Resize(totgrid,0.e0); + + for(int it=0;it xcurr; + getRow(xgrid, it, xcurr); + + for(int jt=0;jt xcurra; + getRow(xgrid, jt, xcurra); + cov_(it,jt)=covariance(xcurr,xcurra,param_) ; + } + } + subtractinplace(cov_,cov_corr1); + addinplace(cov_,cov_corr2); + scaleinplace(cov_,sig2hat_); + + for(int it=0;it& xgrid, string msc, Array1D& mst) +{ + assert(ndim_==xgrid.YSize()); + int totgrid=xgrid.XSize(); + int npts=xdata_.XSize(); + + // Get the mean values at the grid points + PCModel_->EvalPCAtCustPoints(mst,xgrid,bhat_); + + // Fill in appropriate matrices + Array2D H_atgrid; + PCModel_->EvalBasisAtCustPts(xgrid,H_atgrid); + + // If more than the mean is requested + if (msc != "m"){ + cov_.Resize(totgrid,totgrid,0.e0); + var_.Resize(totgrid,0.e0); + } + // Compute the covariance structure of the student-t process + for(int it=0;it xcurr(ndim_,0.e0); + for (int id=0;id tt(npts,0.e0); + for(int ipts=0;ipts xdata_i(ndim_,0.e0); + for (int id=0;id ttAinvH; + prodAlphaMatTVec(AinvH_,tt,1.0,ttAinvH); + + Array1D ht(npc_,0.e0); + for(int ipc=0;ipc httAinvH; + httAinvH=subtract(ht,ttAinvH); + + for(int jt=it;jt xcurra(ndim_,0.e0); + for (int id=0;id tta(npts,0.e0); + for(int ipts=0;ipts xdata_i(ndim_,0.e0); + for (int id=0;id ttaAinvH; + prodAlphaMatTVec(AinvH_,tta,1.0,ttaAinvH); + + + Array1D hta(npc_,0.e0); + for(int ipc=0;ipcnpc_;ipc++) + hta(ipc)=H_atgrid(jt,ipc); + + + Array1D ht_t_AinvH; + ht_t_AinvH=subtract(hta,ttaAinvH); + + double correction2=prod_vecTmatvec(httAinvH,Vst_,ht_t_AinvH); + double correction1=prod_vecTmatvec(tt,Ainv_, tta); + + cov_(it,jt)=(sig2hat_*(covariance(xcurr,xcurra,param_)-correction1+correction2)); + if (it!=jt) + cov_(jt,it)=cov_(it,jt); + + if (msc != "msc") break; + + }//jt=it + }//if m + var_(it)=cov_(it,it); + }//it + + return; +} + +// Parameters of the resulting student-t prediction +// The actual, sigma-integrated predictions are Student-t +void Gproc::getSttPars(Array1D& sttmat) +{ + sttmat.Clear(); + /// \todo check that full cov_ already defined(i.e. msc) not just diagonal + int npts=xdata_.XSize(); + int totgrid=cov_.XSize(); + + + for(int it=0;it& xgrid,Array2D& xycov) +{ + /// \todo check that full cov_ already defined(i.e. msc) not just diagonal + int totgrid=cov_.XSize(); + + xycov.Resize(totgrid*totgrid,2*ndim_+1,0.e0); + int ii=0; + for(int it=0;it& x1, Array1D& x2,Array1D& param) +{ + /// \todo put an 'if' check for covtype_ + int n=x1.XSize(); + int nn=x2.XSize(); + + if (nn!=n ) { + printf("Gproc:covariance() : Error message: covariance: matrix dimensions do not match! \n"); exit(1); + } + + double cov=0.0; + + Array2D B(nn,nn,0.e0); + for(int i=0;i x12; + x12=subtract(x1,x2); + + Array1D Bx12; + prodAlphaMatVec (B, x12, 1.0, Bx12) ; + + cov=exp(-dot(x12,Bx12)); + + return cov; +} + +// Compute full covariance matrix given the data +void Gproc::computeDataCov_(Array2D& xdata,Array1D& param,Array2D& A) +{ + int npts=xdata.XSize(); + int ndim=xdata.YSize(); + A.Resize(npts,npts,0.e0); + for(int i=0;i xdatai(ndim,0.e0); + Array1D xdataj(ndim,0.e0); + for(int id=0;idcovariance(xdatai,xdataj,param)+dataVar_(i)*(i==j); + } + } + + return; +} + +// Find the best correlation length parameter according to max-posterior +void Gproc::findBestCorrParam() +{ + Array1D logparam(ndim_,0.0); + int n=ndim_; + int m=5; + Array1D nbd(n,0); + Array1D l(n,0.e0); + Array1D u(n,0.e0); + + void* info=this; + + lbfgsDR(n,m,logparam.GetArrayPointer(),nbd.GetArrayPointer(),l.GetArrayPointer(),u.GetArrayPointer(),neglogPostParam,NULL,info) ; + + + for (int i=0;igetNdim()); + Array1D param(ndim,0.e0); + + for(int i=0;isetCorrParam(param); + thisClass->BuildGP(); + + double lpp=-(thisClass->getNpt()+2.*thisClass->getAl()-thisClass->getNPC())/2.; + + lpp*=log(thisClass->getSig2hat()); + + + Array2D vst; + thisClass->getVst(vst); + + Array2D acor; + thisClass->getA(acor); + + lpp+=0.5*logdeterm(vst); + lpp-=0.5*logdeterm(acor); + + return -lpp; +} + + + diff --git a/cpp/lib/gproc/gproc.h b/cpp/lib/gproc/gproc.h new file mode 100644 index 00000000..53ae6fa2 --- /dev/null +++ b/cpp/lib/gproc/gproc.h @@ -0,0 +1,167 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file gproc.h +/// \author K. Sargsyan 2014 - +/// \brief Header file for Gaussian Process class + +#ifndef GPROC_H_SEEN +#define GPROC_H_SEEN + +#include "Array1D.h" +#include "Array2D.h" +#include "PCSet.h" + +/// \class Gproc +/// \brief Class for Gaussian processes +class Gproc { +public: + + /// \brief Constructor: initialize with covariance type, trend function basis + /// and roughness parameter vector + Gproc(const string covtype, PCSet *PCModel, Array1D& param); + /// \brief Destructor: cleans up all memory and destroys object + ~Gproc() {}; + + /// \brief Setup the prior + void SetupPrior(); + /// \brief Setup the data + void SetupData(Array2D& xdata, Array1D& ydata,Array1D& datavar); + /// \brief Set the roughness parameter vector + void setCorrParam(Array1D param){param_=param; return;} + + /// \brief Build Gaussian Process regressor, i.e. compute internally + /// all necessary matrices and vectors that describe the posterior GP + void BuildGP(); + /// \brief Build Gaussian Process regressor, i.e. compute internally + /// all necessary matrices and vectors that describe the posterior GP + /// \note This is an older implementation with explicit inversion of measurement matrix + /// \todo Need formal timing analysis to understand in which situations this version is preferred + void BuildGP_inv(); + /// \brief Evaluate the Gaussian Process at a given grid + /// msc controls whether only mean will be computed, or standard devation and covariance as well + void EvalGP(Array2D& xgrid, string msc, Array1D& mst); + /// \brief Evaluate the Gaussian Process at a given grid + /// msc controls whether only mean will be computed, or standard devation and covariance as well + /// \note This is an older implementation with explicit inversion of measurement matrix + /// \todo Need formal timing analysis to understand in which situations this version is preferred + void EvalGP_inv(Array2D& xgrid, string msc, Array1D& mst); + /// \brief Get the number of data points + int getNpt() const {return npt_;} + /// \brief Get the dimensionality + int getNdim() const {return ndim_;} + /// \brief Get the number of basis terms in the trend + int getNPC() const {return npc_;} + /// \brief Get alpha parameter + double getAl() const {return al_;} + /// \brief Get beta parameter + double getBe() const {return be_;} + /// \brief Get Sigma-hat-squared, i.e. the posterior variance factor + double getSig2hat() const {return sig2hat_;} + /// \brief Get \f$V^*\f$, an auxiliary matrix + void getVst(Array2D& vst) {vst=Vst_; return;} + /// \brief Get the correlation matrix \f$A\f$ + void getA(Array2D& acor) {acor=A_; return;} + /// \brief Get the roughness parameters + void getParam(Array1D& param) {param=param_; return;} + /// \brief Get the posterior covariance matrix + void getCov(Array2D& cov) {cov=cov_;} + /// \brief Get the posterior variance vector + void getVar(Array1D& var) {var=var_;} + /// \brief Get the covariance in a different format, with the x,x' values + void getXYCov(Array2D& xgrid,Array2D& xycov); + /// \brief Get the Student-t parameters + void getSttPars(Array1D& sttmat); + /// \brief Function to find the best values for roughness parameters + void findBestCorrParam(); + + + private: + + /// \brief Prior covariance function + double covariance(Array1D& x1, Array1D& x2,Array1D& param); + /// \brief Compute the data covariance \f$A\f$ + void computeDataCov_(Array2D& xdata,Array1D& param,Array2D& A); + + /// \brief xdata array + Array2D xdata_; + /// \brief ydata array + Array1D ydata_; + /// \brief Data noise 'nugget' + Array1D dataVar_; + + /// \brief Number of bases in the mean trend + int npc_; + /// \brief Inverse of the mean trend coefficient prior covariance + Array2D Vinv_; + /// \brief Prior mean of the mean trend + Array1D z_; + //double sig2f_; + /// \brief Prior parameter \f$\alpha\f$ + double al_; + /// \brief Prior parameter \f$\beta\f$ + double be_; + /// \brief Posterior variance factor + double sig2hat_; + + /// \brief Number of data points + int npt_; + /// \brief Dimensionality + int ndim_; + /// \brief Covariance type, only 'SqExp' implemented so far + string covType_; + /// \brief Basis set for the trend function + PCSet *PCModel_; + + /// \brief Mean of the Student-t posterior + Array1D mst_; + /// \brief Variance of the Student-t posterior + Array1D var_; + /// \brief Covariance of the Student-t posterior + Array2D cov_; + /// \brief Roughness parameter vector + Array1D param_; + + //@{ + /// \brief Auxiliary matrices or vectors, see the UQTk Manual + Array2D H_, Ht_; + Array2D A_, Ainv_; + Array1D Ainvd_; + Array1D Vinvz_; + Array1D HtAinvd_; + Array2D AinvH_; + Array2D HtAinvH_; + Array2D Vst_; // V^* + Array1D bhat_; + Array1D Hbhat_; + Array1D yHbhat_; + Array1D AinvyHbhat_; + Array2D Vstinv_; + //@} + + +}; +#endif /* GPROC_H_SEEN */ diff --git a/cpp/lib/include/CMakeLists.txt b/cpp/lib/include/CMakeLists.txt new file mode 100644 index 00000000..066eb44c --- /dev/null +++ b/cpp/lib/include/CMakeLists.txt @@ -0,0 +1,10 @@ + +SET(misc_HEADERS + error_handlers.h + ftndefs.h + gen_defs.h + uqtkconfig.h + ) + +# Install the header files +INSTALL(FILES ${misc_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/include/error_handlers.h b/cpp/lib/include/error_handlers.h new file mode 100644 index 00000000..8fb38ed4 --- /dev/null +++ b/cpp/lib/include/error_handlers.h @@ -0,0 +1,52 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef ERROR_HANDLERS_H_SEEN +#define ERROR_HANDLERS_H_SEEN + +#include +#include + +using namespace std; + +/// \class Tantrum +/// \brief Error handler: allows program to display an error message +/// and exit +/// \todo Build in more smarts for tracing error etc. +struct Tantrum { + /// \brief String literal to store error message in + const char* p; + /// \brief Constructor that takes a string literal as error message + /// to display before core dumping + Tantrum(const char*q) {p=q; cout << p << endl;} + /// \brief Constructor that takes a string as error message + /// to display before core dumping + Tantrum(std::string q) {p=q.c_str(); cout << p << endl;} +}; + + + +#endif /* ERROR_HANDLERS_H_SEEN */ diff --git a/cpp/lib/include/ftndefs.h b/cpp/lib/include/ftndefs.h new file mode 100644 index 00000000..4b0df5fd --- /dev/null +++ b/cpp/lib/include/ftndefs.h @@ -0,0 +1,78 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ + +/** \file ftndefs.h + * header file with definitions and macros to use when calling fortran + * functions from C/C++ and vice versa + * inspired by http://www.thp.univie.ac.at/~jthorn/c2f.html + */ + +/* this header file is idempotent */ +#ifndef FTNDEFS_H_SEEN +#define FTNDEFS_H_SEEN +/**********************************************************************/ + +/* + * C/C++ compatibility: + */ + +/* + * Use this in prototypes like this: extern FTN_FUNC void foo(...) + * + * At present, this is set up to tell a C++ compiler that foo() uses + * a C-compatible calling convention. + */ +#ifdef __cplusplus + #define FTN_FUNC "C" +#else + #define FTN_FUNC /* empty */ +#endif + +/* + * Macro to convert function names to Fortran format + */ + +/* + * Names of Fortran routines are often altered by the compiler/loader. The + * following macro should be used to call a Fortran routine from C code, i.e. + * call sgefa(...) -- Fortran code + * FTN_NAME(sgefa)(...); -- C code to do the same thing + * Make sure the fortran names are always lower case in the C code. + * Specify "wsu" for "with single underscore" if the Fortran compiler appends a single + * underscore to function names. Use "wdu" for "with double underscore". + */ + +#if defined(__wsu) + #define FTN_NAME(n_) n_ ## _ +#elif defined(__wdu) + #define FTN_NAME(n_) n_ ## __ +#else + #error "FTN_NAME macros not defined for this system" +#endif + +/**********************************************************************/ +#endif /* FNTDEFS_H_SEEN */ diff --git a/cpp/lib/include/gen_defs.h b/cpp/lib/include/gen_defs.h new file mode 100644 index 00000000..bc156a2d --- /dev/null +++ b/cpp/lib/include/gen_defs.h @@ -0,0 +1,54 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/** \file gen_defs.h + * Miscellaneous definitions used in several utilities. + */ + +#include "assert.h" + +#ifndef GENDEFS_H +#define GENDEFS_H + +#define BOOLEAN unsigned char + +#ifndef TRUE +# define TRUE ((BOOLEAN)1) +# define FALSE ((BOOLEAN)0) +#endif + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define SIGN(a,b) ( (b) >= 0.0 ? fabs(a) : -fabs(a) ) +#define SWAP(a,b) { double temp=(a); (a)=(b); (b)=temp; } +#define CHECKEQ(a,b) { if ( (a) != (b) ) { cout << "Equality check failed: " << (a) << " not equal to " << (b) << endl; assert( (a)==(b) );} } + +extern char *optarg; + + + + +#endif // GENDEFS_H diff --git a/cpp/lib/include/uqtkconfig.h b/cpp/lib/include/uqtkconfig.h new file mode 100644 index 00000000..95e854ab --- /dev/null +++ b/cpp/lib/include/uqtkconfig.h @@ -0,0 +1,41 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef UQTKCONFIG_H_ +#define UQTKCONFIG_H_ + + +/* Define debug mode */ +/* Should remove all occurences when everything is stable enough */ +#define UQTKDEBUG false + +/* Define a small number */ +#define SMALL 1.e-15 + +/* Define the shape parameter for gamma distribution */ +#define GAMMA_ALPHA 1.0 + +#endif /* !UQTKCONFIG_H_ */ diff --git a/cpp/lib/infer/CMakeLists.txt b/cpp/lib/infer/CMakeLists.txt new file mode 100644 index 00000000..95856b4a --- /dev/null +++ b/cpp/lib/infer/CMakeLists.txt @@ -0,0 +1,31 @@ +project (UQTk) + +SET(infer_HEADERS + inference.h + mrv.h + post.h + ) + +add_library(uqtkinfer inference.cpp mrv.cpp post.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) +include_directories (../pce ) +include_directories (../mcmc ) + +include_directories (../../../dep/slatec) +include_directories (../../../dep/lapack) +include_directories (../../../dep/dsfmt ) +include_directories (../../../dep/figtree ) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories (../../../dep/lbfgs ) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtkinfer DESTINATION lib) + +# Install the header files +INSTALL(FILES ${infer_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/infer/inference.cpp b/cpp/lib/infer/inference.cpp new file mode 100644 index 00000000..e26ec10f --- /dev/null +++ b/cpp/lib/infer/inference.cpp @@ -0,0 +1,325 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file inference.cpp +/// \author K. Sargsyan 2016 - +/// \brief Model inference tools + +#include +#include +#include +#include +#include +#include + +#include "func.h" +#include "post.h" +#include "mrv.h" +#include "inference.h" + +#include "mcmc.h" +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" + +using namespace std; + +void infer_model(Array1D< Array2D (*)(Array2D&, Array2D&, Array2D&, void *) > forwardFuncs, void* funcInfo, + string likType, + string priorType, double priora, double priorb, + Array2D& xdata,Array2D& ydata, Array2D& xgrid, + int dataNoiseInference, Array1D& datanoise_array, + int pdim, int order,Array1D& rndInd,Array2D& fixindnom, string pdfType, string pcType, + int seed, int nmcmc, double mcmcgamma, bool optimflag, Array1D& chstart, Array1D& chsig, + double likParam, int likParam_int, + Array2D& pgrid,Array2D& pchain, int nburn, int nstep, + Array1D& mapparam, Array1D& datavar_map, + Array1D& pmean_map, Array1D& pvar_map, + Array1D& fmean_map, Array1D& fvar_map, + Array1D& postave_datavar, + Array1D& p_postave_mean, Array1D& p_postave_var, Array1D& p_postvar_mean, + Array2D& f_postsam_mean, Array1D& f_postave_mean, Array1D& f_postave_var, Array1D& f_postvar_mean, + Array2D& paramPCcfs){ + + // Some input argument checks and fixes + if (likType=="classical" or likType=="koh"){ + if (pdfType!="full"){ + cout << "Classical likelihood or koh likelihood types require full PDF type." << endl; + pdfType="full"; + } + if (order!=0){ + cout << "Classical or koh likelihood types require zeroth order of PDF PC." << endl; + order=0; + } + } + + // Read x-grid size + int nxgr = xgrid.XSize(); + assert(xgrid.YSize()==xdata.YSize()); + + // Match the likelihood type with the appropriate derived class + map lik_dict; + lik_dict["full"]=new Lik_Full(likParam,likParam_int); + lik_dict["marg"]=new Lik_Marg(likParam,likParam_int); + lik_dict["mvn"]=new Lik_MVN(likParam); + lik_dict["gausmarg"]=new Lik_GausMarg(); + lik_dict["abc"]=new Lik_ABC(likParam); + lik_dict["abcm"]=new Lik_ABCm(likParam); + lik_dict["koh"]=new Lik_Koh(likParam); + lik_dict["classical"]=new Lik_Classical(); + + + if (lik_dict.count(likType)==0){ + cout << "Likelihood type " << likType << " is not found. Exiting." << endl; + exit(1); + } + Post* mypost=lik_dict[likType]; + + // Parse the data noise information + if (dataNoiseInference==0) + mypost->setDataNoise(datanoise_array); + else if (dataNoiseInference==1) + mypost->inferDataNoise(); + else if (dataNoiseInference==2) + mypost->inferLogDataNoise(); + + // Set data + mypost->setData(xdata,ydata); + // Set model + mypost->setModel(forwardFuncs, fixindnom, funcInfo); + // Set the randomized model parameter input + mypost->setModelRVinput(pdim, order,rndInd, pdfType, pcType); + // Set prior + mypost->setPrior(priorType,priora,priorb); + + // Get the chain dimensionality + int chdim=mypost->getChainDim(); + cout << "MCMC dimensionality : " << chdim << endl; + if (chstart.Length()==0) + chstart.Resize(chdim,0.1); + if (chsig.Length()==0) + chsig.Resize(chdim,0.01); + + assert (chdim==chstart.Length() and chdim==chsig.Length()); + + // Overwrite to chain initial state + if (dataNoiseInference>0) + chstart(chdim-1)=datanoise_array(0); + + // Initialize chain + MCMC mchain(LogPosterior,(void *) mypost); + mchain.setSeed(seed); + mchain.setChainDim(chdim); + + // If given parameter grid, compute exact posterior, up to a normalization + int npgr=pgrid.XSize(); + if (npgr>0){ + + cout << "Compute posterior at a grid..........." << endl; + assert(pgrid.YSize()==chdim); + double sum=0.0; + Array1D pdens(npgr,0.e0); + Array1D pdens_log(npgr,0.e0); + for(int i=0;i pgrid1p; + getRow(pgrid,i,pgrid1p); + pdens(i)=exp(mchain.evalLogPosterior(pgrid1p)); + pdens_log(i)=mchain.evalLogPosterior(pgrid1p); + double normalize=1.0; + sum+=pdens(i)*normalize; + } + write_datafile_1d(pdens,"pdens_unnorm.dat"); + + for(int i=0;i0){ + cout << "Starting MCMC..................." << endl; + mchain.runChain(nmcmc, chstart); + } + + if (optimflag || nmcmc>0){ + // get MAP value + mchain.getMode(mapparam); + // thin the chain and remove burn-in + mchain.getSamples(nburn, nstep, pchain); + // append MAP values, too + pchain.insertCol(mapparam,pchain.YSize()); + // transpose for convenient reading/plotting + pchain=Trans(pchain); + } + } + else{ + assert(pchain.YSize()==chdim); + nmcmc=0; + optimflag=false; + cout << "Posterior samples provided. Forcing nmcmc=0 and optimflag=false." << endl; // move this up? + // if pchain is provided, its last row is read as MAP + getRow(pchain, pchain.XSize()-1, mapparam); + } + + // Switch the model, if needed + int pred_mode=1; + funcInfo=(void*) &pred_mode; + mypost->setModel(forwardFuncs, fixindnom, funcInfo); + + + // Compute function prediction moments at xgrid and parameter moments at MAP values + // (skip the covariances) + int npc=0; + Array2D mapparamPCcf; + Array1D mapparamPCcf_flat; + //if (optimflag || nmcmc>0) + //{ + Array2D fcov_map,pcov_map;//dummy + mypost->momForwardFcn(mapparam, xgrid, fmean_map, fvar_map, false, fcov_map); + mypost->momParam(mapparam, pmean_map, pvar_map, false, pcov_map); + + // Compute parameter PC coefficients at MAP values + mapparamPCcf=mypost->getParamPCcf(mapparam); + flatten(mapparamPCcf,mapparamPCcf_flat); + npc=mapparamPCcf_flat.Length(); + // Compute MAP data variance + Array1D tmp=mypost->dataSigma(mapparam(mapparam.Length()-1)); + datavar_map=dotmult(tmp,tmp); + //} + + cout << "===========================================================" << endl; + + npost=pchain.XSize(); + // Repeat postprocessing for each posterior sample + cout << endl << "Going through " << npost << " posterior samples" << endl; + paramPCcfs.Resize(npc,0); + postave_datavar.Resize(xdata.XSize(),0.0); + for(int ipost=0;ipost fmean_mcmc,fvar_mcmc, pmean_mcmc,pvar_mcmc; + Array2D fcov_mcmc,pcov_mcmc; + // Get current parameter column + Array1D mcmcparam; + getRow(pchain,ipost,mcmcparam); + + // Compute function prediction moments at xgrid and parameter moments at current chain values + // (skip the covariances) + mypost->momForwardFcn(mcmcparam, xgrid, fmean_mcmc, fvar_mcmc, false, fcov_mcmc); + mypost->momParam(mcmcparam, pmean_mcmc, pvar_mcmc, false, pcov_mcmc); + + // Compute parameter PC coefficients at current chain values + Array2D mcmcparamPCcf=mypost->getParamPCcf(mcmcparam); + + Array1D mcmcparamPCcf_flat; + flatten(mcmcparamPCcf,mcmcparamPCcf_flat); + paramPCcfs.insertCol(mcmcparamPCcf_flat,ipost); + // Compute posterior average of data variance + // note: if there is no data variance inference, then this is extra work + Array1D tmp=mypost->dataSigma(mcmcparam(mcmcparam.Length()-1)); + Array1D tmp2=dotmult(tmp,tmp); + scaleinplace(tmp2,1./npost); + addinplace(postave_datavar,tmp2); + + // Compute posterior average of parameter mean and variance, and posterior variance of parameter mean + for (int ip=0;ip0){ + cout << "Max a posteriori of data variance " << datavar_map(0) << endl; + cout << "Posterior average of data variance " << postave_datavar(0) << endl; + } + + return; +} + +// Log-posterior function given chain state and auxiliary parameters +double LogPosterior(Array1D& m, void* mypost_void) +{ + Post* mypost = (Post*) mypost_void; + + double logprior=mypost->evalLogPrior(m); + double loglik=0.0; + if (logprior>-1.e80){ + loglik=mypost->evalLogLik(m); + + } + + + double logpost=loglik+logprior; + + return logpost; +} + diff --git a/cpp/lib/infer/inference.h b/cpp/lib/infer/inference.h new file mode 100644 index 00000000..d14d8a54 --- /dev/null +++ b/cpp/lib/infer/inference.h @@ -0,0 +1,106 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file inference.h +/// \author K. Sargsyan 2016 - +/// \brief Header for the model inference tools + +#include + +#include "Array1D.h" +#include "Array2D.h" + + +/// \brief Main function for inferring model parameters +/// \note This is written in a fortran style, i.e. some arguments are inputs, and the rest are output +/// \param[in] *forwardFuncs : an array of y=f(p,x) functions that take np-by-pdim and nx-by-xdim input arrays +/// and returns an np-by-nx output, see tools/func.h for several examples +/// \param[in] funcinfo : auxiliary function-specific information (can be 0) +/// \param[in] likType : likelihood type: options are +/// 'full', 'marg', 'mvn', 'gausmarg', 'abc', 'abcm', 'classical', 'koh' (see UQTk Manual) +/// \param[in] priorType : prior type: options are 'uniform', 'normal', 'inverse', etc ... (see UQTk Manual) +/// \param[in] priora, priorb : prior parameters (todo: need to be made dimension-specific) +/// for uniform, it is the range, for normal it is the moments +/// \param[in] xdata : x-values of data, nx-by-xdim +/// \param[in] ydata : y-values of data, nx-by-neach +/// \param[in] xgrid : x-values where predictive moments are computed after the inference +/// : can be the same as xdata +/// \param[in] dataNoiseInference : indicator, data noise stdev is fixed(0), inferred (1), or log-inferred (2) +/// \param[in] datanoise_array : data noise stdev array, if fixed, otherwise merely an MCMC starting point +/// \param[in] pdim : model parameter dimensionality +/// \param[in] order : order of output PC that is computed via NISP in the likelihood +/// \param[in] rndInd : array of indices of parameters to be randomized +/// \param[in] fixIndNom : array of indices and nominal values of parameters to be fixed +/// \param[in] pdfType : type of PDF PC parameterization, options are 'pct','pci' and 'full' (see UQTk Manual) +/// \param[in] pcType : type of PC for the PDF parameterization, options are all common PC types, e.g. 'HG','LU' +/// \param[in] seed : integer seed for MCMC +/// \param[in] nmcmc : number of MCMC steps to follow optimization; if 0, then only optimization is performed if optimflag is True +/// \param[in] mcmcgamma : gamma (scaling) parameter for adaptive MCMC +/// \param[in] optimflag : indicates if optimization is prepended to MCMC +/// \param[in] chstart : initial chain state +/// \param[in] chsig : initial non-adaptive, dimensionwise proposal jump size +/// \param[in] likParam, likParam_int : likelihood parameters (currently, only needed for KDE-based likelihoods, +/// 'full' and 'marg', to pass the KDE bandwidth and number of samples) +/// \param[in] pgrid : parameter grid, if requested, to compute exact posterior +/// (can be empty) +/// \param[in] nburn : burn-in for MCMC to write to pchain +/// \param[in] nstep : thinning of MCMC to write to pchain +/// \param[in,out] pchain : thinned chain file with nburn and nstep applied, to be used for postprocessing +/// : if given as non-empty array, the MCMC is skipped, and only postprocessing is performed +/// \param[out] mapparam : MAP parameters +/// \param[out] datavar_map : MAP value of data variances +/// \param[out] pmean_map, pvar_map : MAP values of parameter means and variances +/// \param[out] fmean_map, fvar_map : MAP values of function predition (at xgrid) means and variances +/// \param[out] postave_datavar : posterior average of data variances +/// \param[out] p_postave_mean : posterior average of parameter mean +/// \param[out] p_postave_var : posterior average of parameter variance +/// \param[out] p_postvar_mean : posterior variance of parameter mean +/// \param[out] f_postave_mean : posterior average of function prediction mean +/// \param[out] f_postave_var : posterior average of function prediction variance +/// \param[out] f_postvar_mean : posterior variance of function prediction mean +/// \param[out] paramPCcfs : each column is a vector of parameter PC coefficients corresponding to an MCMC sample from pchain +/// the last column is the MAP value of parameter PC coefficients +void infer_model(Array1D< Array2D (*)(Array2D&, Array2D&, Array2D&, void *) > forwardFuncs, void* funcInfo, + string likType, + string priorType, double priora, double priorb, + Array2D& xdata,Array2D& ydata, Array2D& xgrid, + int dataNoiseInference, Array1D& datanoise_array, + int pdim,int order,Array1D& rndInd,Array2D& fixIndNom,string pdfType,string pcType, + int seed, int nmcmc, double mcmcgamma, bool optimflag, Array1D& chstart, Array1D& chsig, + double likParam, int likParam_int, + Array2D& pgrid,Array2D& pchain, int nburn, int nstep, + Array1D& mapparam, Array1D& datavar_map, + Array1D& pmean_map, Array1D& pvar_map, + Array1D& fmean_map, Array1D& fvar_map, + Array1D& postave_datavar, + Array1D& p_postave_mean, Array1D& p_postave_var, Array1D& p_postvar_mean, + Array2D& f_postsam_mean, Array1D& f_postave_mean, Array1D& f_postave_var, Array1D& f_postvar_mean, + Array2D& paramPCcfs); + +/// \brief Log-posterior function given a vector of parameters (chain state) and a void* set of auxiliary variables +double LogPosterior(Array1D& m, void* mypost_void); + + diff --git a/cpp/lib/infer/mrv.cpp b/cpp/lib/infer/mrv.cpp new file mode 100644 index 00000000..8c58cef1 --- /dev/null +++ b/cpp/lib/infer/mrv.cpp @@ -0,0 +1,292 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file mrv.cpp +/// \author K. Sargsyan 2016 - +/// \brief Multivariate random variable class + +#include +#include +#include + +#include "mrv.h" +#include "PCSet.h" +#include "error_handlers.h" +#include "arrayio.h" +#include "arraytools.h" + +#define SIG_MAX 10 + +// Constructor +Mrv::Mrv(int ndim,string pdfType, Array1D rndInd, int order,string pctype) +{ + // Set the appropriate variables + this->nDim_=ndim; + this->pdfType_=pdfType; + this->rndInd_=rndInd; + this->rDim_=this->rndInd_.Length(); + this->order_=order; + this->pcType_=pctype; + this->pcModel_ = new PCSet("NISP",this->order_,this->rDim_,this->pcType_,0.,1.); + this->nPC_=this->pcModel_->GetNumberPCTerms(); + + // Sanity check and reorder the indices of randomized parameters + if (this->rDim_>0){ + shell_sort(this->rndInd_); + assert(this->rndInd_(this->rDim_-1)nDim_); + } + + return; +} + + +// Parameterize the multivariate PC RV +// Does the bookkeeping, i.e. maps each parameter alpha to a physical parameter and PC order +int Mrv::Parametrize() +{ + // Counters + int i=0; + int pccounter=0; + + // Clear the result container + this->paramId_.Clear(); + this->pctermId_.Clear(); + + // Loop through all randomized parameters and fill in paramId and pctermId + for (int cur_rparam=0;cur_rparamrDim_;cur_rparam++){ + int rParamInd=this->rndInd_(cur_rparam); + while(iparamId_.PushBack(i); + this->pctermId_.PushBack(0); + i++; + } + pccounter++; + + // The PC PDF type dictates how the parameterization is done + if(this->pdfType_=="pct"){ + for (int j=0;jparamId_.PushBack(i); + this->pctermId_.PushBack(j); + } + } + else if(this->pdfType_=="pci"){ + for (int j=0;jparamId_.PushBack(i); + this->pctermId_.PushBack(j); + } + } + else if(this->pdfType_=="full"){ + for (int j=0;jnPC_;j++){ + this->paramId_.PushBack(i); + this->pctermId_.PushBack(j); + } + } + i++; + } + + // Fill the rest + while (inDim_){ + this->paramId_.PushBack(i); + this->pctermId_.PushBack(0); + i++; + } + + this->pDim_=this->paramId_.Length(); + + printf("\n Mapping of R.V. parameters: \n"); + for (int i=0;ipDim_;i++){ + printf("R.V. parameter %d is alpha_(%d,%d), i.e. Model parameter %d, PC term %d.\n",i,this->paramId_(i),this->pctermId_(i),this->paramId_(i),this->pctermId_(i)); + } + + return this->pDim_; +} + +// Get the bounds according to the invariance logic, +// i.e. the last randomized parameter has positive coefficients in higher-order terms +void Mrv::getBounds(Array1D& lower, Array1D& upper) +{ + lower.Resize(this->pDim_,-DBL_MAX); + upper.Resize(this->pDim_,DBL_MAX); + if(this->pdfType_=="pct"){ + + for (int ic=0;icpDim_;ic++){ + if(this->pctermId_(ic)!=0){ + upper(ic)=SIG_MAX; + if(this->paramId_(ic)==this->rndInd_(this->rDim_-1)) + lower(ic)=0.e0; + } + } + + } + else if(this->pdfType_=="pci"){ + + for (int ic=0;icpDim_;ic++){ + if(this->pctermId_(ic)!=0){ + upper(ic)=SIG_MAX; + lower(ic)=0.e0; + } + } + + } + else if(this->pdfType_=="full"){ + // No bounds for 'full' representation + } + + return; +} + +// Get matrix of PC coefficients given parameterization +// The matrix is convenient to work with and has dimensions npc-by-ndim +Array2D Mrv::getMultiPCcf(Array1D& rvParams) +{ + assert(rvParams.Length()==this->pDim_); + Array2D multiPCcf(this->nPC_,this->nDim_,0.e0); + + for (int ic=0;icpDim_;ic++) + multiPCcf(this->pctermId_(ic),this->paramId_(ic))=rvParams(ic); + + return multiPCcf; +} + +// Evaluate multivariate PC given germ samples and coefficient matrix +Array2D Mrv::evalMultiPC(Array2D& xiSam, Array2D& multiPCcf) +{ + int nsam=xiSam.XSize(); + assert(xiSam.YSize()==this->rDim_); + + Array2D multiPCSam(nsam,0); + for (int j=0;jnDim_;j++){ + Array1D pdfpccf; + getCol(multiPCcf,j,pdfpccf); + + Array1D samples_dim; + this->pcModel_->EvalPCAtCustPoints(samples_dim,xiSam, pdfpccf); + multiPCSam.insertCol(samples_dim,j); + } + + return multiPCSam; +} + +// Random sample of all parameters given a coefficient matrix +Array2D Mrv::mcParam(Array2D& multiPCcf, int nsam) +{ + Array2D xiSam(nsam,this->rDim_,0.e0); + this->pcModel_->DrawSampleVar(xiSam); + Array2D multiPCSam=this->evalMultiPC(xiSam,multiPCcf); + + return multiPCSam; +} + +// Get quadrature samples of all parameters given coefficient matrix +Array2D Mrv::quadParam(Array2D& multiPCcf) +{ + Array2D xiSam; + Array1D weights; + + this->pcModel_->GetQuadPointsWeights(xiSam, weights); + Array2D multiPCQuadSam=this->evalMultiPC(xiSam,multiPCcf); + + return multiPCQuadSam; +} + +// Propagate the multivariate RV with given coefficeints through a given function at given values x +Array2D Mrv::propNISP(Array2D (*forwardFcn)(Array2D&, Array2D&, Array2D&, void*), Array2D& fixindnom,void* funcinfo, Array2D& multiPCcf, Array2D& x) +{ + Array2D multiPCQuadSam=this->quadParam(multiPCcf); + int ns=multiPCQuadSam.XSize(); + + Array2D funcQuad=forwardFcn(multiPCQuadSam,x, fixindnom, funcinfo); + int nx=funcQuad.YSize(); + + Array2D funcCf(nPC_,0); + + for (int ix=0;ix funcQuad_ix; + getCol(funcQuad,ix,funcQuad_ix); + Array1D fcf; + this->pcModel_->GalerkProjection(funcQuad_ix,fcf); + funcCf.insertCol(fcf,ix); + } + + return funcCf; +} + +// Sample values of a given function given input coefficeint matrix +Array2D Mrv::propMC(Array2D (*forwardFcn)(Array2D&, Array2D&, Array2D&, void*), Array2D& fixindnom,void* funcinfo,Array2D& multiPCcf, Array2D& x,int nsam) +{ + Array2D multiPCSam=this->mcParam(multiPCcf, nsam); + int ns=multiPCSam.XSize(); + + + Array2D funcSam=forwardFcn(multiPCSam,x, fixindnom, funcinfo); + + return funcSam; +} + +// Compute moments given coefficent matrix +void Mrv::computeMoments(Array2D& funcCf, Array1D& fcnMean,Array1D& fcnVar,bool covFlag, Array2D& fcnCov) +{ + int nx=funcCf.YSize(); + fcnMean.Resize(nx); + fcnVar.Resize(nx); + if (covFlag) + fcnCov.Resize(nx,nx,0.e0); + + for (int ix=0;ix fcf; + getCol(funcCf,ix,fcf); + fcnMean(ix)=this->pcModel_->ComputeMean(fcf); + + Array1D varfrac; + double var=this->pcModel_->ComputeVarFrac(fcf,varfrac); + fcnVar(ix)=var; + if (covFlag){ + fcnCov(ix,ix)=var; + + for (int jx=0;jx fcf_; + getCol(funcCf,jx,fcf_); + Array1D varfrac_; + double var_=this->pcModel_->ComputeVarFrac(fcf_,varfrac_); + double cov=0.0; + for (int k=1;k. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file mrv.h +/// \author K. Sargsyan 2016 - +/// \brief Header for multivariate random variable class + +#ifndef MRV_H_SEEN +#define MRV_H_SEEN + +#include "Array1D.h" +#include "Array2D.h" +#include "PCSet.h" + +#include +#include +#include +#include + +using namespace std; // needed for python string conversion + +/// \class Mrv: class for multivariate RV parameterized by PC expansions + +class Mrv { +public: + + /// \brief Constructor with dimensionality, pdftype, randomized parameter indices, order, and pctype + Mrv(int ndim,string pdfType, Array1D rndInd, int order,string pctype); + /// \brief Destructor + ~Mrv() {} + + + /// \brief Parameterization bookkeeping (i.e. alpha corresponds to certain parameter lambda and certain PC term) + int Parametrize(); + + /// \brief Get bounds on parameters + /// \note Useful when some parameters forced to be positive to make use of invariance + void getBounds(Array1D& lower, Array1D& upper); + + /// \brief Get dimensionailty of parameterization + int getPDim(){ return this->pDim_;} + + /// \brief Given parameters of representation, fold them in a 2d-array of PC coefficients for convenience + Array2D getMultiPCcf(Array1D& rvParams); + /// \brief Evaluate at multivariate PC at given germ samples for given coefficient matrix + Array2D evalMultiPC(Array2D& xiSam, Array2D& multiPCcf); + /// \brief Random-sample all parameters given coefficient matrix + Array2D mcParam(Array2D& multiPCcf, int nsam); + /// \brief Quadrature-sample all parameters given coefficient matrix + Array2D quadParam(Array2D& multiPCcf); + /// \brief Propagate the multivariate RV with given coefficeints through a given function at given values x + Array2D propNISP(Array2D (*forwardFcn)(Array2D&, Array2D&, Array2D&, void*), Array2D& fixindnom,void* funcinfo, Array2D& multiPCcf, Array2D& x); + /// \brief Sample values of a given function given input coefficeint matrix + Array2D propMC(Array2D (*forwardFcn)(Array2D&, Array2D&, Array2D&, void*), Array2D& fixindnom,void* funcinfo,Array2D& multiPCcf, Array2D& x,int nsam); + /// \brief Compute moments given coefficent matrix + void computeMoments(Array2D& funcCf, Array1D& fcnMean,Array1D& fcnStd,bool covFlag, Array2D& fcnCov); + + /// \brief Get PC term ID + void getPCTermId(Array1D& pctermid){pctermid=pctermId_; return;} + +private: + /// \brief Randomized parameters indices + Array1D rndInd_; + /// \brief For a given parameterization, id the corresponding physical parameter lambda + Array1D paramId_; + /// \brief For a given parameterization, id the PC term/order for the corresponding parameter representation + Array1D pctermId_; + + /// \brief PDF type ('pct', 'pci' or 'full') + string pdfType_; + /// \brief PC type (see pce library for options) + string pcType_; + /// \brief Number of parameters in alpha parameterization + int pDim_; + /// \brief Number of randomized parameters + int rDim_; + /// \brief Number of physical parameters lambda + int nDim_; + /// \brief Order of function PC representation + int order_; + /// \brief Number of PC parameters for each independent component + int nPC_; + /// \brief Pointer to the corresponding PC object + PCSet* pcModel_; + + + +}; + +/*******************************************************************/ +/*******************************************************************/ +/*******************************************************************/ + + +#endif /* MRV_H_SEEN */ diff --git a/cpp/lib/infer/post.cpp b/cpp/lib/infer/post.cpp new file mode 100644 index 00000000..e079f808 --- /dev/null +++ b/cpp/lib/infer/post.cpp @@ -0,0 +1,751 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file post.cpp +/// \author K. Sargsyan 2016 - +/// \brief Posterior computation class + +#include +#include +#include + +#include "func.h" +#include "mrv.h" +#include "post.h" + +#include "tools.h" + +#include "PCSet.h" +#include "error_handlers.h" +#include "arrayio.h" +#include "arraytools.h" + +#define SIG_MAX 10 + + +// Constructor +Post::Post() +{ + this->extraInferredParams_=0; +} + + +// Set the x- and y-data +void Post::setData(Array2D& xdata,Array2D& ydata) +{ + this->xData_=xdata; + this->yData_=ydata; + + this->nData_=this->xData_.XSize(); + this->xDim_=this->xData_.YSize(); + assert(this->nData_==this->yData_.XSize()); + this->nEach_=this->yData_.YSize(); + + this->yDatam_.Resize(this->nData_,0.e0); + for(int i=0;inData_;i++){ + for(int j=0;jnEach_;j++){ + this->yDatam_(i)+=this->yData_(i,j); + } + this->yDatam_(i)/=this->nEach_; + } + + + return; +} + +// Set the magnitude of data noise +void Post::setDataNoise(Array1D& sigma) +{ + this->inferDataNoise_=false; + this->dataNoiseLogFlag_=false; + + this->dataNoiseSig_=sigma; + + this->extraInferredParams_+=0; + + return; +} + +// Indicate inference of data noise stdev +void Post::inferDataNoise() +{ + + this->inferDataNoise_=true; + this->dataNoiseLogFlag_=false; + + this->extraInferredParams_+=1; + + return; +} + +// Indicate inference of log of data noise stdev +void Post::inferLogDataNoise() +{ + this->inferDataNoise_=true; + this->dataNoiseLogFlag_=true; + + this->extraInferredParams_+=1; + return; +} + +// Get data noise, whether inferred or fixed +Array1D Post::dataSigma(double m_last) +{ + Array1D sig; + if (inferDataNoise_){ + if (dataNoiseLogFlag_){ + sig.Resize(this->nData_,exp(m_last)); + } + else { + sig.Resize(this->nData_,m_last); + } + } + else + sig=this->dataNoiseSig_; + + + + return sig; +} + +// Set a pointer to the forward model f(p,x) +void Post::setModel(Array1D< Array2D (*)(Array2D&, Array2D&, Array2D&, void *) > forwardFuncs, Array2D& fixindnom, void* funcInfo) +{ + this->forwardFcns_=forwardFuncs; + this->ncat_=forwardFuncs.Length(); + this->fixIndNom_=fixindnom; + this->funcinfo_=funcInfo; + return; +} + +// Set model input parameters' randomization scheme +void Post::setModelRVinput(int pdim,int order,Array1D& rndInd,string pdfType,string rvpcType) +{ + + this->pDim_=pdim; + this->rndInd_=rndInd; + this->pdfType_=pdfType; + this->rvpcType_=rvpcType; + + this->Mrv_ = new Mrv(this->pDim_,this->pdfType_, this->rndInd_,order,this->rvpcType_); + this->chDim_=this->Mrv_->Parametrize()+this->extraInferredParams_+this->ncat_-1; + this->Mrv_->getBounds(this->lower_,this->upper_); + + for (int i=0;incat_-1;i++){ + this->lower_.PushBack(0.0); + this->upper_.PushBack(1.0); + } + + if (inferDataNoise_ and dataNoiseLogFlag_){ + this->lower_.PushBack(-SIG_MAX); + this->upper_.PushBack(SIG_MAX); + } + if (inferDataNoise_ and ~dataNoiseLogFlag_){ + this->lower_.PushBack(0.e0); + this->upper_.PushBack(SIG_MAX); + } + + + return; + +} + +// Get the dimensionailty of the posterior function +int Post::getChainDim() +{ + return chDim_; +} + +// Set the prior type and its parameters +void Post::setPrior(string priorType, double priora, double priorb) +{ + this->priorType_=priorType; + this->priora_=priora; + this->priorb_=priorb; + + return; +} + +// Evaluate log-prior +double Post::evalLogPrior(Array1D& m) +{ + double pi=4.*atan(1.); + + double logPrior=0.0; + if (this->priorType_=="uniform"){ + + Array1D pctermid; + this->Mrv_->getPCTermId(pctermid); + + for (int ic=0;icpriora_ or m(ic)>this->priorb_) + return -1.e80; + } + + + logPrior=0.0; + } + + else if (this->priorType_=="uniform_LUpci"){ + + Array1D pctermid; + this->Mrv_->getPCTermId(pctermid); + + for (int ic=0;icpriora_ or m(ic)+m(ic+1)>this->priorb_) + return -1.e80; + } + else{ + if (m(ic)priora_ or m(ic)>this->priorb_) + return -1.e80; + } + } + } + + + + logPrior=0.0; + } + + else if (this->priorType_=="normal"){ + + Array1D pctermid; + this->Mrv_->getPCTermId(pctermid); + + for (int ic=0;icpriorb_; + double mism=m(ic)-this->priora_; + logPrior-=( 0.5*mism*mism/(ps*ps) + 0.5*log(2.*pi) + log(ps) ); + } + } + + else if (this->priorType_=="inverse"){ + + Array1D pctermid; + this->Mrv_->getPCTermId(pctermid); + + for (int ic=0;icpriora_ or m(ic)>this->priorb_) + return -1.e80; + if (pctermid(ic)!=0) + logPrior-=log(fabs(m(ic))); + } + } + + else if (this->priorType_=="wishart"){ + + double nu = this->pDim_ + this->priora_; + double theta = this->priorb_; + + + + bool covFlag = true; + Array1D parMean,parVar; + Array2D parCov; + this->momParam(m, parMean, parVar, covFlag, parCov); + + //Array2D paramPCcf=getParamPCcf(m);//npc x pdim + //this->Mrv_->computeMoments(paramPCcf, fcnMean,fcnVar,covFlag, fcnCov); //funccf is npc x nx + + + logPrior = 0.5 * this->pDim_ * nu + 0.5 * (nu - pDim_ - 1.0) * logdeterm(parCov) - theta * trace(parCov); + + //double a = 0.5*(nu-this->pDim_+1.0); + //double b = theta; + //double logprior2=a*log(b) + (a-1.)*log(m(1)) - b*m(1) - lgamma(a) + } + + else if (this->priorType_=="jeffreys"){ + + + + + bool covFlag = true; + Array1D parMean,parVar; + Array2D parCov; + this->momParam(m, parMean, parVar, covFlag, parCov); + + + logPrior = - 0.5 * (this->pDim_ +1.) * logdeterm(parCov); + + } + else { + cout << "Prior type " << this->priorType_ << " unrecognized. Exiting." << endl; + exit(1); + } + + return logPrior; +} + +// Extract parameter PC coefficients from a posterior input +Array2D Post::getParamPCcf(Array1D& m) +{ + Array1D modelRVparams; + for (int i=0;iextraInferredParams_-this->ncat_+1;i++) + modelRVparams.PushBack(m(i)); + + Array2D paramPCcf=this->Mrv_->getMultiPCcf(modelRVparams); + + return paramPCcf; +} + +// Sample model parameters given posterior input +Array2D Post::samParam(Array1D& m, int ns) +{ + Array2D paramPCcf=this->getParamPCcf(m); + + Array2D paramSamples=this->Mrv_->mcParam(paramPCcf, ns); + + return paramSamples; +} + +// Get moments of parameters given posterior input +void Post::momParam(Array1D& m, Array1D& parMean, Array1D& parVar, bool covFlag, Array2D& parCov) +{ + + Array2D paramPCcf=this->getParamPCcf(m); + +// Array2D paramSamples=this->Mrv_->samParam(paramPCcf, ns); + this->Mrv_->computeMoments(paramPCcf, parMean,parVar,covFlag, parCov); + + return; +} + +// Sample forward function at a given grid for given posterior input +Array2D Post::samForwardFcn(Array2D (*forwardFunc)(Array2D&, Array2D&, Array2D&, void*),Array1D& m, Array2D& xgrid, int ns) +{ + + Array2D paramPCcf=this->getParamPCcf(m); + + Array2D funcSam=this->Mrv_->propMC(forwardFunc, this->fixIndNom_,this->funcinfo_,paramPCcf, xgrid,ns); + + + return funcSam; +} + +// Get moments of forward function at a given grid for given posterior input +void Post::momForwardFcn(Array2D (*forwardFunc)(Array2D&, Array2D&, Array2D&, void*),Array1D& m, Array2D& xgrid, Array1D& fcnMean, Array1D& fcnVar, bool covFlag, Array2D& fcnCov) +{ + + Array2D paramPCcf=this->getParamPCcf(m); + + Array2D funcCf=this->Mrv_->propNISP(forwardFunc, this->fixIndNom_,this->funcinfo_,paramPCcf, xgrid); + + this->Mrv_->computeMoments(funcCf, fcnMean,fcnVar,covFlag, fcnCov); + return; +} + +// Get moments of composite forward function at a given grid for given posterior input +void Post::momForwardFcn(Array1D& m, Array2D& xgrid, Array1D& fcnMean, Array1D& fcnVar, bool covFlag, Array2D& fcnCov) +{ + Array2D paramPCcf=this->getParamPCcf(m); + int nxgrid=xgrid.XSize(); + fcnMean.Resize(nxgrid,0.e0); + fcnVar.Resize(nxgrid,0.e0); + fcnCov.Resize(nxgrid,nxgrid,0.e0); + + Array1D weights(this->ncat_,1.e0); + for (int i=0;incat_-1;i++){ + weights(i)=m(m.Length()-extraInferredParams_-this->ncat_+1+i); + weights(this->ncat_-1)-=weights(i); + } + + Array1D< Array1D > fcnMeans(0); + Array1D< Array1D > fcnVars(0); + Array1D< Array2D > fcnCovs(0); + + for (int i=0;incat_;i++){ + Array2D funcCf=this->Mrv_->propNISP(this->forwardFcns_(i), this->fixIndNom_,this->funcinfo_,paramPCcf, xgrid); + Array1D fcnMean_i,fcnVar_i; + Array2D fcnCov_i; + this->Mrv_->computeMoments(funcCf, fcnMean_i,fcnVar_i,covFlag, fcnCov_i); + for (int j=0;jncat_;i++){ + fcnVar(j)+=weights(i)*fcnVars(i)(j); + fcnVar(j)+=weights(i)*fcnMeans(i)(j)*fcnMeans(i)(j); + } + fcnVar(j)-=fcnMean(j)*fcnMean(j); + } + + if (covFlag){ + printf("Post:momForwardFcn(): Covariance computation not implemented for categorical variables. Exiting."); + exit(1); + } + + + + return; +} +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate full log-likelihood +double Lik_Full::evalLogLik(Array1D& m) +{ + + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + + Array2D ydatat; + transpose(this->yData_,ydatat); + + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + + // TODO assumes one function + Array2D funcSam=samForwardFcn(this->forwardFcns_(0),m, this->xData_, this->nsam_); + + Array2D dataNoiseSam(this->nsam_,this->nData_); + generate_normal(dataNoiseSam, time(NULL)); + Array2D tmp; + Array2D diagsig=diag(dataSig); + prodAlphaMatMat(dataNoiseSam,diagsig,1.0,tmp); + addinplace(funcSam,tmp); + + Array1D weight(this->nsam_,1.e0); + Array1D dens(this->nEach_,0.e0); + Array1D bdw(this->nData_,this->bdw_); + if (this->bdw_<=0) + get_opt_KDEbdwth(funcSam,bdw); + //cout << "BD " << bdw(0) << " " << bdw(1) << endl; + getPdf_figtree(funcSam,ydatat,bdw,dens, weight); + + + double logLik=0.; + for (int ie=0;ienEach_;ie++){ + //cout << dens(ie) << endl; + //ldens2(ie)=-(data(ie,0)-mu)*(data(ie,0)-mu)/(2.*std*std)-log(std*sqrt(2*pi)) ; + if (dens(ie)==0) + return -1.e80; + else + logLik +=log(dens(ie)); + } + + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate marginal log-likelihood +double Lik_Marg::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + // TODO Assumes one function + Array2D funcSam=samForwardFcn(this->forwardFcns_(0),m, this->xData_, this->nsam_); + + Array2D ydatat; + transpose(this->yData_,ydatat); + + + Array2D dataNoiseSam(this->nsam_,this->nData_); + + generate_normal(dataNoiseSam, time(NULL)); + Array2D tmp; + Array2D diagsig=diag(dataSig); + prodAlphaMatMat(dataNoiseSam,diagsig,1.0,tmp); + addinplace(funcSam,tmp); + + double logLik=0.; + + for (int ix=0;ixnData_;ix++){ + Array2D funcSam_ix(this->nsam_,1); + Array2D ydatat_ix(this->nEach_,1); + for(int is=0;isnsam_;is++) + funcSam_ix(is,0)=funcSam(is,ix); + for(int ie=0;ienEach_;ie++) + ydatat_ix(ie,0)=ydatat(ie,ix); + Array1D weight(this->nsam_,1.e0); + Array1D dens(this->nEach_,0.e0); + Array1D bdw(1,this->bdw_); + if (this->bdw_<=0) + get_opt_KDEbdwth(funcSam_ix,bdw); + getPdf_figtree(funcSam_ix,ydatat_ix,bdw,dens, weight); + + for(int ie=0;ienEach_;ie++){ + if (dens(ie)==0) + return -1.e80; + else + logLik +=log(dens(ie)); + } + + + } + + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate mvn log-likelihood +double Lik_MVN::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + + Array1D fcnMean,fcnVar; + Array2D fcnCov; + momForwardFcn(m, this->xData_, fcnMean, fcnVar, true, fcnCov); + + + Array2D fcnCovN=fcnCov; + + for (int i=0;inData_;i++) + fcnCovN(i,i)+=(pow(dataSig(i),2.)+pow(this->nugget_,2.)); + + double logLik=evalLogMVN(this->yDatam_,fcnMean,fcnCovN); + + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate gaussian-marginal log-likelihood +double Lik_GausMarg::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + + Array1D fcnMean,fcnVar; + Array2D fcnCov; + // TODO assumes one function + momForwardFcn(m, this->xData_, fcnMean, fcnVar, false, fcnCov); + + Array1D dataVar=dotmult(dataSig,dataSig); + + double logLik=0.; + for (int ix=0;ixnData_;ix++){ + double err=fabs(this->yDatam_(ix)-fcnMean(ix)); + logLik-= ( 0.5*err*err/(fcnVar(ix)+dataVar(ix)) + 0.5*log(2.*pi) + 0.5*log(fcnVar(ix)+dataVar(ix)) ); + } + + return logLik; +} + + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate ABC log-likelihood +double Lik_ABC::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + + Array1D fcnMean,fcnVar; + Array2D fcnCov; + momForwardFcn(m, this->xData_, fcnMean, fcnVar, false, fcnCov); + + + Array1D dataVar=dotmult(dataSig,dataSig); + + + //////// + double alpha=1.; + double norm=0.0; + double logLik=0.; + for (int ix=0;ixnData_;ix++){ + double err=fabs(this->yDatam_(ix)-fcnMean(ix)); + norm+=pow(err,2.); + norm+=pow(alpha*err-sqrt(fcnVar(ix)+dataVar(ix)),2.); + } + logLik=-(0.5/(this->abceps_*this->abceps_))*(norm)-0.5*log(2.*pi)-log(this->abceps_); + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate ABC-mean log-likelihood +double Lik_ABCm::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + //Array1D dataSig=this->dataSigma(m(m.Length()-1)); + + Array1D fcnMean,fcnVar; + Array2D fcnCov; + momForwardFcn(m, this->xData_, fcnMean, fcnVar, false, fcnCov); + + double norm=0.0; + double logLik=0.; + for (int ix=0;ixnData_;ix++){ + double err=fabs(this->yDatam_(ix)-fcnMean(ix)); + norm+=pow(err,2.); + } + logLik=-(0.5/(this->abceps_*this->abceps_))*(norm)-0.5*log(2.*pi)-log(this->abceps_); + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate Kennedy-O'Hagan log-likelihood +double Lik_Koh::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + double modelSig=m(m.Length()-2); + + Array1D fcnMean,fcnVar; + Array2D fcnCov; + momForwardFcn(m, this->xData_, fcnMean, fcnVar, false, fcnCov); + + + Array2D fcnCovKoh(this->nData_,this->nData_); + + for (int i=0;inData_;i++){ + fcnCovKoh(i,i)=pow(modelSig,2.0); + for (int j=0;jnData_;j++){ + double norm=0.0; + for (int k=0;kxDim_;k++) + norm+=pow(xData_(i,k)-xData_(j,k),2.0); + norm=sqrt(norm); + fcnCovKoh(i,j)=pow(modelSig,2.0)*exp(-0.5*pow(norm/this->corLength_,2.0)); + fcnCovKoh(j,i)=fcnCovKoh(i,j); + } + } + + + for (int i=0;inData_;i++) + fcnCovKoh(i,i)+=(pow(dataSig(i),2.)); + + double logLik=evalLogMVN(this->yDatam_,fcnMean,fcnCovKoh); + + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ + +// Evaluate classical log-likelihood +double Lik_Classical::evalLogLik(Array1D& m) +{ + for (int ic=0;iclower_(ic) or m(ic)>this->upper_(ic)){ + return -1.e+80; + } + } + + double pi=4.*atan(1.); + Array1D dataSig=this->dataSigma(m(m.Length()-1)); + + Array1D fcnMean,fcnVar; + Array2D fcnCov; + momForwardFcn(m, this->xData_, fcnMean, fcnVar, false, fcnCov); + //or fcnMean=samForwardFcn(this->forwardFcns_(0),m, this->xData_, 1);// assuming one function + + + double logLik=0.; + for (int ix=0;ixnData_;ix++){ + for (int ie=0;ienEach_;ie++){ + double err=fabs(this->yData_(ix,ie)-fcnMean(ix)); + logLik-= ( 0.5*err*err/(dataSig(ix)*dataSig(ix)) + 0.5*log(2.*pi) + log(dataSig(ix)) ); + } + } + + + return logLik; +} + +/****************************************************************************************/ +/****************************************************************************************/ +/****************************************************************************************/ diff --git a/cpp/lib/infer/post.h b/cpp/lib/infer/post.h new file mode 100644 index 00000000..a06390b9 --- /dev/null +++ b/cpp/lib/infer/post.h @@ -0,0 +1,327 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file post.h +/// \author K. Sargsyan 2016 - +/// \brief Header for the posterior computation class + +#ifndef POST_H_SEEN +#define POST_H_SEEN + +#include "Array1D.h" +#include "Array2D.h" +#include "mrv.h" + +#include +#include +#include +#include + +using namespace std; // needed for python string conversion + +/// \class Post: class for posterior evaluation with various likelihood and prior options + +class Post { +public: + + /// \brief Constructor + Post(); + /// \brief Destructor + ~Post() {} + + /// \brief Set the x- and y-data + void setData(Array2D& xdata,Array2D& ydata); + /// \brief Set the magnitude of data noise + void setDataNoise(Array1D& sigma); + /// \brief Indicate inference of data noise stdev + void inferDataNoise(); + /// \brief Indicate inference of log of data noise stdev + void inferLogDataNoise(); + /// \brief Get data noise, whether inferred or fixed + Array1D dataSigma(double m_last); + /// \brief Set a pointer to the forward model f(p,x) + void setModel(Array1D< Array2D (*)(Array2D&, Array2D&, Array2D&, void *) > forwardFuncs, Array2D& fixindnom, void* funcInfo); + /// \brief Set model input parameters' randomization scheme + void setModelRVinput(int pdim, int order, Array1D& rndInd,string pdfType,string pcType); + /// \brief Get the dimensionailty of the posterior function + int getChainDim(); + /// \brief Set the prior type and its parameters + void setPrior(string priorType, double priora, double priorb); + /// \brief Evaluate log-prior + double evalLogPrior(Array1D& m); + /// \brief Extract parameter PC coefficients from a posterior input + Array2D getParamPCcf(Array1D& m); + /// \brief Sample model parameters given posterior input + Array2D samParam(Array1D& m, int ns); + /// \brief Get moments of parameters given posterior input + void momParam(Array1D& m, Array1D& parMean, Array1D& parVar, bool covFlag, Array2D& parCov); + /// \brief Sample forward function at a given grid for given posterior input + Array2D samForwardFcn(Array2D (*forwardFunc)(Array2D&, Array2D&, Array2D&, void*),Array1D& m, Array2D& xgrid, int ns); + /// \brief Get moments of forward function at a given grid for given posterior input + void momForwardFcn(Array2D (*forwardFunc)(Array2D&, Array2D&, Array2D&, void*),Array1D& m, Array2D& xgrid, Array1D& fcnMean, Array1D& fcnVar, bool covflag, Array2D& fcnCov); + void momForwardFcn(Array1D& m, Array2D& xgrid, Array1D& fcnMean, Array1D& fcnVar, bool covflag, Array2D& fcnCov); + /// \brief Dummy evaluation of log-likelihood + virtual double evalLogLik(Array1D& m){return 0;}; + + +protected: + /// \brief xdata + Array2D xData_; + /// \brief ydata + Array2D yData_; + /// \brief ydata averaged per measurement (in case more than one y is given for each x) + Array1D yDatam_; + /// \brief Number of data points + int nData_; + /// \brief Number of samples at each input + int nEach_; + /// \brief Dimensionality of x-space + int xDim_; + /// \brief Dimensionality of parameter space (p-space) + int pDim_; + /// \brief Dimensionality of posterior input + int chDim_; + /// \brief Flag for data noise inference + bool inferDataNoise_; + /// \brief Flag to check if data noise logarithm is used + bool dataNoiseLogFlag_; + /// \brief Data noise stdev + Array1D dataNoiseSig_; + /// \brief Pointer to the forward function f(p,x) + //Array2D (*forwardFcn_)(Array2D&, Array2D&, Array2D&, void*); + Array1D< Array2D (*)(Array2D&, Array2D&, Array2D&, void *) > forwardFcns_; + /// \brief Auxiliary information for function evaluation + void* funcinfo_; + /// \brief Number of extra inferred parameters, such as data noise or Koh variance + int extraInferredParams_; + /// \brief Number of categories + int ncat_; + + /// \brief Pointer to a multivariate PC RV object + Mrv * Mrv_; + /// \brief Indices of randomized inputs + Array1D rndInd_; + /// \brief Indices and nominal values for fixed inputs + Array2D fixIndNom_; + /// \brief Lower and upper bounds on parameters + Array1D lower_,upper_; + /// \brief Input parameter PDF type + string pdfType_; + /// \brief PC type parameter for the r.v. + string rvpcType_; + /// \brief Prior type + string priorType_; + /// \brief Prior parameter #1 + double priora_; + /// \brief Prior parameter #2 + double priorb_; + + private: + + /// \brief Verbosity level + int verbosity_; + +}; + +/*******************************************************************/ +/*******************************************************************/ +/*******************************************************************/ + +/// \class Lik_Full +/// \brief Derived class for full likelihood +class Lik_Full: public Post { +public: + /// \brief Constructor given KDE bandwidth and sample size + Lik_Full(double bdw,int nsam){this->bdw_=bdw; this->nsam_=nsam; return;} + /// \brief Destructor + ~Lik_Full(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + + private: + /// \brief KDE bandwidth + double bdw_; + /// \brief KDE sample size + int nsam_; +}; + +/*******************************************************************/ +/*******************************************************************/ +/*******************************************************************/ + +/// \class Lik_Marg +/// \brief Derived class for marginal likelihood +class Lik_Marg: public Post { +public: + /// \brief Constructor given KDE bandwidth and sample size + Lik_Marg(double bdw,int nsam){this->bdw_=bdw; this->nsam_=nsam; return;} + /// \brief Destructor + ~Lik_Marg(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + + private: + /// \brief KDE bandwidth + double bdw_; + /// \brief KDE sample size + int nsam_; + +}; + +/*******************************************************************/ +/*******************************************************************/ +/*******************************************************************/ + +/// \class Lik_MVN +/// \brief Derived class for mvn likelihood +class Lik_MVN: public Post { +public: + /// \brief Constructor given fiagonal nugget + Lik_MVN(double nugget){this->nugget_=nugget; return;} + /// \brief Destructor + ~Lik_MVN(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + + private: + /// \brief Nugget size + double nugget_; + +}; + +/*******************************************************************/ + +/// \class Lik_GausMarg +/// \brief Derived class for gaussian-marginal likelihood +class Lik_GausMarg: public Post { +public: + /// \brief Constructor + Lik_GausMarg(){return;} + /// \brief Destructor + ~Lik_GausMarg(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + +}; + +/*******************************************************************/ + +/// \class Lik_GausMargD +/// \brief Derived class for gaussian-marginal likelihood with discrete parameter +class Lik_GausMargD: public Post { +public: + /// \brief Constructor + Lik_GausMargD(){return;} + /// \brief Destructor + ~Lik_GausMargD(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + +}; + +/*******************************************************************/ + +/// \class Lik_ABC +/// \brief Derived class for ABC likelihood +class Lik_ABC: public Post { +public: + /// \brief Constructor given ABC epsilon + Lik_ABC(double eps){this->abceps_=eps; return;} + /// \brief Destructor + ~Lik_ABC(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + +private: + /// \brief ABC epsilon + double abceps_; + +}; + +/*******************************************************************/ + +/// \class Lik_ABCm +/// \brief Derived class for ABC-mean likelihood +class Lik_ABCm: public Post { +public: + /// \brief Constructor given ABC epsilon + Lik_ABCm(double eps){this->abceps_=eps; return;} + /// \brief Destructor + ~Lik_ABCm(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + +private: + /// \brief ABC epsilon + double abceps_; + +}; + +/*******************************************************************/ + +/// \class Lik_Koh +/// \brief Derived class for Kennedy-O'Hagan likelihood +class Lik_Koh: public Post { +public: + /// \brief Constructor given correlation length + Lik_Koh(double corLength){ this->extraInferredParams_=1;this->corLength_=corLength; return;} + /// \brief Destructor + ~Lik_Koh(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); +private: + double corLength_; + +}; + +/*******************************************************************/ + +/// \class Lik_Classical +/// \brief Derived class for classical likelihood +class Lik_Classical: public Post { +public: + /// \brief Constructor + Lik_Classical(){ return;} + /// \brief Destructor + ~Lik_Classical(){}; + + /// \brief Evaluate log-likelihood + double evalLogLik(Array1D& m); + + +}; + +/*******************************************************************/ + +#endif /* POST_H_SEEN */ diff --git a/cpp/lib/kle/CMakeLists.txt b/cpp/lib/kle/CMakeLists.txt new file mode 100644 index 00000000..1199e993 --- /dev/null +++ b/cpp/lib/kle/CMakeLists.txt @@ -0,0 +1,18 @@ + +SET(kle_HEADERS + kle.h + ) + +add_library(uqtkkle kle.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) + +include_directories (../../../dep/lapack) + +# Install the library +INSTALL(TARGETS uqtkkle DESTINATION lib) + +# Install the header files +INSTALL(FILES ${kle_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/kle/kle.cpp b/cpp/lib/kle/kle.cpp new file mode 100644 index 00000000..3a25b4f0 --- /dev/null +++ b/cpp/lib/kle/kle.cpp @@ -0,0 +1,347 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file kldecompuni.cpp +/// \author B. Debusschere, K. Sargsyan, C. Safta, 2007 - +/// \brief Karhunen-Loeve decomposition class + +#include +#include "kle.h" +#include "deplapack.h" +#include "error_handlers.h" + +KLDecompUni::KLDecompUni(const Array1D& tSamples) +{ + // Initializations + this->Init() ; + + const size_t n_t = tSamples.XSize(); // Number of time samples, which defines overall dimensions + + // Properly size arrays for matrix and weights, which are independent of the + // number of KL modes requested. + whcwh_.Resize(n_t,n_t,0.e0); + w_. Resize(n_t, 0.e0); + wh_. Resize(n_t, 0.e0); + + // Compute the weights for Nystrom's method for Fredholm integral equation solution + // using the trapezoidal rule as the quadrature rule + w_(0) = (tSamples(1)-tSamples(0))/2.e0; + for(size_t i=1; i < n_t-1; i++){ + w_(i) = (tSamples(i+1)-tSamples(i-1))/2.e0; + } + w_(n_t-1) = (tSamples(n_t-1)-tSamples(n_t-2))/2.e0; + + // Get the square roots of these weights + for( size_t i=0; i < n_t; i++ ){ + wh_(i) = sqrt(w_(i)); + } + +} + +KLDecompUni::KLDecompUni() +{ + + // Initializations + this -> Init() ; + +} + +void KLDecompUni::Init() +{ + + // Initializations + decomposed_ = false; + + // settings for the LAPACK eigensolver + jobz_ = 'V' ; // get eigenvalues and eigenvectors + eigRange_ = 'I' ; // get eigenvalues within a given range of indices (from smaller to larger) + uplo_ = 'U' ; // upper triangular storage + vl_ = 0.e0; // not used + vu_ = 1.e0; // not used + absTol_ = 0.e0; // let routine determine appropriate tolerance + +} + +void KLDecompUni::SetWeights(const Array1D &weights) +{ + + const int npts = weights.XSize(); // Number of time samples, which defines overall dimensions + this->SetWeights(weights.GetConstArrayPointer(), npts); + + return ; + +} + +void KLDecompUni::SetWeights(const double *weights, const int npts) +{ + + const size_t n_t = npts; // Number of time samples, which defines overall dimensions + + w_.Resize(npts); + for ( size_t i=0;i& corr, const int &nKL) { + + return (this->decompose(corr.GetConstArrayPointer(), nKL)); + +} + +int KLDecompUni::decompose(const double *corr, const int &nKL) { + + const size_t n_t = whcwh_.XSize(); // dimension (rank) of the matrix, which determines + // max # of eigenvalues + + // Set the range of indices of the eigenvalues we look for (in ascending order) + // to get the largest nKL eigenvalues + const size_t one = 1; + il_ = max(one, n_t - nKL + one); + iu_ = n_t; + + // Populate the upper triangular part of the matrix, with each entry being + // \sqrt{w(i)} C(i,j) \sqrt{w(j)} + // This needs to be done every time we call the eigenvalue solver as this solver + // destroys the matrix entries. + for(size_t i=0; i < n_t; i++){ + for(size_t j = i; j < n_t; j++){ + whcwh_(i,j) = wh_(i)*corr[j*n_t+i]*wh_(j); + } + } + + // Set the dimensions of the arrays that will hold the eigenvalues and + // eigenvectors and reset all elements to 0.e0 + eig_values_.Resize(n_t, 0.e0); + KL_modes_. Resize(n_t,nKL,0.e0); + + // Work arrays + Array1D work_eigval(n_t, 0.e0); // Temporary storage of eigenvalues + Array2D work_eigvec(n_t,nKL,0.e0); // Temporary storage of eigenvectors + + int lwork = 10 * n_t; // size of work array (see LAPACK routine dsyevx.f for more info) + Array1D work(lwork,0.e0); // double precision work array + Array1D iwork(5*n_t,0); // integer work array + + ifail_.Resize(n_t,0); // on output: contains indices of eigenvectors that failed to converge + eig_info_ = 0; // info on success of the eigenvector solutions + + int n_eig = 0; // on output: has number of eigenvalues that were obtained + int n_t_int=n_t; + + // Call the eigenproblem solver + FTN_NAME(dsyevx)(&jobz_, &eigRange_, &uplo_, &n_t_int, whcwh_.GetArrayPointer(), + &n_t_int, &vl_, &vu_, &il_, &iu_, + &absTol_, &n_eig, work_eigval.GetArrayPointer(), + work_eigvec.GetArrayPointer(), &n_t_int, + work.GetArrayPointer(), &lwork, iwork.GetArrayPointer(), + ifail_.GetArrayPointer(), &eig_info_); + + // Set the decomposed flag if successful eigenvalue solve + if ( eig_info_ == 0 ){ + decomposed_ = true; + } else { + std::string err_message = "Something in the eigensolve went wrong. Check error code: "; + err_message += eig_info_; + err_message += " in the LAPACK routine dsyevx.f"; + throw Tantrum(err_message); + } + + // Reverse the order in the array with eigenvalues so that they are ordered + // in descending order (LAPACK dsyevx returns them in ascending order) + for(size_t i=0; i <(size_t) n_eig; i++){ + eig_values_(i) = work_eigval(n_eig-1-i); + } + + // Rearrange the eigenvectors accordingly and scale them with the square root of the + // integration weights to get the eigenmodes of the autocorrelation matrix. + for(size_t i=0; i < n_t; i++){ + for(size_t j=0; j < (size_t) n_eig; j++){ + KL_modes_(i,j) = work_eigvec(i,n_eig-1-j)/wh_(i); + } + } + + // Return the number of obtained eigenvalues + return n_eig; + +} + +void KLDecompUni::KLproject(const Array2D &realiz, Array2D &xi) +{ + + // Get dimensions + int nKL = xi.XSize(); + const size_t n_t = realiz.XSize(); + const size_t n_r = realiz.YSize(); + + // dimension check + if ( n_r != xi.YSize() ) { + printf("KLproject(): dimension error"); exit(1); + } + + Array1D mean_realiz(n_t,0.e0); + this->meanRealiz(realiz,mean_realiz); + + for(int ikl=0; ikl < nKL; ikl++) + for(int k=0; k < (int) n_r; k++) { + xi(ikl,k) = 0.0 ; + for(size_t i=0; i < n_t; i++) + xi(ikl,k) += KL_modes_(i,ikl) * ( realiz(i,k) - mean_realiz(i) ) + * w_(i) / sqrt(eig_values_(ikl)) ; + } + + return; + +} + +const Array1D& KLDecompUni::eigenvalues() const +{ + + if(!decomposed_){ + std::string err_message = "Eigenvalues are not yet available"; + throw Tantrum(err_message); + } else { + return eig_values_; + } + +} + +void KLDecompUni::eigenvalues(const int nEIG, double *eigs) const +{ + + if(!decomposed_){ + std::string err_message = "Eigenvalues are not yet available"; + throw Tantrum(err_message); + } else { + if (nEIG > eig_values_.XSize() ) { + std::cout<& KLDecompUni::KLmodes() const +{ + + if(!decomposed_){ + std::string err_message = "KL modes are not yet available"; + throw Tantrum(err_message); + } else { + return KL_modes_; + } + +} + +void KLDecompUni::KLmodes(const int npts, const int nKL, double *klModes ) const +{ + + if(!decomposed_){ + std::string err_message = "KL modes are not yet available"; + throw Tantrum(err_message); + } else { + if (npts != KL_modes_.XSize() ) { + std::string err_message = "KLmodes(): number of grid points does not match"; + throw Tantrum(err_message); + } + if (nKL != KL_modes_.YSize() ) { + std::string err_message = "KLmodes(): number of modes does not match"; + throw Tantrum(err_message); + } + for(size_t j=0; j < nKL; j++) + for(size_t i=0; i < npts; i++) + klModes[j*npts+i] = KL_modes_(i,j); + } + + return ; + +} + +void KLDecompUni::meanRealiz(const Array2D &realiz, Array1D &mean_realiz) +{ + const size_t n_t = realiz.XSize(); + const int n_r = realiz.YSize(); + + // dimension check + if (n_t != mean_realiz.XSize()) { + printf("meanRealiz: dimension error"); exit(1); + } + + for(size_t i=0; i < n_t; i++){ + mean_realiz(i) = 0.0 ; + for(int k=0; k < n_r; k++){ + mean_realiz(i) += realiz(i,k)/n_r; + } + } + + return; + +} + +void KLDecompUni::truncRealiz(const Array1D& meanrea,const Array2D& xi, + const int& nKL, Array2D& trunc_realiz) +{ + + const size_t n_t = meanrea.XSize(); + const int nsample=xi.XSize(); + + // dimension check + if ( ( nsample != (int) trunc_realiz.XSize() ) || + ( n_t != trunc_realiz.YSize() ) ) { + printf("truncRealiz: dimension error"); exit(1); + } + if ( nKL > (int) xi.YSize() ) { + printf("truncRealiz: there are not enough xi variables."); exit(1); + } + + for(int isample=0; isample < nsample; isample++){ + for(size_t i=0; i < n_t; i++){ + trunc_realiz(isample,i) = meanrea(i); + for(int ikl=0; ikl < nKL; ikl++){ + trunc_realiz(isample,i) += xi(isample,ikl)*sqrt(eig_values_(ikl))*KL_modes_(i,ikl); + } + } + } + + return; + +} diff --git a/cpp/lib/kle/kle.h b/cpp/lib/kle/kle.h new file mode 100644 index 00000000..c0b20c1a --- /dev/null +++ b/cpp/lib/kle/kle.h @@ -0,0 +1,188 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file kldecompuni.h +/// \author B. Debusschere, K. Sargsyan, C. Safta, 2007 - +/// \brief Header for Karhunen-Loeve decomposition class + + +#ifndef KLDECOMPUNI_H_SEEN +#define KLDECOMPUNI_H_SEEN + +#include +#include "ftndefs.h" +#include "Array1D.h" +#include "Array2D.h" +// #include "Array3D.h" + +/*! + \class KLDecompUni + \brief Computes the Karhunen-Loeve decomposition of a univariate stochastic process + \details + @f[ + F(t,\theta) = \left < F(t,\theta) \right >_{\theta} + + \sum_{k=1}^{\infty} \sqrt{\lambda_k} f_k(t) \xi_k@f] +*/ +class KLDecompUni { + + public: + + /*! + \brief + Constructor that takes the autocorrelation matrix "corr" (\f$C\f$) of the process + we are studying as well as the array "tsamples" (\f$t\f$) with the points in time where + snapshots of the system were taken. + + \details + Constructs weights (\f$w\f$) needed for the Nystrom method to solve the Fredholm integral equation + @f[ \int C(s,t)f(t)dt=\lambda f(s) \rightarrow \sum w_j C(s_i,t_j) f_k(t_j) = \lambda_k f_k(s_i)@f] + */ + KLDecompUni(const Array1D& tSamples); + + KLDecompUni(); + + /// \brief Destructor + ~KLDecompUni() {}; + + void Init() ; + + /// \brief Set weights for computing the integral needed for + /// Nystrom's method for solving the Fredholm integral equation + void SetWeights(const Array1D& weights) ; + + /// \brief Set weights for computing the integral needed for + /// Nystrom's method for solving the Fredholm integral equation + void SetWeights(const double *weights, const int npts) ; + + /*! + \brief Perform KL decomposition into nKL modes and return actual number of + modes that were obtained + \details Further manipulation of the discretized Fredholm equation leads to the eigenvalue problem + @f[A g=\lambda g @f] + where \f$A=W K W\f$ and \f$g=Wf\f$, with \f$W\f$ being the diagonal matrix, \f$W_{ii}=\sqrt{w_i}\f$ and + \f$K_{ij}=Cov(t_i,t_j)\f$. Solutions consist of pairs of eigenvalues \f$\lambda_k\f$ and KL modes \f$f_k=W^{-1}g_k\f$. + */ + int decompose(const Array2D& corr, const int& nKL); + + /*! + \brief Perform KL decomposition into nKL modes and return actual number of + modes that were obtained + \details Further manipulation of the discretized Fredholm equation leads to the eigenvalue problem + @f[A g=\lambda g @f] + where \f$A=W K W\f$ and \f$g=Wf\f$, with \f$W\f$ being the diagonal matrix, \f$W_{ii}=\sqrt{w_i}\f$ and + \f$K_{ij}=Cov(t_i,t_j)\f$. Solutions consist of pairs of eigenvalues \f$\lambda_k\f$ and KL modes \f$f_k=W^{-1}g_k\f$. + */ + int decompose(const double *corr, const int &nKL); + + /*! + \brief Project realizations \f$F(t,\theta_l)\f$ to the KL modes and store them in xi (\f$\xi_k\f$) + + \details Samples of random variables \f$\xi_k\f$ are obtained by projecting + realizations of the random process \f$F\f$ on the eigenmodes \f$f_k\f$ + @f[ \left.\xi_k\right\vert_{\theta_l}=\left _{\theta}, f_k(t) \right >_t/\sqrt{\lambda_k} @f] + ... or numerically + @f[ + \left.\xi_k\right\vert_{\theta_l}=\sum_{i=1}^{N_p} w_i\left(F(t_i,\theta_l)-\left < + F(t_i,\theta) \right >_{\theta} \right) f_k(t_i)/\sqrt{\lambda_k} @f] + */ + void KLproject(const Array2D& realiz, Array2D& xi); + + /// \brief Get eigenvalues in descending order + const Array1D& eigenvalues() const; + void eigenvalues(const int nEIG, double *eigs) const; + + /// \brief Get associated KL modes + const Array2D& KLmodes() const; + + /// \brief Get associated KL modes + void KLmodes(const int npts, const int nKL, double *klModes ) const; + + /// \brief Calculate (in meanRealiz) the mean realizations + void meanRealiz(const Array2D& realiz, Array1D& mean_realiz); + + /*! + \brief + Returns the truncated KL sum + \details + @f[ + F(t_i,\theta_l) = \left < F(t_i,\theta) \right >_{\theta} + + \sum_{k=1}^{nKL} \sqrt{\lambda_k} f_k(t_i) \left. \xi_k\right\vert_{\theta_l} + + @f] + */ + void truncRealiz(const Array1D& meanrea,const Array2D& xi,const int& nKL, Array2D& trunc_realiz); + + private: + /// \brief Dummy default constructor, which should not be used as it is not well defined + //KLDecompUni() {}; + + /// \brief Dummy copy constructor, which should not be used as it is currently not well defined + KLDecompUni(const KLDecompUni &) {}; + + /// \brief Flag to determine whether KL decomposition has taken place (and consequently + /// that the interal data structures contain meaningful eigenvalues and vectors ... ) + bool decomposed_; + + /// \brief Matrix to hold the upper triangular part of the matrix to get eigenvalues of + Array2D whcwh_; + + /// \brief Array to hold weights for Nystrom's method for Fredholm integral equation solution + Array1D w_; + + /// \brief Array to hold square roots of weights + Array1D wh_; + + /// \brief Option to determine what to compute (eigenvalues and eigenvectors) + char jobz_ ; + /// \brief Option to set the type of range for eigenvalues + char eigRange_; + /// \brief Option to indicate how matrix is stored + char uplo_; + /// \brief Lower bound for range of eigenvalues + double vl_; + /// \brief Upper bound for range of eigenvalues + double vu_; + /// \brief Lower index of range of eigenvalues requested + int il_; + /// \brief Upper index of range of eigenvalues requested + int iu_; + /// \brief Absolute tolerance for convergence + double absTol_; + + /// \brief Array to store eigenvalues + Array1D eig_values_; + /// \brief Matrix to store KL modes + Array2D KL_modes_; + + /// \brief info on success of the eigenvector solutions + int eig_info_; + /// \brief Array to store indices of eigenvectors that failed to converge + Array1D ifail_; + +}; + +#endif /* KLDECOMPUNI_H_SEEN */ diff --git a/cpp/lib/lreg/CMakeLists.txt b/cpp/lib/lreg/CMakeLists.txt new file mode 100644 index 00000000..4a72169e --- /dev/null +++ b/cpp/lib/lreg/CMakeLists.txt @@ -0,0 +1,29 @@ +project(UQTk) + +SET(lreg_HEADERS + lreg.h + ) + +add_library(uqtklreg lreg.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) +include_directories (../pce ) +include_directories (../bcs ) + + +include_directories (../../../dep/lapack) +include_directories (../../../dep/blas) +include_directories (../../../dep/lbfgs) +include_directories (../../../dep/dsfmt) +include_directories (../../../dep/figtree) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtklreg DESTINATION lib) + +# Install the header files +INSTALL(FILES ${lreg_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/lreg/lreg.cpp b/cpp/lib/lreg/lreg.cpp new file mode 100644 index 00000000..40a5b88b --- /dev/null +++ b/cpp/lib/lreg/lreg.cpp @@ -0,0 +1,652 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file lreg.cpp +/// \author K. Sargsyan 2015 - +/// \brief Linear regression class + + +#include +#include +#include + +#include "lreg.h" +#include "gen_defs.h" +#include "error_handlers.h" + +#include "arraytools.h" +#include "arrayio.h" +#include "PCSet.h" + +#include "bcs.h" + +#include "ftndefs.h" +#include "depblas.h" +#include "deplapack.h" + + +#include "tools.h" +#include "lbfgs_routines.h" + +#include +//#define DEBUG + +/// Leave-one-out error computation done as a global function for optimization +/// \todo Find a more elegant way to do this within the class +double loo(int ndim, double* m, void* classpointer); + + +// Constructor for Radial Basis Function basis class +RBFreg::RBFreg(Array2D& centers, Array1D& widths) +{ + centers_=centers; + widths_=widths; + ndim_=centers.YSize(); + nbas_=centers.XSize(); + CHECKEQ(ndim_,widths.XSize()); + + return; +} + +// Constructor for Polynomial Chaos basis class, given order and dim +PCreg::PCreg(string strpar,int order, int dim) +{ + Array2D mindex; + computeMultiIndex(dim,order,mindex); + + this->SetMindex(mindex); + pctype_=strpar; + + nbas_=this->mindex_.XSize(); + ndim_=this->mindex_.YSize(); + + return; +} + +// Constructor for Polynomial Chaos basis class, given multiindex +PCreg::PCreg(string strpar,Array2D& mindex) +{ + this->SetMindex(mindex); + pctype_=strpar; + + nbas_=this->mindex_.XSize(); + ndim_=this->mindex_.YSize(); + + + return; +} + +// Constructor of monomial basis class, given order and dim +PLreg::PLreg(int order, int dim) +{ + Array2D mindex; + computeMultiIndex(dim,order,mindex); + + this->SetMindex(mindex); + + nbas_=this->mindex_.XSize(); + ndim_=this->mindex_.YSize(); + + return; +} + +// Constructor of monomial basis class, given multiindex +PLreg::PLreg(Array2D& mindex) +{ + this->SetMindex(mindex); + + nbas_=this->mindex_.XSize(); + ndim_=this->mindex_.YSize(); + + return; +} + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// + +// Initializing linear regression, parent class +void Lreg::InitRegr() +{ + weights_.Resize(this->nbas_,0.e0); + dataSetFlag_=false; + regMode_="m"; +} + +// Set the x- and y(1D)- data +void Lreg::SetupData(Array2D& xdata, Array1D& ydata) +{ + xdata_=xdata; + ydata_=ydata; + npt_=xdata.XSize(); + CHECKEQ(npt_,ydata.XSize()); + CHECKEQ(ndim_,xdata.YSize()); + + dataSetFlag_=true; + + return; +} + +// Set the x- and y(2D)- data +void Lreg::SetupData(Array2D& xdata, Array2D& ydata) +{ + + int nx=xdata.XSize(); + CHECKEQ(ndim_,xdata.YSize()); + CHECKEQ(nx,ydata.XSize()); + int numeach=ydata.YSize(); + + + npt_=nx*numeach; + + xdata_.Resize(npt_,ndim_); + ydata_.Resize(npt_); + + + int j=0; + for(int i=0; i& weights) +{ + weights_=weights; + CHECKEQ(this->nbas_,weights_.XSize()); + + return; +} + +// Building regression with BCS methods +void Lreg::BCS_BuildRegr(Array1D& used, double eta) +{ + assert(dataSetFlag_); + int ntot=ydata_.XSize(); + // Work variables + Array1D lambda_init,weights, errbars, basis, alpha ; + Array2D newmindex; + Array2D Sig; + double lambda ; + + // Hardwired parameters + int adaptive = 0 ; + int optimal = 1 ; + double scale = 0.1 ; + int verbose = 0 ; + // Initial variance 'rule-of-thumb' + sigma2_= max(1.e-12,get_var(ydata_)/1.0e6); + + // Compute the basis evaluation matrix + this->EvalBases(xdata_,bdata_); + + // Run the BCS + lambda_init=weights_; + WBCS(bdata_,ydata_,sigma2_,eta,lambda_init,adaptive, optimal,scale, + verbose,coef_,used,coef_erb_,basis,alpha,lambda,coef_cov_); + + // Only retain the bases selected by WBCS + this->StripBases(used); + + return; +} + +// Building least-squares regression +void Lreg::LSQ_BuildRegr() +{ + // Make sure data is set + assert(dataSetFlag_); + + // Fill in the basis evaluation matrix + this->EvalBases(xdata_,bdata_); + A_=MatTMat(bdata_) ; + + // Add the regularization weights to the diagonal + for (int i=0;iA_inv_ = INV(this->A_); + + // Compute via the classical least-square formula + prodAlphaMatTVec(bdata_, ydata_, 1.0, Hty_) ; + prodAlphaMatVec(A_inv_, Hty_, 1.0, coef_) ; + + + // If errorbars are requested + if (this->regMode_=="ms" or this->regMode_=="msc"){ + double s1=0.0,s2=0.0; + + for(int it=0;it>1, beta>>1, beta/alpha=sigma for fixed sigma + // \todo to be implemented + + sigma2_=(betta+betta_add)/(alfa+0.5*(npt_-nbas_)-1.); + if (sigma2_<0.0){ + cout << "Negative (should be very small) data noise, set to zero. Sigma2=" << sigma2_ << endl; + sigma2_=0.0; + } + coef_cov_.Resize(nbas_,nbas_,0.e0); + for(int ib=0;ibnbas_; i++) coef_erb_(i) = sqrt(coef_cov_(i,i)); + + } + + return; +} + + +// Evaluate the pre-built regression at given values +void Lreg::EvalRegr(Array2D& xcheck, Array1D& ycheck,Array1D& yvar,Array2D& ycov) +{ + CHECKEQ(ndim_,xcheck.YSize()); + int ncheck=xcheck.XSize(); + Array2D bcheck; + + this->EvalBases(xcheck,bcheck); + prodAlphaMatVec(bcheck, coef_, 1.0, ycheck) ; + + // If more than the the means are requested + if (this->regMode_=="ms" or this->regMode_=="msc"){ + if (sigma2_==0.0){ + yvar.Resize(ncheck,0.0); + ycov.Resize(ncheck,ncheck,0.0); + return; + } + + Array2D L=coef_cov_; + + // Cholesky factorization of the covariance + int nd=L.XSize(); + CHECKEQ(nd,this->nbas_); + int chol_info=0; + char lu='L'; + FTN_NAME(dpotrf)(&lu,&nd, L.GetArrayPointer(),&nd,&chol_info); + + // Catch the error in Cholesky factorization + if (chol_info != 0 ){ + printf("Lreg::EvalRegr():Error in Cholesky factorization, info=%d\n", chol_info); + exit(1); + } + + for (int i=0;i A; + prodAlphaMatMat(bcheck,L,1.0,A); + + yvar.Resize(ncheck); + for (int i=0;iregMode_=="msc"){ + + ycov.Resize(ncheck,ncheck); + ycov(i,i)=yvar(i); + for (int j=0;j& array,Array1D& proj_array) +{ + CHECKEQ(npt_,array.XSize()); + Array1D tmp,tmp2; + prodAlphaMatTVec(bdata_,array,1.0,tmp); + prodAlphaMatVec(A_inv_,tmp,1.0,tmp2); + prodAlphaMatVec(bdata_,tmp2,1.0,proj_array); + + for (int i=0;i Lreg::LSQ_computeBestLambdas() +{ + + Array1D lambda(nbas_,0.1); + int n=nbas_; //1;//ndim_; + int m=5; + Array1D nbd(n,1); + Array1D l(n,0.e0); + Array1D u(n,0.e0); + + void* info=this; + + // Minimize leave-one-out error + lbfgsDR(n,m,lambda.GetArrayPointer(),nbd.GetArrayPointer(),l.GetArrayPointer(),u.GetArrayPointer(),loo,NULL,info) ; + + + return lambda; +} + +// Compute best values for regularization weight parameter +double Lreg::LSQ_computeBestLambda() +{ + + double lambda=0.1; + int n=1;//ndim_; + int m=5; + Array1D nbd(n,1); + Array1D l(n,0.e0); + Array1D u(n,0.e0); + + void* info=this; + + // Minimize leave-one-out error + lbfgsDR(n,m,&lambda,nbd.GetArrayPointer(),l.GetArrayPointer(),u.GetArrayPointer(),loo,NULL,info) ; + + return lambda; +} + +// Compute residual +void Lreg::getResid() +{ + + if (!residFlag_){ + Array1D tmp; + prodAlphaMatVec(bdata_,coef_,1.0,tmp); + resid_=subtract(ydata_,tmp); + residFlag_=true; + } + + return; +} + +// COmpute the diagonal of the projection matrix +void Lreg::getDiagP() +{ + if (!diagPFlag_){ + diagP_.Resize(npt_,1.e0); + for (int i=0;i Lreg::computeErrorMetrics(string method) +{ + Array1D err(2,-999.); + if (method=="lsq"){ + err(0)=this->LSQ_computeLOO(); + err(1)=this->LSQ_computeGCV(); + } + else{ + printf("Computation of errors not implemented for %s method\n",method.c_str()); + } + + return err; +} + + +// Compute the validation error given a set of x-y data +double Lreg::computeRVE(Array2D& xval,Array1D& yval,Array1D& yval_regr) +{ + int nval=xval.XSize(); + CHECKEQ(ndim_,xval.YSize()); + CHECKEQ(nval,yval.XSize()); + + double sum=0.0; + Array1D dummy_var; Array2D dummy_cov; + this->SetRegMode("m"); + this->EvalRegr(xval,yval_regr, dummy_var,dummy_cov); + for (int i=0;igetResid(); + + this->getDiagP(); + + Array1D resid_scaled=dotdivide(resid_,diagP_); + + return norm(resid_scaled)/sqrt(npt_); + +} + +// Compute the generalized cross validation error +double Lreg::LSQ_computeGCV() +{ + this->getResid(); + this->getDiagP(); + + double sum=0.0; + for (int i=0;i& centers) +{ + centers_=centers; + CHECKEQ(ndim_,centers.YSize()); + CHECKEQ(nbas_,centers.XSize()); + return; +} + +// Setting RBF widths +void RBFreg::SetWidths(Array1D& widths) +{ + widths_=widths; + CHECKEQ(ndim_,widths.XSize()); + return; +} + +// Evaluate PC bases +void PCreg::EvalBases(Array2D& xx,Array2D& bb) +{ + CHECKEQ(ndim_,xx.YSize()); + + PCSet currPCModel("NISPnoq",mindex_,pctype_,0.,1.); + + currPCModel.EvalBasisAtCustPts(xx,bb); + + return; + +} + +// Evaluate monomial bases +void PLreg::EvalBases(Array2D& xx,Array2D& bb) +{ + CHECKEQ(ndim_,xx.YSize()); + int nx=xx.XSize(); + bb.Resize(nx,nbas_,0.e0); + + for(int is=0;is& xx,Array2D& bb) +{ + CHECKEQ(ndim_,xx.YSize()); + int nx=xx.XSize(); + + bb.Resize(nx,nbas_,0.e0); + for(int is=0;is& used) +{ + int nused=used.Length(); + Array2D mindex_new(nused,ndim_,0); + for (int i=0;inbas_=nused; + return; +} + +// Select given monomial bases +void PLreg::StripBases(Array1D& used) +{ + int nused=used.Length(); + Array2D mindex_new(nused,ndim_,0); + for (int i=0;inbas_=nused; + return; +} + +// Select given RBFs +void RBFreg::StripBases(Array1D& used) +{ + int nused=used.Length(); + Array2D centers_new(nused,ndim_,0.); + Array1D widths_new(nused,0.); + + for (int i=0;inbas_=nused; + + return; +} + + +// Leave-one-out error estimator +double loo(int ndim, double* mm, void* classpointer) +{ + Lreg* thisClass=(Lreg*) classpointer; + + Array1D lam(thisClass->GetNbas()); + if (ndim==1) + lam.Resize(thisClass->GetNbas(),mm[0]); + else{ + CHECKEQ(ndim,thisClass->GetNbas()); + for (int i=0;iSetRegWeights(lam); + thisClass->LSQ_BuildRegr(); + + Array1D errors=thisClass->computeErrorMetrics("lsq"); + double err_loo=errors(0); + return err_loo; + +} diff --git a/cpp/lib/lreg/lreg.h b/cpp/lib/lreg/lreg.h new file mode 100644 index 00000000..f95402d5 --- /dev/null +++ b/cpp/lib/lreg/lreg.h @@ -0,0 +1,234 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file lreg.h +/// \author K. Sargsyan 2015 - +/// \brief Header file for the linear regression class +/// A great deal of notations and computations follow \cite Orr:1996 + +#ifndef LREG_H_SEEN +#define LREG_H_SEEN + +#include "Array1D.h" +#include "Array2D.h" + +/// \class Lreg +/// \brief Class for linear parameteric regression +class Lreg { +public: + + /// \brief Constructor + Lreg() {residFlag_=false; diagPFlag_=false; return;}; + /// \brief Destrcutor + ~Lreg() {}; + + + /// \brief Set multiindex + virtual void SetMindex(Array2D& mindex){}; + /// \brief Get multiindex + virtual void GetMindex(Array2D& mindex){}; + /// \brief Set centers (for RBF) + virtual void SetCenters(Array2D& centers){}; + /// \brief Set widths (for RBF) + virtual void SetWidths(Array1D& widths){}; + /// \brief Set parameters (for RBF) + virtual void SetParamsRBF(){}; + /// \brief Evaluate bases + virtual void EvalBases(Array2D& xx,Array2D& bb){};// dummy + /// \brief Strip bases + virtual void StripBases(Array1D& used){}; + + /// \brief Initialize + void InitRegr(); + /// \brief Setup data (1d ydata) + void SetupData(Array2D& xdata, Array1D& ydata); + /// \brief Setup data (2d ydata) + void SetupData(Array2D& xdata, Array2D& ydata); + /// \brief Set the regression mode + void SetRegMode(string regmode){regMode_=regmode; return;} + /// \brief Set weights + void SetRegWeights(Array1D& weights); + /// \brief Build BCS regression + void BCS_BuildRegr(Array1D& selected, double eta); + /// \brief Build LSQ regression + void LSQ_BuildRegr(); + /// \brief Evaluate the regression expansion + void EvalRegr(Array2D& xcheck, Array1D& ycheck,Array1D& yvar,Array2D& ycov); + + /// \brief Get the number of points + int GetNpt() const {return npt_;} + /// \brief Get dimensionality + int GetNdim() const {return ndim_;} + /// \brief Get the number of bases + int GetNbas() const {return nbas_;} + /// \brief Get the variance + double GetSigma2() const {return sigma2_;} + /// \brief Get coefficient covariance + void GetCoefCov(Array2D& coef_cov) {coef_cov=coef_cov_; return;} + /// \brief Get coefficients + void GetCoef(Array1D& coef) {coef=coef_; return;} + /// \brief Project + void Proj(Array1D& array,Array1D& proj_array); + /// \brief Compute the best values for regulariation parameter vector lambda, for LSQ + Array1D LSQ_computeBestLambdas(); + /// \brief Compute the best value for regulariation parameter lambda, for LSQ + double LSQ_computeBestLambda(); + /// \brief Compute the residual vector, if not already computed + void getResid(); + /// \brief Compute the diagonal of projection matrix, if not already computed + void getDiagP(); + /// \brief Compote error according to a selected metrics + Array1D computeErrorMetrics(string method); + /// \brief Compute validation error + double computeRVE(Array2D& xval,Array1D& yval,Array1D& yval_regr); + + + protected: + + /// \brief xdata array + Array2D xdata_; + /// \brief ydata array + Array1D ydata_; + + /// \brief Number of samples + int npt_; + /// \brief Number of bases + int nbas_; + /// \brief Dimensionality + int ndim_; + /// \brief Variance + double sigma2_; + /// \brief Weights + Array1D weights_; + /// \brief Residuals + Array1D resid_; + /// \brief Flag to indicate whether residual is computed + bool residFlag_; + /// \brief Diagonal of projection matrix + Array1D diagP_; + /// \brief Flag to indicate whether diagonal of projetion matrix is computed + bool diagPFlag_; + + //@{ + /// \brief Auxiliary matrix or vector; see UQTk Manual + Array2D bdata_,A_,A_inv_,coef_cov_; + Array1D Hty_,coef_,coef_erb_; + //@} + +private: + + /// \brief Compute Leave-one-out error for LSQ + double LSQ_computeLOO(); + /// \brief COmpute generalized-cross-validation error for LSQ + double LSQ_computeGCV(); + /// \brief Flag to indicate whether data has been set or not + bool dataSetFlag_; + /// \brief Regression mode (m, ms, msc for mean-only, mean+variance, mean+covariance) + string regMode_; + +}; + +/// \class RBFreg +/// \brief Derived class for RBF regression +class RBFreg: public Lreg { +public: + /// \brief Constructor: + RBFreg(Array2D& centers, Array1D& widths); + /// \brief Destructor + ~RBFreg() {}; + + /// \brief Set centers + void SetCenters(Array2D& centers); + /// \brief Set widths + void SetWidths(Array1D& widths); + + /// \brief Evaluate the bases + void EvalBases(Array2D& xx,Array2D& bb); + /// \brief Strip the bases + void StripBases(Array1D& used); + +private: + /// \brief RBF centers + Array2D centers_; + /// \brief RBF bases' widhts + Array1D widths_; + +}; + +/// \class PCreg +/// \brief Derived class for PC regression +class PCreg: public Lreg { +public: + /// \brief Constructors: + PCreg(string strpar,int order,int dim); + PCreg(string strpar,Array2D& mindex); + /// \brief Destructor + ~PCreg() {}; + + /// \brief Evaluate the bases + void EvalBases(Array2D& xx,Array2D& bb); + /// \brief Strip the bases + void StripBases(Array1D& used); + /// \brief Set multiindex + void SetMindex(Array2D& mindex){mindex_=mindex;} + /// \brief Get multiindex + void GetMindex(Array2D& mindex){mindex=mindex_;return;} + +private: + /// \brief Multiindex + Array2D mindex_; + /// \brief PC type + string pctype_; + +}; + +/// \class PLreg +/// \brief Derived class for polynomial regression +class PLreg: public Lreg { +public: + /// \brief Constructors: + PLreg(int order, int dim); + PLreg(Array2D& mindex); + /// \brief Destructor + ~PLreg() {}; + + /// \brief Evaluate the bases + void EvalBases(Array2D& xx,Array2D& bb); + /// \brief Strip the bases + void StripBases(Array1D& used); + /// \brief Set multiindex + void SetMindex(Array2D& mindex){mindex_=mindex;} + /// \brief Get multiindex + void GetMindex(Array2D& mindex){mindex=mindex_;return;} + + +private: + /// \brief Multiindex + Array2D mindex_; + +}; + +#endif /* LREG_H_SEEN */ diff --git a/cpp/lib/mcmc/CMakeLists.txt b/cpp/lib/mcmc/CMakeLists.txt new file mode 100644 index 00000000..71e1643e --- /dev/null +++ b/cpp/lib/mcmc/CMakeLists.txt @@ -0,0 +1,26 @@ + +SET(mcmc_HEADERS + mcmc.h + ) + +add_library(uqtkmcmc mcmc.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) + +include_directories (../../../dep/slatec) +include_directories (../../../dep/lapack) +include_directories (../../../dep/dsfmt ) +include_directories (../../../dep/figtree) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories (../../../dep/lbfgs ) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtkmcmc DESTINATION lib) + +# Install the header files +INSTALL(FILES ${mcmc_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/mcmc/mcmc.cpp b/cpp/lib/mcmc/mcmc.cpp new file mode 100644 index 00000000..e0814c64 --- /dev/null +++ b/cpp/lib/mcmc/mcmc.cpp @@ -0,0 +1,1031 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// \file mcmc.cpp +// \author K. Sargsyan, C. Safta, B. Debusschere, 2012 - +// \brief Markov chain Monte Carlo class + +#include +#include +#include "error_handlers.h" +#include "deplapack.h" + +#include "tools.h" +#include "arrayio.h" +#include "arraytools.h" +#include "mcmc.h" +#include "gen_defs.h" +#include "lbfgs_routines.h" + + +double neg_logposteriorproxy(int chaindim, double* m, void* classpointer); +void grad_neg_logposteriorproxy(int chaindim, double* m, double* grads, void* classpointer); + +//******************NEW ROUTINES*************************// +void MCMC::setSeed(int seed){ + dsfmt_init_gen_rand(&RandomState,seed); +} +void MCMC::setWriteFlag(int I){ + WRITE_FLAG = I; +} + +void MCMC::resetChainState(){ + fullChain_.Clear(); +} +//******************NEW ROUTINES*************************// + +MCMC::MCMC(double (*logPosterior)(Array1D&, void *), void *postinfo) +{ + + //***************************************** + FLAG = 0; + //***************************************** + + postInfo_=postinfo; + logPosterior_=logPosterior; + + // / Set the initialization flags to false + gradflag_=false; + tensflag_=false; + + chaindimInit_=false; + propcovInit_=false; + methodInit_=false; + outputInit_=false; + adaptstepInit_=false; + gammaInit_=false; + epscovInit_=false; + epsMalaInit_=false; + + + // Initiate the random number generator seed + // \todo This needs to be made more generic + seed_=13; + dsfmt_init_gen_rand(&RandomState,seed_); + + // Set the location of the last chain state written (-1 means nothing is written to files yet) + lastwrite_=-1; + + // By default the names are not prepended + namePrepend_=false; + + // Set defaults + this->initDefaults(); + + WRITE_FLAG = 1; + + return; +} + +//***************************************** +MCMC::MCMC(LikelihoodBase& L) +{ + FLAG = 1; + L_ = &L; + + // / Set the initialization flags to false + gradflag_=false; + tensflag_=false; + + chaindimInit_=false; + propcovInit_=false; + methodInit_=false; + outputInit_=false; + adaptstepInit_=false; + gammaInit_=false; + epscovInit_=false; + epsMalaInit_=false; + + // Set the location of the last chain state written (-1 means nothing is written to files yet) + lastwrite_=-1; + + // Initiate the random number generator seed + // \todo This needs to be made more generic + seed_=13; + dsfmt_init_gen_rand(&RandomState,seed_); // you can override with setseed + + // By default the names are not prepended + namePrepend_=false; + + // Set defaults + this->initDefaults(); + + WRITE_FLAG = 1; + + + return; +} + +// create samples where each column is a sample +void MCMC::getSamples(int burnin, int every,Array2D& samples) +{ + int nCalls = fullChain_.Length(); + samples.Resize(chainDim_,0); // initialize sample array + int j=0; + for (int i = burnin; i < nCalls; i+=every){ + samples.insertCol(fullChain_(i).state,j); + j++; + } +} + +// create samples where each column is a sample +void MCMC::getSamples(Array2D& samples) +{ + getSamples(0,1,samples); +} +//***************************************** + + +void MCMC::setGradient(void (*gradlogPosterior)(Array1D&, Array1D&, void *)) +{ + gradlogPosterior_ = gradlogPosterior; + gradflag_ = true; + return; +} + +void MCMC::setMetricTensor(void (*metricTensor)(Array1D&, Array2D&, void *)) +{ + metricTensor_ = metricTensor; + tensflag_ = true; + return; +} + +void MCMC::initDefaults() +{ + this->default_method_="am"; + this->default_gamma_=0.01; + this->default_eps_cov_=1e-8; + + this->default_eps_mala_=0.1; + + this->newMode_=false; + this->accRatio_ = -1.0; + + return; +} + +void MCMC::printChainSetup() +{ + if (this->methodInit_) + cout << "Method : " << this->methodinfo_.type << endl; + else + cout << "Method (default) : " << this->default_method_ << endl; + if (this->gammaInit_) + cout << "Gamma : " << this->methodinfo_.gamma << endl; + else + cout << "Gamma (default) : " << this->default_gamma_ << endl; + if (this->epscovInit_) + cout << "Eps_Cov : " << this->methodinfo_.eps_cov << endl; + else + cout << "Eps_Cov (default): " << this->default_eps_cov_ << endl; + return; +} + + + +double MCMC::evalLogPosterior(Array1D& m){ + // Evaluate given the log-posterior function defined by the user in the constructor + //***************************************** + if (FLAG == 0){ + return logPosterior_(m,postInfo_); + } + if (FLAG == 1){ + return L_->eval(m); + } + + //***************************************** +} + +void MCMC::evalGradLogPosterior(Array1D& m, Array1D& grads) +{ + // Evaluate given the log-posterior function defined by the user in the constructor + gradlogPosterior_(m,grads,postInfo_); + + return; + +} + +void MCMC::initMethod(string method) +{ + // Set the method type + methodinfo_.type=method; + // Set the initialization flag to True + methodInit_=true; + return; +} + +void MCMC::initAdaptSteps(int adaptstart,int adaptstep, int adaptend) +{ + // Initialize the vector containing the adaptivity information: when to start, how often and when to stop. + methodinfo_.adaptstep.Resize(3); + methodinfo_.adaptstep(0)=adaptstart; + methodinfo_.adaptstep(1)=adaptstep; + methodinfo_.adaptstep(2)=adaptend; + + // Set the initialization flag to True + adaptstepInit_=true; + + return; +} + +void MCMC::initAMGamma(double gamma) +{ + // Initialize the scale factor gamma + methodinfo_.gamma=gamma; + // Set the initialization flag to True + gammaInit_=true; + + return; +} + +void MCMC::initEpsCov(double eps_cov) +{ + // Initialize the covariance 'nugget' + methodinfo_.eps_cov=eps_cov; + // Set the initialization flag to True + epscovInit_=true; + + return; +} + +void MCMC::initEpsMALA(double eps_mala) +{ + // Initialize the epsilon parameter for MALA algorithm + epsMALA_=eps_mala; + // Set the initialization flag to True + epsMalaInit_=true; + + return; +} + +void MCMC::setOutputInfo(string outtype, string file,int freq_file, int freq_screen) +{ + outputinfo_.type=outtype; + outputinfo_.filename=file; + outputinfo_.freq_chainfile=freq_file; + outputinfo_.freq_outscreen=freq_screen; + // Set the initialization flag to True + outputInit_=true; + return; +} + +void MCMC::initChainPropCov(Array2D& propcov) +{ + // Initialize the proposal covariance matrix + methodinfo_.chcov=propcov; + // Set the initialization flag to True + propcovInit_=true; + return; +} + +void MCMC::initChainPropCovDiag(Array1D& sig) +{ + + // Create a diagonal matrix and fill in the diagonal terms + methodinfo_.chcov.Resize(this->chainDim_,this->chainDim_,0.e0); + for(int i=0;ichainDim_;i++) methodinfo_.chcov(i,i)=sig(i)*sig(i); + // Set the initialization flag to True + propcovInit_=true; + return; +} + +void MCMC::getChainPropCov(Array2D& propcov) +{ + // Get the proposal covariance matrix + propcov=methodinfo_.chcov; + return; +} + +double neg_logposteriorproxy(int chaindim, double* m, void* classpointer) +{ + + MCMC* thisClass=(MCMC*) classpointer; + + int aa=thisClass->GetChainDim(); + +// Double check chain dimensionality + if(chaindim != thisClass->GetChainDim()){ + + throw Tantrum(std::string("neg_logposteriorproxy: The passed in MCMC chain dimension") + + " does not match the dimension of the MChain class instance"); +} + + Array1D mm(chaindim,0.e0); + + for(int i=0;ievalLogPosterior(mm); + + + + +} + +void grad_neg_logposteriorproxy(int chaindim, double* m, double* grads, void* classpointer) +{ + + MCMC* thisClass=(MCMC*) classpointer; + + int aa=thisClass->GetChainDim(); + +// Double check chain dimensionality + if(chaindim != thisClass->GetChainDim()){ + + throw Tantrum(std::string("grad_neg_logposteriorproxy: The passed in MCMC chain dimension") + + " does not match the dimension of the MChain class instance"); +} + + Array1D mm(chaindim,0.e0); + + for(int i=0;i grads_arr; + thisClass->evalGradLogPosterior(mm, grads_arr); + + + for(int i=0;i& start) +{ + int n=start.Length(); + int m=5; + Array1D nbd(n,0); + Array1D l(n,0.e0); + Array1D u(n,0.e0); + + for (int i=0;iLower_(i); + } + if (upper_flag_(i) && !lower_flag_(i)){ + nbd(i)=3; + u(i)=this->Upper_(i); + } + if (upper_flag_(i) && lower_flag_(i)){ + nbd(i)=2; + l(i)=this->Lower_(i); + u(i)=this->Upper_(i); + } + } + void* info=this; + + + if (gradflag_) + lbfgsDR(n,m,start.GetArrayPointer(),nbd.GetArrayPointer(),l.GetArrayPointer(),u.GetArrayPointer(),neg_logposteriorproxy,grad_neg_logposteriorproxy,info) ; + else + lbfgsDR(n,m,start.GetArrayPointer(),nbd.GetArrayPointer(),l.GetArrayPointer(),u.GetArrayPointer(),neg_logposteriorproxy,NULL,info) ; + + currState_.step=0; + currState_.state=start; + currState_.alfa=0.0; + currState_.post=this->evalLogPosterior(start); + this->updateMode(); + + return; +} + + + +void MCMC::runChain(int ncalls, Array1D& chstart) +{ + // Check the mandatory initialization + if(!chaindimInit_) + throw Tantrum((string) "Chain dimensionality needs to be initialized"); + + // Check what is not initialized and use defaults instead + // \todo Specify defaults somewhere more transparently + + // Set defaults proposal covariance + if(!propcovInit_){ + Array1D chsig(this->chainDim_,0.e0); + for(int i=0;ichainDim_;i++) chsig(i)=MAX(fabs(0.1*chstart(i)),0.001); + this->initChainPropCovDiag(chsig); + } + + // Set defaults output format + if (!outputInit_) + this->setOutputInfo("txt","chain.dat", max(1,(int) ncalls/100), max(1,(int) ncalls/20)); + + + // Set the default method + if (!methodInit_) + methodinfo_.type=default_method_; + + // Set the default parameters for aMCMC + if(!strcmp(this->methodinfo_.type.c_str(),"am")){ + + if(!adaptstepInit_) + this->initAdaptSteps((int) ncalls/10,10,ncalls); + + if(!gammaInit_) + this->initAMGamma(this->default_gamma_); + + if(!epscovInit_) + this->initEpsCov(this->default_eps_cov_); + + } + else if(!strcmp(this->methodinfo_.type.c_str(),"mala")){ + if(!epsMalaInit_) + this->initEpsMALA(this->default_eps_mala_); + } + + + // For simplicity, work variables + string method=methodinfo_.type; + string output=outputinfo_.type; + + + // Set the number of substeps per one chain step + if(!strcmp(method.c_str(),"ss")) + nSubSteps_=chainDim_; + else //if(!strcmp(method.c_str(),"am")) or if(!strcmp(method.c_str(),"mala")) + nSubSteps_=1; + + + // Initial chain state + currState_.step=0; + currState_.state=chstart; + currState_.alfa=0.0; + currState_.post=this->evalLogPosterior(chstart); + this->updateMode(); + fullChain_.PushBack(currState_); + + // Number of accepted steps and number of all trials + int nacc=0; + int nall=0; + + // No new mode found yet + newMode_=false; + + // Main loop + for (int t=1; t <= ncalls; t++) { + currState_.step=t; + double sum_alpha=0.0; + + // Create a new proposed sample + // If the method is 'ss'(Single-Site), one actually searches all dimensions before recording the new state, i.e. + // one chain step has d substeps, where d is the chain dimensionality. + // For 'am'(Adaptive), d is set to 1. + for (int is=0; is m_cand; + if(!strcmp(method.c_str(),"ss")) + this->proposalSingleSite(currState_.state, m_cand, is); + else if(!strcmp(method.c_str(),"am")) + this->proposalAdaptive(currState_.state, m_cand, t); + else if(!strcmp(method.c_str(),"mala")) + this->proposalMALA(currState_.state, m_cand); + else if(!strcmp(method.c_str(),"mmala")) + this->proposalMMALA(currState_.state, m_cand); + else + throw Tantrum((string) "Chain running method is not recognized"); + + // Evaluate the posterior at the new sample point + double eval_cand = this->evalLogPosterior(m_cand); + + // Evaluate the new|old and old|new proposals + double old_given_new = this->probOldNew(currState_.state, m_cand); + double new_given_old = this->probOldNew(m_cand,currState_.state); + + + + // Accept or reject it + double alpha = exp(eval_cand - currState_.post + old_given_new - new_given_old); + // cout << t << " " << eval_cand << " " << currState_.post << " " << old_given_new << " " << new_given_old << " " << alpha << endl; + // cout << "alpha = " << alpha << endl; + sum_alpha+=alpha; + if (alpha>=1 || alpha > dsfmt_genrand_urv(&RandomState)){ // Accept and update the state + if (this->inDomain(m_cand)) + { + nacc++; + currState_.state = m_cand; + currState_.post = eval_cand; + } + } // If state not accepted, keep previous state as the current state + + nall++; + } + currState_.alfa=sum_alpha/nSubSteps_; + + // Append the current state to the array of all past states + fullChain_.PushBack(currState_); + + // Keep track of the mode (among the locations visited so far) + // \todo maybe only store tmode_(we save the full chain anyway) + if (currState_.post > modeState_.post){ + this->updateMode(); + newMode_=true; + } + + accRatio_ = (double) nacc/nall; + + + + if (WRITE_FLAG == 1){ + + // Output to the screen + if( t % outputinfo_.freq_outscreen == 0 || t==ncalls){ + + printf("%lg %% completed; Chain step %d\n", 100.*t/ncalls,t); + printf("================= Current logpost:%f, Max logpost:%f, Accept rate:%f\n",currState_.post,modeState_.post,accRatio_); + printf("================= Current MAP params: "); + for(int ic=0;icchainDim_;ic++) + printf("par(%d)=%f ",ic,modeState_.state(ic)); + cout << endl; + + } + + // Output to file + if( t % outputinfo_.freq_chainfile == 0 || t==ncalls){ + + if(!strcmp(output.c_str(),"txt")) + this->writeChainTxt(outputinfo_.filename); + else if(!strcmp(output.c_str(),"bin")) + this->writeChainBin(outputinfo_.filename); + else + throw Tantrum((string) "Chain output type is not recognized"); + lastwrite_ = t; + } + } + + } // End of main loop + + return; +} + +void MCMC::updateMode() +{ + // Update the chain mode (MAP state) + modeState_.step=currState_.step; + modeState_.state=currState_.state; + modeState_.post=currState_.post; + modeState_.alfa=-1.0; + + return; +} + +bool MCMC::newModeFound() +{ + // Check to see if a new mode was found during last call to runChain + return newMode_; +} + +void MCMC::getAcceptRatio(double * accrat) +{ + // Returns the acceptance ratio + *accrat = accRatio_; + return; +} + +void MCMC::proposalSingleSite(Array1D& m_t,Array1D& m_cand,int dim) +{ + // Single-site proposal + m_cand=m_t; + m_cand(dim) += ( sqrt(methodinfo_.chcov(dim,dim))*dsfmt_genrand_nrv(&RandomState) ); + + return; +} + + +void MCMC::proposalAdaptive(Array1D& m_t,Array1D& m_cand,int t) +{ + int chol_info=0; + char lu='L'; + + // xm[] is the mean of m_t[] over all previous states, X_0,...,X_{t-1} + // at this stage, index t, we know X_0,X_1,...,X_{t-1} + // and we're seeking to find X_t, the new state of the chain + // also evaluate covt, the covariance matrix + + if (t == 1) { + // at the first iteration, the mean is easy and the sample covariance is 0 + methodinfo_.curmean=m_t; + methodinfo_.curcov.Resize(this->chainDim_,this->chainDim_,0.e0); + } else if( t > 1 && t < methodinfo_.adaptstep(2) ){ +// after the first iteration, start keeping track of the sample mean + for (int i=0; i < chainDim_; i++) { + methodinfo_.curmean(i) = ( methodinfo_.curmean(i)*(t-1.) + m_t(i) )/t; + } + + + + for (int i=0; i < this->chainDim_; i++) + for (int j=0; j < i+1; j++) + methodinfo_.curcov(i,j) = ( (t-2.)/(t-1.) )*methodinfo_.curcov(i,j) + + ( t/((t-1.)*(t-1.)) ) * ( m_t(i) - methodinfo_.curmean(i) )*( m_t(j) - methodinfo_.curmean(j) ); + + //transpose + for (int i=0; i < chainDim_; i++) + for (int j=i+1; j < chainDim_ ; j++) + methodinfo_.curcov(i,j) = methodinfo_.curcov(j,i) ; + + } + + + + // Jump size + double sigma = methodinfo_.gamma * 2.4 * 2.4 / (double)this->chainDim_; + + if(t ==1) { + propLCov_=methodinfo_.chcov; + + // Cholesky factorization of the proposal covariance propLCov_, done in-place + // Note, for diagonal covariances, this is an overkill + FTN_NAME(dpotrf)(&lu,&chainDim_, propLCov_.GetArrayPointer(),&chainDim_,&chol_info); + + } + + if ( ( t > methodinfo_.adaptstep(0) ) && ( (t % methodinfo_.adaptstep(1) ) == 0 ) && t <= methodinfo_.adaptstep(2) ) { + + for (int i=0; i < chainDim_; i++) + for (int j=0; j < chainDim_; j++) + propLCov_(i,j) = sigma*( methodinfo_.curcov(i,j) + (i==j)*methodinfo_.eps_cov ) ; + + methodinfo_.chcov=propLCov_; + + + // Cholsky factorization of the proposal covariance propLCov_, done in-place + FTN_NAME(dpotrf)(&lu,&chainDim_, propLCov_.GetArrayPointer(),&chainDim_,&chol_info); + + // Catch the error in Cholesky factorization + if (chol_info != 0 ) { + printf("Error in Cholesky factorization, info=%d, printing the matrix below:\n", chol_info); + + for(int i=0;i xi(chainDim_,0.e0); + for (int i=0; i < chainDim_; i++) { + xi(i)=dsfmt_genrand_nrv(&RandomState); + double Lnrv=0.0; + for (int j=0; j < i+1; j++) { + Lnrv += propLCov_(i,j)*xi(j); + } + m_cand(i) += Lnrv; + } + + + + return; + +} + +void MCMC::proposalMALA(Array1D& m_t,Array1D& m_cand) +{ + Array1D grads; + gradlogPosterior_(m_t,grads,NULL); + cout << "grads= " << grads(0) << " " << grads(1) << endl; + m_cand=m_t; + for (int i=0; i < chainDim_; i++) { + m_cand(i) += epsMALA_*epsMALA_*grads(i)/2.; + m_cand(i) += epsMALA_*dsfmt_genrand_nrv(&RandomState); + } + + + return; +} + + +void MCMC::proposalMMALA(Array1D& m_t,Array1D& m_cand) +{ + + int chol_info=0; + char lu='L'; + + Array1D grads; + this->gradlogPosterior_(m_t,grads,NULL); + Array2D mtensorinv; + this->metricTensor_(m_t,mtensorinv,NULL); + m_cand=m_t; + + Array1D mtggrads; + prodAlphaMatVec(mtensorinv, grads, 1.0, mtggrads) ; + + Array2D sqrt_mtensorinv; + sqrt_mtensorinv=mtensorinv; + FTN_NAME(dpotrf)(&lu,&chainDim_, sqrt_mtensorinv.GetArrayPointer(),&chainDim_,&chol_info); + // Catch the error in Cholesky factorization + if (chol_info != 0 ) + printf("Error in Cholesky factorization, info=%d\n", chol_info); + + + for (int i=0; i < chainDim_; i++) { + m_cand(i) += epsMALA_*epsMALA_*mtggrads(i)/2.; + for (int j=0; j < i+1; j++) { + m_cand(i) += epsMALA_*sqrt_mtensorinv(i,j)*dsfmt_genrand_nrv(&RandomState); + } + } + + + return; +} + +void MCMC::appendMAP() +{ + this->fullChain_.PushBack(modeState_); + return; +} + +void MCMC::writeChainTxt(string filename) +{ + + // Choose whether write or append + char* writemode="w"; + if (lastwrite_>=0 || namePrepend_) + writemode="a"; + + // Open the text file + FILE* f_out; + if(!(f_out = fopen(filename.c_str(),writemode))){ + printf("writeChain: could not open file '%s'\n",filename.c_str()); + exit(1); + } + + // Write to the text file + for(int i=this->lastwrite_+1;ifullChain_.XSize();i++){ + fprintf(f_out, "%d ", this->fullChain_(i).step); + for(int ic=0;icchainDim_;ic++) + fprintf(f_out, "%24.16lg ", this->fullChain_(i).state(ic)); + fprintf(f_out, "%24.16lg %24.16lg \n", this->fullChain_(i).alfa, this->fullChain_(i).post); + + } + + // Close the text file + if(fclose(f_out)){ + printf("writeChain: could not close file '%s'\n",filename.c_str()); + exit(1); + } + + // Report + printf("Written the states %d - %d to the text file %s\n", this->lastwrite_+1, this->fullChain_.XSize()-1, filename.c_str()); + + return ; + +} + +void MCMC::writeFullChainTxt(string filename, Array1D fullchain) +{ + + // Open the text file in a write mode + char* writemode="w"; + + // Append if the names already prepended + if (namePrepend_) + writemode="a"; + + FILE* f_out; + if(!(f_out = fopen(filename.c_str(),writemode))){ + printf("writeChain: could not open file '%s'\n",filename.c_str()); + exit(1); + } + + // Write the full chain + for(int i=0;ichainDim_;ic++) + fprintf(f_out, "%24.16lg ", fullchain(i).state(ic)); + fprintf(f_out, "%24.16lg %24.16lg \n", fullchain(i).alfa,fullchain(i).post); + + } + + // Closte the file + if(fclose(f_out)){ + printf("writeChain: could not close file '%s'\n",filename.c_str()); + exit(1); + } + + // Report + printf("Written the full chain out to text file %s\n",filename.c_str()); + + return ; + +} + + +void MCMC::writeChainBin(string filename) +{ + + // Choose whether write or append + char* writemode="wb"; + if (lastwrite_>=0) + writemode="ab"; + + // Open the binary file + FILE* f_out; + if(!(f_out = fopen(filename.c_str(),writemode))){ + printf("writeChain: could not open file '%s'\n",filename.c_str()); + exit(1); + } + + + // Write to the binary file + for(int i=this->lastwrite_+1;ifullChain_.XSize();i++){ + fwrite(&(this->fullChain_(i).step), sizeof(int), 1, f_out); + fwrite(fullChain_(i).state.GetArrayPointer(),this->chainDim_*sizeof(double),1, f_out); + fwrite(&(this->fullChain_(i).alfa), sizeof(double), 1, f_out); + fwrite(&(this->fullChain_(i).post), sizeof(double), 1, f_out); + } + + // CLose the binary file + if(fclose(f_out)){ + printf("writeChain: could not close file '%s'\n",filename.c_str()); + exit(1); + } + + // Report + printf("Written the states %d - %d to the binary file %s\n",this->lastwrite_+1, this->fullChain_.XSize()-1, filename.c_str()); + + return ; + +} + +void MCMC::parseBinChain(string filename, Array1D& readchain) +{ + double tmp; + int readstep,i=0; + + FILE *fb = fopen(filename.c_str(),"rb"); + + chainstate curchain; + // Read the binary file and write to an array of chain states + while( fread(&readstep,sizeof(int),1,fb) ) { + + curchain.step=readstep; + assert(readstep==i); + + curchain.state.Resize(this->chainDim_); + + fread(curchain.state.GetArrayPointer(),this->chainDim_*sizeof(double),1,fb); + fread(&tmp,sizeof(double),1,fb); + curchain.alfa=tmp; + fread(&tmp,sizeof(double),1,fb); + curchain.post=tmp; + readchain.PushBack(curchain); + i++; +} + + fclose(fb); + + return; +} + + +double MCMC::getMode(Array1D& MAPparams) +{ + + + //for(int ic=0;icchainDim_;ic++) + MAPparams=modeState_.state; + + return modeState_.post; +} + + +double MCMC::probOldNew(Array1D& a, Array1D& b) +{ + string method=methodinfo_.type; + + double logprob; + Array1D gradb; + + if(!strcmp(method.c_str(),"mala")){ + gradlogPosterior_(b,gradb,NULL); + double eps2=this->epsMALA_*this->epsMALA_; + Array1D bmean(this->chainDim_,0.e0); + Array1D diagcov(this->chainDim_,0.e0); + + for (int i=0;i& x,Array1D& mu,Array1D& sig2) +{ + double pi=4.0*atan(1.0); + + double value=0.e0; + + // \todo Put sanity checks on dimensions + + for (int i=0;ichainDim_;i++){ + value -= 0.5*log(2.*pi*sig2(i)); + value -= (x(i)-mu(i))*(x(i)-mu(i))/(2.0*sig2(i)); + } + return value; +} + + +bool MCMC::inDomain(Array1D& m) +{ + int nd = m.XSize(); + + for (int id=0;idUpper_(id)) + return false; + } + + return true; +} + +void MCMC::setLower(double lower, int i) +{ + this->Lower_(i)=lower; + lower_flag_(i)=1; + + return; +} + +void MCMC::setUpper(double upper, int i) +{ + this->Upper_(i)=upper; + upper_flag_(i)=1; + return; +} + + +void MCMC::setChainDim(int chdim) +{ + this->chainDim_=chdim; chaindimInit_=true; + this->setDefaultDomain(); + + return; +} + +void MCMC::setDefaultDomain() +{ + this->Lower_.Resize(this->chainDim_,-DBL_MAX); + this->Upper_.Resize(this->chainDim_,DBL_MAX); + this->lower_flag_.Resize(this->chainDim_,0); + this->upper_flag_.Resize(this->chainDim_,0); + + + return; +} diff --git a/cpp/lib/mcmc/mcmc.h b/cpp/lib/mcmc/mcmc.h new file mode 100644 index 00000000..94214442 --- /dev/null +++ b/cpp/lib/mcmc/mcmc.h @@ -0,0 +1,329 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2013) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file mcmc.h +/// \author K. Sargsyan, C. Safta, B. Debusschere, 2012 - +/// \brief Header file for the Markov chain Monte Carlo class + +#ifndef UQTKMCMC_H_SEEN +#define UQTKMCMC_H_SEEN + + +#include "dsfmt_add.h" + +#include +#include +#include +#include + +using namespace std; // needed for python string conversion + +//***************************************** +class LikelihoodBase{ +public: + virtual double eval(Array1D&){return 3.14;}; + virtual ~LikelihoodBase(){}; +}; +//***************************************** + +/// \class MCMC +/// \brief Markov Chain Monte Carlo class. +/// Implemented single-site and adaptive MCMC algorithms +class MCMC { +public: + /// \brief Constructor, given a pointer to logPosterior function, a pointer to additional info, e.g. data + /// and the chain dimaensionality + MCMC(double (*logposterior)(Array1D&, void *), void *postinfo); + /// \brief Dummy constructor + MCMC(){}; + + //***************************************** + + MCMC(LikelihoodBase& L); + int WRITE_FLAG; + void setWriteFlag(int I); + void resetChainState(); + dsfmt_t RandomState; + + + //***************************************** + + /// \brief Destructor + ~MCMC(){}; + + /// \brief Set the gradient function + void setGradient(void (*gradlogPosterior)(Array1D&, Array1D&, void *)); + /// \brief Set the metric tensor function + void setMetricTensor(void (*metricTensor)(Array1D&, Array2D&, void *)); + + /// \brief Set defaults + void initDefaults(); + + /// \brief Print chain information on the screen + void printChainSetup(); + + /// \brief Set chain dimensionality + void setChainDim(int chdim) ; + + /// \brief Initialize proposal covariance matrix given as a 2d-array + /// For aMCMC, this matrix is used only before adaptivity starts + void initChainPropCov(Array2D& propcov); + /// \brief Initialize proposal covariance matrix given its 1d-array diagonal + /// For aMCMC, this matrix is used only before adaptivity starts + void initChainPropCovDiag(Array1D& sig); + /// \brief Returns proposal covariance matrix + void getChainPropCov(Array2D& propcov); + // / \brief Initialize the method used, 'am' or 'ss' + void initMethod(string method); + /// \brief Initialize adaptivity step parameters for aMCMC + void initAdaptSteps(int adaptstart,int adaptstep, int adaptend); + /// \brief Initialize the scaling factor gamma for aMCMC + void initAMGamma(double gamma); + /// \brief Initialize the covariance 'nugget' for aMCMC + void initEpsCov( double eps_cov); + /// \brief Initialize epsilon for MALA + void initEpsMALA(double eps_mala); + + /// \brief Set output specification, type('txt' or 'bin'), filename, frequency of outputs to the file and to screen. + void setOutputInfo(string outtype, string file,int freq_file, int freq_screen); + + /// \brief Set the indicator to confirm that the names of parameters are prepended in the output file + void namesPrepended() {this->namePrepend_=true; return;} + + /// \brief Get the name of the chain file + string getFilename(){return this->outputinfo_.filename;} + + /// \brief Reset to a new chain file + void resetChainFilename(string filename){this->fullChain_.Clear(); this->lastwrite_=-1; this->outputinfo_.filename=filename; return;} + + /// \brief The optimization routine + void runOptim(Array1D& start); + + /// \brief The actual function that generates MCMC + void runChain(int ncalls, Array1D& chstart); + + /// \brief Structure that holds the chain state information + struct chainstate{ + int step; + Array1D state; + double alfa; + double post; + }; + + /// \brief An auxiliary function to parse the binary file and produce an array of chain-states + void parseBinChain(string filename, Array1D& readchain); + /// \brief Write an array of chain-states to a file + void writeFullChainTxt(string filename, Array1D fullchain); + /// \brief Get full chain as an array of chain-states + void getFullChain(Array1D& readchain) { readchain=fullChain_; return;} + /// \brief Append MAP state to the end + void appendMAP(); + + + /// \brief Get MAP parameters + double getMode(Array1D& MAPparams); + + /// \brief Check to see if a new mode was found during last call to runChain + bool newModeFound(); + + /// \brief Get the chain's acceptance ratio + void getAcceptRatio(double * accrat); + + /// \brief Get the MCMC chain dimensionality + int GetChainDim() const {return this->chainDim_;} + + /// \brief Function to evaluate the log-posterior + double evalLogPosterior(Array1D& m); + + /// \brief Function to evaluate the gradient of log-posterior + void evalGradLogPosterior(Array1D& m, Array1D& grads); + + /// \brief Set random generation seed + void setSeed(int seed); + + /// \brief Check if a point is in the domain + bool inDomain(Array1D& m); + + /// \brief Set lower bounds + void setLower(double lower, int i); + /// \brief Set upper bounds + void setUpper(double upper, int i); + /// \brief Set default unbounded domain + void setDefaultDomain(); + + /// \brief Get samples of the chain with burnin and thining + void getSamples(int burnin, int every,Array2D& samples); + /// \brief Get all samples of the chain + void getSamples(Array2D& samples); + +private: + + //***************************************** + int FLAG; + LikelihoodBase* L_; + //***************************************** + + /// \brief Void pointer to the posterior info (e.g. data) + + /// \brief Chain dimensionality + int chainDim_; + + /// \brief Pointer to log-posterior function (of tweaked parameters and a void pointer to any other info) + /// this pointer is set i the constructor to a user-defined function + double (*logPosterior_)(Array1D&, void *); + void (*gradlogPosterior_)(Array1D&, Array1D&, void *); + void (*metricTensor_)(Array1D&, Array2D&, void *); + + /// \brief Void pointer to the posterior info (e.g. data) + void *postInfo_; + + /// \brief The Cholesky factor(square-root) of proposal covariance + Array2D propLCov_; + + /// \brief Random seed for MCMC + int seed_; + + /// \brief The number of proposal steps within one MCMC step (=1 for AMCMC, =chaindim for MCMC_SS) + int nSubSteps_; + + /// \brief Generating the proposal candidate vector of parameters according to the adaptive MCMC algorithm + void proposalAdaptive(Array1D& m_t,Array1D& m_cand,int t); + /// \brief Generating the proposal candidate vector of parameters according to the Single-Site algorithm + void proposalSingleSite(Array1D& m_t,Array1D& m_cand,int dim); + /// \brief Generating the proposal candidate vector of parameters according to the MALA algorithm + void proposalMALA(Array1D& m_t,Array1D& m_cand); + /// \brief Generating the proposal candidate vector of parameters according to the MMALA algorithm + void proposalMMALA(Array1D& m_t,Array1D& m_cand); + + /// \brief Evaluate old|new and new|old probabilities + double probOldNew(Array1D& a, Array1D& b); + + /// \brief Evaluate MVN + double evallogMVN_diag(Array1D& x,Array1D& mu,Array1D& sig2); + + + /// \brief A structure to hold method-specific parameters + struct methodpar + { + /// In adaptive MCMC, covariance of the chain values sampled so far + Array2D curcov; + /// In adaptive MCMC, mean of the chain values sampled so far + Array1D curmean; + /// In adaptive MCMC, the coefficient behind the covariance scaling factor + double gamma; + /// In adaptive MCMC, the offset epsilon for Cholesky to be computationally feasible + double eps_cov; + /// In adaptive MCMC, a size=3 vector (t_start,t_step,t_end) that indicates + /// when the adaptivity starts, how often the proposal covariance is updated and when the adaptivity ends, respectively. + Array1D adaptstep; + /// Chain proposal distributions (before the adaptivity starts) + Array2D chcov; + /// Method type, 'am' or 'ss' + string type; + } methodinfo_; + + /// \brief Epsilon for MALA algorithm + double epsMALA_; + + /// \brief A structure to hold parameters of output specification + struct outputpar + { + /// Frequency of printing the chain progress on screen + int freq_outscreen; + /// Frequency of printing the chain progress to a file + int freq_chainfile; + /// The name of the file + string filename; + /// The output type, 'txt' or 'bin' + string type; + } outputinfo_; + + /// \brief The current chain state + chainstate currState_; + /// \brief The current MAP state + chainstate modeState_; + + /// \brief Array of chain states + Array1D fullChain_; + + /// \brief Function to update the chain mode, i.e. the MAP location + void updateMode(); + + /// \brief Write the full chain as a text + void writeChainTxt(string filename); + /// \brief Write the full chain as a binary file + void writeChainBin(string filename); + /// \brief Indicates up to which state of the chain is already written to files + int lastwrite_; + /// \brief Indicates up to which state of the chain is already written to files + bool namePrepend_; + + /// \brief Flag to indicate whether a new mode is found during last call to runChain + bool newMode_; + + /// \brief Acceptance Ratio of the chain + double accRatio_; + + //@{ + /// \brief Flag to indicate whether the corresponding parameters are initialized or not + bool chaindimInit_; + bool propcovInit_; + bool methodInit_; + bool outputInit_; + bool adaptstepInit_; + bool gammaInit_; + bool epscovInit_; + bool epsMalaInit_; + //@} + + /// \brief Flag that indicates whether gradient information is given or not + bool gradflag_; + /// \brief Flag that indicates whether tensor information is given or not + bool tensflag_; + + //@{ + /// \brief Default + string default_method_; + double default_gamma_; + double default_eps_cov_; + double default_eps_mala_; + //@} + + /// \brief Lower bounds + Array1D Lower_; + /// \brief Upper bounds + Array1D Upper_; + + ///\brief Lower bound existence flags + Array1D lower_flag_; + ///\brief Upper bound existence flags + Array1D upper_flag_; + + +}; + +#endif /* UQTKMCMC_H_SEEN */ + diff --git a/cpp/lib/pce/CMakeLists.txt b/cpp/lib/pce/CMakeLists.txt new file mode 100644 index 00000000..ac8b7706 --- /dev/null +++ b/cpp/lib/pce/CMakeLists.txt @@ -0,0 +1,24 @@ +project(UQTk) + +SET(pce_HEADERS + PCSet.h + PCBasis.h + ) + +add_library(uqtkpce PCBasis.cpp PCSet.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) + +include_directories (../../../dep/slatec) +include_directories (../../../dep/dsfmt ) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtkpce DESTINATION lib) + +# Install the header files +INSTALL(FILES ${pce_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/pce/PCBasis.cpp b/cpp/lib/pce/PCBasis.cpp new file mode 100644 index 00000000..e2eb325e --- /dev/null +++ b/cpp/lib/pce/PCBasis.cpp @@ -0,0 +1,559 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file PCBasis.cpp +/// \author B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 - +/// \brief Univariate PC class + +#include "PCBasis.h" +#include "error_handlers.h" +#include "uqtkconfig.h" +#include + +#include "quad.h" +#include "arrayio.h" +#include "pcmaps.h" +#include "combin.h" + +#include +#include +#include +#include +using namespace std; // needed for python string conversion + +PCBasis::PCBasis( const string type, const double alpha, const double betta, const int maxord): + type_(type), maxord_(maxord), alpha_(alpha), beta_(betta) +{ + + // Make sure a valid basis type is requested + if(!strcmp(type_.c_str(),"HG") || !strcmp(type_.c_str(),"WH") || !strcmp(type_.c_str(),"HER") || !strcmp(type_.c_str(),"HERMITE")){ + narg_=0; + type_ = "HG"; // Hermite-Gaussian + } else if (!strcmp(type_.c_str(),"LU") || !strcmp(type_.c_str(),"LEG") || !strcmp(type_.c_str(),"LEGENDRE")){ + narg_ = 0; + type_ = "LU"; // Legendre-Uniform + } else if (!strcmp(type_.c_str(),"LU_N") || !strcmp(type_.c_str(),"LEG_N") || !strcmp(type_.c_str(),"LEGENDRE_N")){ + narg_ = 0; + type_ = "LU_N"; // Legendre-Uniform-Normalized + } else if (!strcmp(type_.c_str(),"GLG") || !strcmp(type_.c_str(),"LG") || !strcmp(type_.c_str(),"LAG") || !strcmp(type_.c_str(),"LAGUERRE")){ + narg_ = 1; + type_ = "GLG"; // Laguerre-Gamma + } else if (!strcmp(type_.c_str(),"JB") || !strcmp(type_.c_str(),"BJ") || !strcmp(type_.c_str(),"JAC") || !strcmp(type_.c_str(),"JACOBI")){ + narg_ = 2; + type_ = "JB"; // Jacobi-Beta + } else if (!strcmp(type_.c_str(),"SW") || !strcmp(type_.c_str(),"GW") || !strcmp(type_.c_str(),"WIG") || !strcmp(type_.c_str(),"WIGERT")){ + narg_ = 2; + type_ = "SW"; // Gauss-Wigert, or Stieltjes-Wigert (lognormal) + } + else if (!strcmp(type_.c_str(),"pdf")){ + narg_ = 0; + type_ = "pdf"; // Custom + } + else { + string err_message = (string) "PCBasis::PCBasis(): requested basis type, " + type_ + + (string) ", is not supported"; + throw Tantrum(err_message); + } + + // The default implementation relies on N_q=p+1 quadrature points, where p is the maximal order and N_q is the number of quadrature points + this->Init1dQuadPoints(maxord+1); + this->Eval1dBasisAtQuadPoints(); + this->Eval1dNormSq(maxord); + + // Seed for random number generator in case we need to sample + // the basis functions + int startSeed = 1; + this->SeedRandNumGen(startSeed); + + return; +} + +void PCBasis::Init1dQuadPoints(int nqdpts) +{ + // Move strings to char*, since Quad class needs char* + char type_c[10]; + strcpy(type_c, type_.c_str()); + Quad spRule(type_c,(char *)"full",1,nqdpts,alpha_,beta_); // CHECK! + spRule.SetRule(); + + // Get the integration rule information + spRule.GetRule(quadPoints_, quadWeights_,quadIndices_); + + return; +} + +void PCBasis::Eval1dBasisAtQuadPoints() +{ + Array1D quadPoints1d; + for(int iq=0;iq<(int)quadPoints_.XSize();iq++) + quadPoints1d.PushBack(quadPoints_(iq,0)); + + this->Eval1dBasisAtCustPoints(psi1d_,maxord_,quadPoints1d); + + + return; +} + +void PCBasis::Eval1dBasisAtCustPoints(Array2D& psi,int kord, const Array1D& custPoints) +{ + + int npts=custPoints.XSize(); + + psi.Resize(npts,kord+1,0.e0); + + // Evaluate the basis functions at each of the quadrature points + for(int isp=0; isp < npts; isp++){ + // Define a temporary array to store the basis + // values in for this quadrature point per dimensions + Array1D basisVals(kord+1); + + this->EvalBasis(custPoints(isp),basisVals); + + // Store the results back in the psi_ array + for(int iord=0; iord < kord+1; iord++) + psi(isp,iord) = basisVals(iord); + + } + + return; + +} + + +double PCBasis::EvalBasis(const double &xi, Array1D &basisEvals) const +{ + + // Get the order, up to which the Basis is computed + int kord=basisEvals.Length()-1; + + return (this->EvalBasis(xi, kord, basisEvals.GetArrayPointer())); + +} + +double PCBasis::EvalBasis(const double &xi, const int kord, double *basisEvals) const +{ + + // Use Recursion formulas to evaluate polynomials at the requested xi value + if(!strcmp(type_.c_str(),"HG")){ // Hermite-Gaussian + + basisEvals[0] = 1.e0; + + if(kord > 0){ + basisEvals[1] = xi; + for(int iord=2; iord < kord+1; iord++){ + basisEvals[iord] = xi*basisEvals[iord-1]-(double)(iord-1)*basisEvals[iord-2]; + } + } /* done if kord>0 for HG */ + + } else if (!strcmp(type_.c_str(),"LU")){ // Legendre-Uniform + + double ca,cb; + basisEvals[0] = 1.e0; + if(kord > 0){ + basisEvals[1] = xi; + for(int iord=2; iord < kord+1; iord++){ + ca = (2.e0*(double)(iord-1) + 1.e0)*xi; + cb = (double)(iord-1); + basisEvals[iord] = (ca*basisEvals[iord-1] - cb*basisEvals[iord-2])/(double)(iord); + } + } /* done if kord>0 for LU */ + + } else if (!strcmp(type_.c_str(),"LU_N")){ // Legendre-Uniform-Normailzed + + double ca,cb; + basisEvals[0] = 1.e0; + if(kord > 0){ + basisEvals[1] = xi*sqrt(3.0); + for(int iord=2; iord < kord+1; iord++){ + ca = sqrt(2.e0*(double)(iord-1) + 1.e0)*xi; + cb = (double)(iord-1)/sqrt(2.e0*(double)(iord-2) + 1.e0); + basisEvals[iord] = sqrt(2.e0*(double)(iord) + 1.e0)*(ca*basisEvals[iord-1] - cb*basisEvals[iord-2])/(double)(iord); + } + } /* done if kord>0 for LU_N */ + + } else if (!strcmp(type_.c_str(),"GLG")){ // Laguerre-Gamma + + double ca,cb; + basisEvals[0] = 1.e0; + if(kord > 0){ + basisEvals[1] = -xi + alpha_ + 1.e0; + for(int iord=2; iord < kord+1; iord++){ + ca = 2.e0*(double)(iord-1) + alpha_ + 1.e0 - xi; + cb = (double)(iord-1) + alpha_; + basisEvals[iord] = (ca*basisEvals[iord-1] - cb*basisEvals[iord-2])/(double)(iord); + } + } /* done if kord>0 for GLG*/ + + } else if (!strcmp(type_.c_str(),"JB")){ // Jacobi-Beta + + double ca,cb,cc; + basisEvals[0] = 1.e0; + if(kord > 0){ + basisEvals[1] = (alpha_-beta_)/2.e0+xi*(alpha_+beta_+2.e0)/2.e0; + for(int iord=2; iord < kord+1; iord++){ + ca = (2.e0*(double)(iord) + alpha_ + beta_ - 1.e0)*(alpha_*alpha_-beta_*beta_) + xi*(2.e0*(double)(iord)+alpha_+beta_-2.e0)*(2.e0*(double)(iord)+alpha_+beta_-1.e0)*(2.e0*(double)(iord)+alpha_+beta_); + cb = 2.e0*((double)(iord-1) + alpha_)*((double)(iord-1) + beta_)*(2.e0*(double)(iord) + alpha_+beta_); + cc = 2.e0*(double)(iord)*(double(iord)+alpha_+beta_)*(2.e0*(double)(iord-1)+alpha_+beta_); + basisEvals[iord] = (ca*basisEvals[iord-1] - cb*basisEvals[iord-2])/cc; + } + } /* done if kord>0 for JB */ + + } else if (!strcmp(type_.c_str(),"SW")){ // Wigert-Lognormal + + double ca,cb,cc; + double ee = exp(beta_*beta_/2.); + double eesq = ee*ee ; + basisEvals[0] = 1.e0; + if(kord > 0){ + basisEvals[1] = xi-ee*exp(alpha_); + for(int iord=2; iord < kord+1; iord++){ + ca = xi-exp(alpha_)*pow(ee,2.e0*double(iord)-3.e0)*((eesq+1.0)*pow(eesq,(double)(iord)-1.e0)-1.e0); + cb = exp(2.e0*alpha_)*pow(eesq,3.e0*(double)(iord)-5.e0)*(pow(ee,2.e0*(double)(iord-1))-1.e0); + cc = 1.e0; + basisEvals[iord] = (ca*basisEvals[iord-1] - cb*basisEvals[iord-2])/cc; + } + } /* done if kord>0 for SW */ + + } else if (!strcmp(type_.c_str(),"pdf")){ // Custom + Array2D albe; + read_datafileVS(albe,"ab.dat"); + if ((int)albe.XSize() 0){ + basisEvals[1] = xi-albe(0,0); + for(int iord=2; iord < kord+1; iord++){ + ca = xi-albe(iord-1,0); + cb = albe(iord-1,1); + cc = 1.e0; + basisEvals[iord] = (ca*basisEvals[iord-1] - cb*basisEvals[iord-2])/cc; + } + } /* done if kord>0 for pdf */ + } else { + string err_message = (string) "PCBasis:: EvalBasis: invalid basis type"; + throw Tantrum(err_message); + } + + // Return the basis value for the highest order + return basisEvals[kord]; + +} + +/*********************************************************** +Derivative methods +*************************************************************/ + +/***************************************************** +1st Derivatives of 1d Legendre Polynomials +******************************************************/ +void PCBasis::EvalDerivBasis(const double& xi, Array1D& basisDEvals){ + + if (!strcmp(type_.c_str(),"LU")){ + // Only works for non-normalized Legendre uniform PCE + + int kord=basisDEvals.Length()-1; + + // get basis evals at xi (not derivative) + Array1D basisEvals(kord+1,0.0); + EvalBasis(xi, basisEvals); + + basisDEvals(0) = 0.e0; // derivative of zeroth order leg poly + + if(kord > 0){ + + basisDEvals(1) = 1; // derivative of first legendre poly. + + for(int iord=2; iord < kord+1; iord++){ + basisDEvals(iord) = basisDEvals(iord-2) + (2*iord - 1)*basisEvals(iord-1); + } + } + } + else{ + string err_message = (string) "PCBasis:: EvalBasis: invalid basis type"; + throw Tantrum(err_message); + } + + return; + +} + +void PCBasis::Eval1dDerivBasisAtCustPoints(Array2D& dpsi,int kord, const Array1D& custPoints){ + + if (!strcmp(type_.c_str(),"LU")){ + + int npts=custPoints.XSize(); + dpsi.Resize(npts,kord+1,0.e0); + + // Evaluate the derivative of the basis functions at each of the quadrature points + for(int isp=0; isp < npts; isp++){ + // Define a temporary array to store the basis + // values in for this quadrature point per dimensions + Array1D basisDVals(kord+1); + + EvalDerivBasis(custPoints(isp),basisDVals); + + // Store the results back in the psi_ array + for(int iord=0; iord < kord+1; iord++) + dpsi(isp,iord) = basisDVals(iord); + + } + } + else{ + string err_message = (string) "PCBasis:: EvalBasis: invalid basis type"; + throw Tantrum(err_message); + } +} + +/***************************************************** +2nd Derivatives of 1d Legendre Polynomials +******************************************************/ +void PCBasis::Eval2ndDerivBasis(const double& xi,Array1D& ddP) { + + if (!strcmp(type_.c_str(),"LU")) { + int kord=ddP.Length()-1; + Array1D P(ddP.Length(),0); + Array1D dP(ddP.Length(),0); + + EvalBasis(xi,P); + EvalDerivBasis(xi,dP); + + Array1D temp(3,0); + temp(0) = 0.0; temp(1) = 0.0; temp(2) = 3.0; + + if (kord > 2) { + ddP(0)=0.0; + ddP(1)=0.0; + ddP(2)=3.0; + for (int n=1; n& psi, int kord, Array1D& custPoints) { + + if (!strcmp(type_.c_str(),"LU")){ + int npts=custPoints.XSize(); + + psi.Resize(npts,kord+1,0.0); + + for (int i=0; i ddbasisVals(kord+1); + + Eval2ndDerivBasis(custPoints(i),ddbasisVals); + + for(int iord=0; iord& randSamples) +{ + int nSamples = randSamples.Length(); + + // get the random variable samples + this->GetRandSample(randSamples.GetArrayPointer(), nSamples); + + return; +} + +void PCBasis::GetRandSample(double* randSamples, const int& nSamp) +{ + // Make local copy of nSamp to preserve const requirement on nSamp + int nSamples = nSamp; + + + // Depending on the basis type, pick the right random number generator + if(!strcmp(type_.c_str(),"HG")){ // Hermite-Gaussian + for (int i = 0 ; i < nSamples ; i++ ) + randSamples[i] = dsfmt_genrand_nrv(&rnstate_); + } else if (!strcmp(type_.c_str(),"LU")){ // Legendre-Uniform + for (int i = 0 ; i < nSamples ; i++ ) + randSamples[i] = dsfmt_genrand_urv_sm(&rnstate_,-1.0,1.0); + } else if (!strcmp(type_.c_str(),"LU_N")){ // Legendre-Uniform-Normalized + for (int i = 0 ; i < nSamples ; i++ ) + randSamples[i] = dsfmt_genrand_urv_sm(&rnstate_,-1.0,1.0); + } else if (!strcmp(type_.c_str(),"GLG")){ // Laguerre-Gamma + for (int i = 0 ; i < nSamples ; i++ ) + randSamples[i] = dsfmt_genrand_urv_sm(&rnstate_,-1.0,1.0); + // Map to gamma random variable + for (int i = 0 ; i < nSamples ; i++ ) randSamples[i] = PCtoPC(randSamples[i], "LU", 0, 0, "LG", alpha_, 0) ; + + } else if (!strcmp(type_.c_str(),"JB")){ // Jacobi-Beta + + for (int i = 0 ; i < nSamples ; i++ ) + randSamples[i] = dsfmt_genrand_urv_sm(&rnstate_,-1.0,1.0); + // Map to beta random variable + for (int i = 0 ; i < nSamples ; i++ ) randSamples[i] = PCtoPC(randSamples[i], "LU", 0, 0, "JB", alpha_, beta_) ; + + } else if (!strcmp(type_.c_str(),"SW")){ // Stieltjes-Wigert + + for (int i = 0 ; i < nSamples ; i++ ) + randSamples[i] = exp(dsfmt_genrand_nrv_sm(&rnstate_,alpha_,beta_)); + + } else if (!strcmp(type_.c_str(),"pdf")){ // Custom-PDF + + string err_message = (string) "PCBasis::GetRandSample(): Custom-PDF sampling is not implemented yet"; + throw Tantrum(err_message); + + } + else { + string err_message = (string) "PCBasis::GetRandSample(): requested basis type, " + type_ + + (string) ", is not supported"; + throw Tantrum(err_message); + } + + return; +} + + +void PCBasis::GetQuadRule(Array2D& qPoints, Array1D& qWeights, Array2D& qIndices) +{ +this->GetQuadPoints(qPoints); +this->GetQuadWeights(qWeights); +this->GetQuadIndices(qIndices); + +return; +} + + +void PCBasis::SeedRandNumGen(const int& seed) +{ + + // Update the stored seed + this->rSeed_ = seed; + + // seed the appropriate random number generator + dsfmt_init_gen_rand(&(this->rnstate_), (uint32_t) rSeed_ ); + + return; +} + +void PCBasis::Eval1dNormSq(int kord) +{ + // Norms^2 of basis functions + psi1dSq_.Resize(kord+1,0.e0); + + // Take the norm of f^2 by numerical quadrature + for(int iord=0;iord < kord+1; iord++){ + double tempSum = 0.e0; + for(int iqp=0; iqp < (int) quadPoints_.XSize(); iqp++){ + tempSum += psi1d_(iqp,iord)*psi1d_(iqp,iord)*quadWeights_(iqp); + } + psi1dSq_(iord) = tempSum; + //cout << "Norm(" << iord << ")=" << tempSum << endl; + } + return; +} + +void PCBasis::Eval1dNormSq_Exact(int kord) +{ + // Norms^2 of basis functions + psi1dSqExact_.Resize(kord+1,0.e0); + + // Take the norm of f^2 by numerical quadrature + for(int iord=0;iord < kord+1; iord++){ + psi1dSqExact_(iord) = NormSq_Exact(iord); + } + return; +} + + +double PCBasis::NormSq_Exact(int kord) +{ + + double normSq=1.e0; + if(!strcmp(type_.c_str(),"HG")){ + for (int i=2;i<=kord;i++) normSq*=i; + } + else if(!strcmp(type_.c_str(),"LU")) + normSq=1.e0/(2.e0*(double)(kord)+1.e0); + else if(!strcmp(type_.c_str(),"LU_N")) + normSq=1.e0; + else if(!strcmp(type_.c_str(),"GLG")) + normSq=exp(lgamma((double)(kord)+alpha_+1.e0)-lgamma(alpha_+1.e0)-lgamma((double)(kord)+1.e0)); + else if(!strcmp(type_.c_str(),"JB")){ + if(kord>0){ + double dk = (double) kord; + double ap1 = alpha_+1.e0; + double bp1 = beta_ +1.e0; + double abp1 = alpha_+beta_ +1.e0; + normSq = exp(lgamma(dk+ap1)+lgamma(dk+bp1)-lgamma(dk+1.e0)-lgamma(dk+abp1)-lgamma(ap1)-lgamma(bp1)+lgamma(ap1+bp1)) + /(2.e0*dk+abp1); + } + else + normSq=1.e0; + } + else if(!strcmp(type_.c_str(),"SW")){ + if(kord>0){ + //normSq=exp((2.e0*alpha_+1.e0)*kord)*(3.e0*(double)(kord)-1.e0)*beta_*beta_/2.e0; + normSq=exp((2.e0*alpha_)*kord)*exp((3.e0*(double)(kord)-1.e0)*beta_*beta_*kord/2.e0); + for(int iord=1;iord<=kord;iord++) + normSq *= (exp((double)(iord)*beta_*beta_)-1); + } + else + normSq=1.e0; + } + else if (!strcmp(type_.c_str(),"pdf")){ // Custom-PDF + + string err_message = (string) "PCBasis::NormSq_Exact(): Custom-PDF norm-squared is not implemented yet"; + throw Tantrum(err_message); + + } + else { + string err_message = (string) "PCBasis::NormSq_Exact(): requested basis type, " + type_ + + (string) ", is not supported"; + throw Tantrum(err_message); + } + + return normSq; + +} + diff --git a/cpp/lib/pce/PCBasis.h b/cpp/lib/pce/PCBasis.h new file mode 100644 index 00000000..07cf2216 --- /dev/null +++ b/cpp/lib/pce/PCBasis.h @@ -0,0 +1,239 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file PCBasis.h +/// \author B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 - +/// \brief Header file for the univariate PC class + +#ifndef PCBASIS_H_SEEN +#define PCBASIS_H_SEEN + +#include +#include +#include "Array1D.h" +#include "Array2D.h" +// #include "Array3D.h" +#include "ftndefs.h" +#include "dsfmt_add.h" + + +/// \class PCBasis +/// \brief Contains all basis type specific definitions and operations +/// needed to generate a PCSet +class PCBasis { +public: + /// \brief Constructor: initializes the univariate basis type and order + /// + /// Currently, the only valid types are Hermite-Gaussian, denoted with "HG", + /// Legendre-Uniform, denoted with "LU", or Laguerre-Gamma, denoted with "LG". + /// (Where the shape parameter for the Gamma distribution is alpha + 1 = 2) + /// \todo At some point, the basis selection should probably be implemented + /// in a more elegant way using base and inherited classes. For the time being, + /// Hermite-Gaussian or Legendre-Uniform will probably be the most commonly used + /// cases. + /// The parameters alpha and betta are relevant only for GLG, SW and JB chaoses + /// \note Maxord specifies the maximal order up to which the computations are performed + PCBasis(const string type="LU", const double alpha=0.0, const double betta=1.0, const int maxord=10); + + + /// \brief Destructor + ~PCBasis() {}; + + /// \brief Initialize the quadrature points and weights and store the information + /// in arrays quadPoints_, quadWeights_,quadIndices_ + /// \note Uses an arbitrary number of quad. points. + /// \note The default implementation relies on N_q=2*p+1 quadrature points, + /// where p is the maximal order and N_q is the number of quadrature points + /// \todo Come up with a smarter way to pick the number of quadrature points + /// \note Quadrature points are set according to the basis function type + /// \note quadPoints is a 2D array but its second dimension is equal to 1. + void Init1dQuadPoints(int qdpts); + + /// \brief Evaluate polynomial 1d basis functions at quadrature points + /// and store in the private variable psi1d_ + void Eval1dBasisAtQuadPoints(); + + /// \brief Evaluate polynomial 1d basis functions up to the order kord at custom points + /// given by an array custPoints + /// Returns the evaluations in the first argument psi, where the number of rows are + /// the number of points, and columns correspond to successive orders + void Eval1dBasisAtCustPoints(Array2D& psi,int kord, const Array1D& custPoints); + + /// \brief Evaluate 1d basis functions for the given value of random + /// variable xi. Return the value of the basis functions for all orders + /// in the passed Array1D array (indexed by their order), + /// also returns the highest-order value. + /// \note For custom 'pdf' option, a file containing the polynomial recursion + /// coefficients, called 'ab.dat', is required. + /// \todo Import the recursion coefficients in a more friendly fashion. + double EvalBasis(const double &xi, Array1D &basisEvals) const; + /// \brief Evaluate 1d basis functions for the given value of random + /// variable xi. Return the value of the basis functions for all orders + /// in the passed double * array (indexed by their order), + /// also returns the highest-order value. + double EvalBasis(const double &xi, const int kord, double *basisEvals) const; + + /// \brief Evaluate the norms (squared) of the basis functions exactly + /// and stores in the private array psi1dSqExact_ + void Eval1dNormSq_Exact(int kord); + + + /*************************************************** + New derivative functionality + ***************************************************/ + /// \brief Evaluate derivative of 1d non-normalized Legendre basis. + void EvalDerivBasis(const double& xi, Array1D& basisDEvals); + void Eval1dDerivBasisAtCustPoints(Array2D& dpsi,int kord, const Array1D& custPoints); + + void Eval2ndDerivBasis(const double& xi,Array1D& ddP); + void Eval2ndDerivCustPoints(Array2D& psi, int kord, Array1D& custPoints); + /*************************************************** + ***************************************************/ + + /// \brief Get the norms-squared of the basis functions. + /// Returns the values for each basis function in the passed Array1D array + void Get1dNormsSq(Array1D& psi1dSq) const {psi1dSq=psi1dSq_; return;} + + /// \brief Get the analytic norms-squared of the basis functions. + /// Returns the values for each basis function in the passed Array1D array + void Get1dNormsSqExact(Array1D& psi1dSqExact) const {psi1dSqExact=psi1dSqExact_; return;} + + /// \brief Get samples of the random variables associated + /// with the current PC basis functions and return them in the 1D array randSamples. + /// Take as many samples as the length of the array randSamples + /// \note This function does NOT reset the random number seed before sampling + void GetRandSample(Array1D& randSamples); + + /// \brief Get nSamp samples of the random variables associated + /// with the current PC basis functions and return them in the double* randSamples. + /// \note This function does NOT reset the random number seed before sampling + void GetRandSample(double* randSamples, const int& nSamp); + + /// \brief Get the random number generator seed + int GetSeed() const {return rSeed_;} + + /// \brief Function to (re)seed the random number generator + /// used to sample the Basis functions + void SeedRandNumGen(const int& seed); + + /// \brief Get the quadrature integration information + void GetQuadRule(Array2D& qPoints, Array1D& qWeights, Array2D& qIndices); + + /// \brief Get the quadrature points in the passed Array2D array + /// \note Although quadPoints is a 2D array, its second dimension is equal to 1 + void GetQuadPoints(Array2D& quadPoints) const { quadPoints=quadPoints_; return;} + + /// \brief Get the quadrature weights in the passed Array1D array + void GetQuadWeights(Array1D& quadWeights) const { quadWeights=quadWeights_; return;} + + /// \brief Get the quadrature points' indices in the passed Array1D array + void GetQuadIndices(Array2D& quadIndices) const { quadIndices=quadIndices_; return;} + + /// \brief Get the basis values at quadrature points in the passed Array2D array + void GetBasisAtQuadPoints(Array2D& psi1d) const { psi1d=psi1d_; return;} + + /// \brief Get the PC type + string GetPCType() const {return type_;} + + /// \brief Get the value of the parameter alpha + double GetAlpha() const {return alpha_;} + + /// \brief Get the value of the parameter beta + double GetBeta() const {return beta_;} + +private: + /// \brief Dummy default constructor, which should not be used as it is not well defined + /// Therefore we make it private so it is not accessible + /// \note All parameters are intialized to dummy values. + // PCBasis(): type_("NA") {}; + + /// \brief Dummy copy constructor, which should not be used as it is currently + /// not well defined. Therefore we make it private so it is not accessible. + /// \note I am not sure actually whether the initialization performed below + /// is legal as it requires access to private data members of the class that + /// is passed in. + PCBasis(const PCBasis &obj):type_(obj.type_) {}; + + + /// \brief Evaluate the norms (squared) of the basis functions + /// and stores in the private array psi1dSq_ + void Eval1dNormSq(int kord); + + + /// \brief Evaluate 1d norm of order kord exactly + double NormSq_Exact(int kord); + + /// \brief String indicator of type of basis functions used + string type_; + + /// \brief Array to store quadrature points + Array2D quadPoints_; + + /// \brief Array to store quadrature weights + Array1D quadWeights_; + + /// \brief Array to store quadrature point indexing; useful only for nested rules + Array2D quadIndices_; + + + /// \brief Array to store basis functions evaluated at quadrature points + /// for each order: psi1d_(iqp,iord) contains the value of the polynomial + /// chaos basis of order iord at the location of quadrature point iqp. + Array2D psi1d_; + + /// \brief Array with the norms squared of the 1D basis functions for each order + Array1D psi1dSq_; + + /// \brief Array with the exact norms squared of the 1D basis functions for each order + Array1D psi1dSqExact_; + + /// \brief Maximal order of any dimension + int maxord_; + + /// \brief Number of parameters to specify the basis + int narg_; + + /// \brief Parameter alpha for PCs that require a parameter (GLG,SW,JB) + double alpha_; + + /// \brief Parameter beta for PCs that require two parameters (SW,JB) + double beta_; + + /// \brief Random sequence state for dsfmt + /// \todo need more functionalities to get/set this variable from user + dsfmt_t rnstate_ ; + + /// \brief The seed used for the random number generators that + /// sample the xi's in the basis functions + /// + /// This seed is set to 1 during the class construction and + /// can be reset with the SeedRandNumGen function + /// \sa SeedRandNumGen + int rSeed_; + +}; + +#endif /* PCBASIS_H_SEEN */ diff --git a/cpp/lib/pce/PCSet.cpp b/cpp/lib/pce/PCSet.cpp new file mode 100644 index 00000000..9a5f6640 --- /dev/null +++ b/cpp/lib/pce/PCSet.cpp @@ -0,0 +1,2996 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file PCSet.cpp +/// \author B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 - +/// \brief Multivariate PC class + +#include "PCSet.h" +#include "PCBasis.h" +#include +#include "uqtkconfig.h" +#include "depslatec.h" +#include "quad.h" +#include "multiindex.h" +#include "minmax.h" +#include "arraytools.h" + +// Static members need to be pre-declared +int PCSet::next_index_ = 0; +PCSet::OMap_t *PCSet::omap_ = NULL; + + +PCSet::PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, const double alpha, const double betta): + spType_(sp_type), pcType_(pc_type), order_(order), nDim_(n_dim), alpha_(alpha), beta_(betta) +{ + + SetVerbosity(0); + + nPCTerms_=computeMultiIndex(nDim_,order_, multiIndex_); + + maxOrdPerDim_.Resize(this->nDim_,this->order_); + + Initialize("TotalOrder"); + + return; +} + +PCSet::PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, const string pc_seq, const double alpha, const double betta): + spType_(sp_type), pcType_(pc_type), pcSeq_(pc_seq), order_(order), nDim_(n_dim), alpha_(alpha), beta_(betta) +{ + + SetVerbosity(0); + + nPCTerms_=computeMultiIndex(nDim_,order_, multiIndex_, pcSeq_); + + maxOrdPerDim_.Resize(this->nDim_,this->order_); + + Initialize("TotalOrder"); + + return; +} + +PCSet::PCSet(const string sp_type, const Array1D& maxOrders, const int n_dim, const string pc_type, const double alpha, const double betta): + spType_(sp_type), pcType_(pc_type), maxOrders_(maxOrders), nDim_(n_dim), alpha_(alpha), beta_(betta) +{ + SetVerbosity(0); + + nPCTerms_=computeMultiIndexHDMR(nDim_,maxOrders_, multiIndex_); + + order_=maxOrders_(maxIndex(maxOrders_)); + maxOrdPerDim_.Resize(this->nDim_,this->order_); + + Initialize("HDMR"); + + return; + +} + +PCSet::PCSet(const string sp_type, const Array2D& customMultiIndex, const string pc_type, const double alpha, const double betta): + spType_(sp_type), pcType_(pc_type), nDim_(customMultiIndex.YSize()), alpha_(alpha), beta_(betta) +{ + + SetVerbosity(0); + + order_=0; + this->multiIndex_=customMultiIndex; + + this->nPCTerms_=multiIndex_.XSize(); + + for(int i=0;inPCTerms_;i++){ + int sum=0; + for(int j=0;jnDim_;j++) + sum+=customMultiIndex(i,j); + + if (order_<=sum) + order_=sum; + } + + this->ComputeMaxOrdPerDim(); + + Initialize("Custom"); + + return; + +} + + +PCSet::~PCSet() +{ + // Remove this object from the object map + OMap_t::iterator me = PCSet::omap_->find(this->my_index_); + if(PCSet::omap_ && (me != PCSet::omap_->end())) PCSet::omap_->erase(me); + + // Destroy the PC basis object + delete p_basis_; +} + +void PCSet::GetMultiIndex(int *mindex) const { + + int idx=0; + for(int ipc=0; ipc < this->nPCTerms_; ipc++){ + for(int id=0;idnDim_;id++){ + mindex[idx] = multiIndex_(ipc,id); + idx++; + } + } + + return; + +} + +void PCSet::ComputeMaxOrdPerDim() +{ + maxOrdPerDim_.Resize(nDim_,0); + for(int id=0;idnDim_;id++){ + for(int ipc=0;ipcnPCTerms_;ipc++){ + if(multiIndex_(ipc,id)>maxOrdPerDim_(id)) + maxOrdPerDim_(id)=multiIndex_(ipc,id); + } + } + + return; +} + + +void PCSet::Initialize(const string ordertype) +{ + // Echo the settings if desired + if(uqtkverbose_>0){ + cout << endl; + cout << "-----------------------------------------------------" << endl ; + cout << "Initializing PCSet class with the following settings:" << endl ; + cout << "# Dim : " << nDim_ << endl; + if(!strcmp(ordertype.c_str(),"HDMR")){ + cout << "Customized order for each HDMR-dimensionality: " << endl; + for(int i=0;i<(int)maxOrders_.XSize();i++) + cout << i << "-dim order " << maxOrders_(i) << ", "; + cout << endl; + } + else if(!strcmp(ordertype.c_str(),"Custom")){ + cout << "Customized multiIndex with " << multiIndex_.XSize() + << " basis terms."<< endl; + if(uqtkverbose_>1){ + for(int i=0;i<(int)multiIndex_.XSize();i++){ + for(int j=0;j<(int)multiIndex_.YSize();j++){ + cout << multiIndex_(i,j) << " "; + } + cout << endl; + } + cout << endl; + } + } + else + cout << "Order : " << order_ << endl; + cout << "Basis type : " << pcType_ << endl; + cout << "-----------------------------------------------------" << endl ; + } + + // Add this object to the static object map with + // an integer handle that will be used to retrieve this object + // as needed when it is called from Fortran. + if(! PCSet::omap_) PCSet::omap_ = new PCSet::OMap_t ; + this->my_index_ = PCSet::next_index_++; + (*PCSet::omap_)[my_index_] = this; + + // Initialize 1d basis class + maxorddim_=maxOrdPerDim_(maxIndex(maxOrdPerDim_)); + p_basis_ = new PCBasis(pcType_, alpha_, beta_,maxorddim_); + pcType_=p_basis_->GetPCType(); + + + // Get the norms of the multi-D basis functions + this->EvalNormSq(psiSq_); + + if (!strcmp(spType_.c_str(),"NISP")){ + this->InitNISP(); + } + else if (!strcmp(spType_.c_str(),"NISPnoq")){ + // do nothing + } + else if (!strcmp(spType_.c_str(),"ISP")){ + if(!strcmp(ordertype.c_str(),"TotalOrder")){ + this->InitISP(); + } + else{ + throw Tantrum("Intrusive implementation is only available for TotalOrder multiindex construction"); + } + } + else { + string err_message = (string) "PCSet::PCSet(): requested implementation (should be ISP, NISP or NISPnoq) type, " + spType_ + + (string) ", is not supported"; + throw Tantrum(err_message); + } + + + + return ; + +} + + +/***************************************************** +Gradient of PCE +******************************************************/ +void PCSet::dPhi_alpha(Array1D& x, Array1D& alpha, Array1D& grad){ + + // get gradient of single pce basis for a fixed x point + // where x is d-dimensional + int argmax; + int ndim = alpha.Length(); + int nord = maxVal(alpha,&argmax); + + Array2D basisEvals; + Array2D basisDEvals; + grad.Resize(ndim,0); + + p_basis_->Eval1dBasisAtCustPoints(basisEvals,nord,x); + p_basis_->Eval1dDerivBasisAtCustPoints(basisDEvals,nord,x); + + for (int i=0; i& x, Array2D& mindex, Array1D& grad, Array1D& ck){ + + // get gradient of pce model defined by a multi-index and coefficient array ck, for a fixed x point + + int ndim = mindex.YSize(); + int nindices = mindex.XSize(); + + Array2D gradtemp(nindices,ndim,0); + gradtemp.Resize(nindices,ndim,0.0); + + Array1D mindex0(ndim,0); + Array1D grad0(ndim,0); + + for (int i=0; i& x, Array2D& mindex, Array2D& grad, Array1D& ck){ + + // get gradient of pce model defined by a multi-index and coefficient array ck, for a set of x points + + int ndim = mindex.YSize(); + // int nindices = mindex.XSize(); + int nx = x.XSize(); + + // Determine the gradient + grad.Resize(nx,ndim); + grad.SetValue(0); // clear contents + + for (int i = 0; i < nx; i++){ + Array1D gradtemp(ndim,0); + + Array1D xtemp(ndim,0); + for (int j = 0; j < ndim; j++) xtemp(j) = x(i,j); + + dPhi(xtemp, mindex, gradtemp, ck); + for (int k = 0; k < ndim; k++) grad(i,k) = gradtemp(k); + } +} +/***************************************************** +Hessian of PCE +******************************************************/ +void PCSet::ddPhi_alpha(Array1D& x, Array1D& alpha, Array2D& hessian){ + + // get gradient of single pce basis for a fixed x point + // where x is d-dimensional + + int argmax; + int ndim = alpha.Length(); + int nord = maxVal(alpha,&argmax); + + Array2D basisEvals; + Array2D basisDEvals; + Array2D basisD2Evals; + Array1D grad(ndim,0.0); + hessian.Resize(ndim,ndim,0.0); + hessian.SetValue(0); + + p_basis_->Eval1dBasisAtCustPoints(basisEvals,nord,x); + p_basis_->Eval1dDerivBasisAtCustPoints(basisDEvals,nord,x); + p_basis_->Eval2ndDerivCustPoints(basisD2Evals,nord,x); + + // fill in diagonals + for (int i=0; i& x, Array2D& mindex, Array2D& hessian, Array1D& ck){ + + // get Hessian of pce model defined by a multi-index and coefficient array ck, for a fixed x point + hessian.SetValue(0); // zero elements + + int ndim = mindex.YSize(); + int nindices = mindex.XSize(); + + Array2D hesstemp1(ndim,ndim,0.0); + // Array2D hesstemp2(ndim,ndim,0.0); + hessian.Resize(ndim,ndim,0.0); + + Array1D alpha(ndim,0); + // // Array1D grad0(ndim,0); + + for (int i=0; iEvalBasisProd3(); + this->EvalBasisProd4(); + + // Set some defaults + this->rTolTaylor_ = 1.e-6 ; + this->maxTermTaylor_ = 500 ; + this->SMALL_ = 1.e-15 ; + this->rTolGMRESDiv_ = 1.e-8 ; + this->logMethod_ = TaylorSeries ; + + // Set cvode defaults + this->CVmaxord_ = 8 ; + this->CVmaxnumsteps_ = 5000 ; + this->CVinitstep_ = 2.e-8 ; + this->CVmaxstep_ = 2.e-1 ; + this->CVrelt_ = 1.e-10 ; + this->CVabst_ = 1.e-14 ; + + return; +} + +void PCSet::InitNISP() +{ + + + // Initialize the default quadrature points and evaluate basis functions at those + // locations + + + if (nDim_>7){ + cout << "PCESet.cpp::InitNISP()::Warning: Dim = " << nDim_ + << ", initializing with sparse quadrature due to high dimensionality." << endl; + + // The third argument is the level of the sparse quadrature, this may be an overkill to integrate up to 2*order_ exactly + this->SetQuadRule(pcType_,"sparse",order_+1); + cout << "Used level " << order_+1 << " sparse quadrature points for initialization." << endl; + + } + else{ + cout << "Generating " << order_+1 << "^" << nDim_ << " = "<< (int) pow(order_+1,nDim_) <<" quadrature points." << endl; + this->SetQuadRule(pcType_,"full",order_+1); + cout << "Used " << order_+1 << " quadrature points per dimension for initialization." << endl; + } + + return; +} + + +void PCSet::EvalBasisProd3() +{ + + // Allocate storage for non-zero <\Psi_i \Psi_j \Psi_k> and their indices + this->iProd2_.Clear(); + this->iProd2_.Resize(this->nPCTerms_); + this->jProd2_.Clear(); + this->jProd2_.Resize(this->nPCTerms_); + this->psiIJKProd2_.Clear(); + this->psiIJKProd2_.Resize(this->nPCTerms_); + + // Evaluate all possible <\Psi_i \Psi_j \Psi_k> that would enter the computation + // of the k-th PC coefficient in the product of two PCEs. Only retain the ones + // that are non-zero. + if(uqtkverbose_>0){ + cout << endl; + cout << "Computation of <\\Psi_i \\Psi_j \\Psi_k>'s. The number of non-zero entries for" << endl; + } + + // Get 1d quadrature of the appropriate accuracy + Array1D qdpts1d; + Array1D wghts1d; + this->SetQd1d(qdpts1d,wghts1d,int(3*maxorddim_/2)+1); + Array2D psi1d; + this->p_basis_->Eval1dBasisAtCustPoints(psi1d,maxorddim_,qdpts1d); + + + for(int k=0; k < nPCTerms_; k++){ + Array1D mi_k; + getRow(multiIndex_,k,mi_k); + + // Make sure there are no elements in the <\Psi_i \Psi_j \Psi_k> storage vector + iProd2_(k).Clear(); + jProd2_(k).Clear(); + psiIJKProd2_(k).Clear(); + for(int j=0; j < nPCTerms_; j++){ + Array1D mi_j; + getRow(multiIndex_,j,mi_j); + for(int i=0; i < nPCTerms_; i++){ + Array1D mi_i; + getRow(multiIndex_,i,mi_i); + + + + double prd=1.0; + for(int id=0; id < this->nDim_; id++){ + double int_thisdim = 0.0; + for(int iqp=0; iqp < qdpts1d.Length(); iqp++){ + int_thisdim += psi1d(iqp,mi_i(id))*psi1d(iqp,mi_j(id))*psi1d(iqp,mi_k(id))*wghts1d(iqp); + } + + prd *= int_thisdim; + } + + + // All these terms are supposed to be integer-valued actually, but + // roundoff and inaccuracies from the integration can make them + // slightly non-zero, so we check to see if they are non-zero + // by checking whether they are larger than 0.001 in magnitude + if(fabs(prd) > 0.001){ + // Store the term and its indices + iProd2_(k).PushBack(i); + jProd2_(k).PushBack(j); + psiIJKProd2_(k).PushBack(prd); + } + } + } + if(uqtkverbose_>0){ + cout << "k = " << k << " : " << psiIJKProd2_(k).Length() << endl; + } + if(uqtkverbose_>1){ + Array1D tmpw; + tmpw=psiIJKProd2_(k); + Array1D tmpi, tmpj; + tmpi=iProd2_(k); + tmpj=jProd2_(k); + for (int m=0;m<(int) psiIJKProd2_(k).Length();m++) + cout << tmpi(m) << " " << tmpj(m) << " " << k << " : " << tmpw(m) << endl; + cout << endl; + } + + } + return; + +} + +int PCSet::GetNumTripleProd() const +{ + int isum = 0; + for (int k=0; k < nPCTerms_; k++) + isum += psiIJKProd2_(k).Length(); + return isum ; +} + +void PCSet::GetTripleProd(int *nTriple, int *iProd, int *jProd, double *Cijk) const +{ + + nTriple[0] = 0; + for (int k=0; k < nPCTerms_; k++){ + nTriple[k+1] = nTriple[k]+psiIJKProd2_(k).Length(); + for (int i=0; i < (int) psiIJKProd2_(k).Length(); i++){ + iProd[nTriple[k]+i] = iProd2_(k)(i); + jProd[nTriple[k]+i] = jProd2_(k)(i); + Cijk[nTriple[k]+i] = psiIJKProd2_(k)(i); + } + } + return ; + +} + +void PCSet::GetTripleProd(Array1D& nTriple, Array1D& iProd, Array1D& jProd, Array1D& Cijk) const +{ + + // Get total number of triple products + double splength = this->GetNumTripleProd(); + cout << splength << endl; + + // Resize the containers + iProd.Resize(splength,0); + jProd.Resize(splength,0); + Cijk.Resize (splength,0); + nTriple.Resize(nPCTerms_+1,0); + + // Fill containers through the int*/double* function + this->GetTripleProd(nTriple.GetArrayPointer(), iProd.GetArrayPointer(), jProd.GetArrayPointer(), Cijk.GetArrayPointer()); + + return ; + +} + +void PCSet::EvalBasisProd4() +{ + + // Allocate storage for non-zero <\Psi_i \Psi_j \Psi_k> and their indices + this->iProd3_.Clear(); + this->iProd3_.Resize(this->nPCTerms_); + this->jProd3_.Clear(); + this->jProd3_.Resize(this->nPCTerms_); + this->kProd3_.Clear(); + this->kProd3_.Resize(this->nPCTerms_); + this->psiIJKLProd3_.Clear(); + this->psiIJKLProd3_.Resize(this->nPCTerms_); + + // Evaluate all possible <\Psi_i \Psi_j \Psi_k \Psi_l> that would enter the computation + // of the l-th PC coefficient in the product of two PCEs. Only retain the ones + // that are non-zero. + if(uqtkverbose_>0){ + cout << endl; + cout << "Computation of <\\Psi_i \\Psi_j \\Psi_k \\Psi_l>'s. The number of non-zero entries for" << endl; + } + + // Get 1d quadrature of the appropriate accuracy + Array1D qdpts1d; + Array1D wghts1d; + this->SetQd1d(qdpts1d,wghts1d,2*maxorddim_+1); + Array2D psi1d; + this->p_basis_->Eval1dBasisAtCustPoints(psi1d,maxorddim_,qdpts1d); + + + for(int l=0; l < nPCTerms_; l++){ + + Array1D mi_l; + getRow(multiIndex_,l,mi_l); + + // Make sure there are no elements in the <\Psi_i \Psi_j \Psi_k \Psi_l> storage vector + iProd3_(l).Clear(); + jProd3_(l).Clear(); + kProd3_(l).Clear(); + psiIJKLProd3_(l).Clear(); + + for (int k=0; k < nPCTerms_; k++){ + Array1D mi_k; + getRow(multiIndex_,k,mi_k); + for (int j=0; j < nPCTerms_; j++){ + Array1D mi_j; + getRow(multiIndex_,j,mi_j); + for (int i=0; i < nPCTerms_; i++){ + Array1D mi_i; + getRow(multiIndex_,i,mi_i); + + + double prd=1.0; + for(int id=0; id < this->nDim_; id++){ + double int_thisdim = 0.0; + for(int iqp=0; iqp < qdpts1d.Length(); iqp++){ + int_thisdim += psi1d(iqp,mi_i(id))*psi1d(iqp,mi_j(id))*psi1d(iqp,mi_k(id))*psi1d(iqp,mi_l(id))*wghts1d(iqp); + } + prd *= int_thisdim; + } + + + // All these terms are supposed to be integer-valued actually, but + // roundoff and inaccuracies from the integration can make them + // slightly non-zero, so we check to see if they are non-zero + // by checking whether they are larger than 0.001 in magnitude + if(fabs(prd) > 1.e-5){ + // Store the term and its indices + iProd3_(l).PushBack(i); + jProd3_(l).PushBack(j); + kProd3_(l).PushBack(k); + psiIJKLProd3_(l).PushBack(prd); + } + } + } + } + if(uqtkverbose_>0){ + cout << "l = " << l << " : " << psiIJKLProd3_(l).Length() << endl; + } + if(uqtkverbose_>1){ + Array1D tmpi, tmpj, tmpk; + Array1D tmpw; + tmpi = iProd3_(l); + tmpj = jProd3_(l); + tmpk = kProd3_(l); + tmpw = psiIJKLProd3_(l); + for (int m = 0; m < (int) psiIJKLProd3_(l).Length(); m++) + cout << tmpi(m) << " " << tmpj(m) << " " << tmpk(m) << " " << l + << " : " << tmpw(m) << endl; + cout << endl; + } + + } + + return; + +} + +int PCSet::GetNumQuadProd() const +{ + int isum = 0; + for (int k=0; k < nPCTerms_; k++) + isum += psiIJKLProd3_(k).Length(); + return isum ; +} + + +void PCSet::GetQuadProd(int *nQuad, int *iProd, int *jProd, int *kProd, double *Cijkl) const +{ + + nQuad[0] = 0; + for (int k=0; k < nPCTerms_; k++){ + nQuad[k+1] = nQuad[k]+psiIJKLProd3_(k).Length(); + for (int i=0; i < (int) psiIJKLProd3_(k).Length(); i++){ + iProd[nQuad[k]+i] = iProd3_(k)(i); + jProd[nQuad[k]+i] = jProd3_(k)(i); + kProd[nQuad[k]+i] = kProd3_(k)(i); + Cijkl[nQuad[k]+i] = psiIJKLProd3_(k)(i); + } + } + return ; + +} + +void PCSet::GetQuadProd(Array1D& nQuad, Array1D& iProd, Array1D& jProd, Array1D& kProd, Array1D& Cijkl) const +{ + + // Get total number of quad products + double splength = this->GetNumQuadProd(); + cout << splength << endl; + + // Resize the containers + iProd.Resize(splength,0); + jProd.Resize(splength,0); + kProd.Resize(splength,0); + Cijkl.Resize(splength,0); + nQuad.Resize(nPCTerms_+1,0); + + // Fill containers through the int*/double* function + this->GetQuadProd(nQuad.GetArrayPointer(), iProd.GetArrayPointer(), jProd.GetArrayPointer(), kProd.GetArrayPointer(), + Cijkl.GetArrayPointer()); + + return ; + +} + +void PCSet::SetQd1d(Array1D& qdpts1d,Array1D& wghts1d, int nqd) +{ + char type_c[10]; + strcpy(type_c, this->pcType_.c_str()); + Quad qd1d(type_c,(char *)"full",1,nqd,this->alpha_,this->beta_); + qd1d.SetRule(); + Array2D ind1d; + Array2D qdpts1d_in2d; + qd1d.GetRule(qdpts1d_in2d, wghts1d,ind1d); + + qdpts1d.Clear(); + for(int iq=0;iq<(int)qdpts1d_in2d.XSize();iq++) + qdpts1d.PushBack(qdpts1d_in2d(iq,0)); + + return; +} + +void PCSet::SetQuadRule(const string grid_type,const string fs_type,int param) +{ + // Move strings to char*, since Quad needs char* + /// \todo Need to improve it + char grid_type_c[10], fs_type_c[10]; + strcpy(grid_type_c, grid_type.c_str()); + strcpy(fs_type_c, fs_type.c_str()); + + Quad spRule(grid_type_c,fs_type_c,nDim_,param,alpha_,beta_); + spRule.SetRule(); + + // Get the integration rule information + spRule.GetRule(this->quadPoints_, this->quadWeights_,this->quadIndices_); + this->nQuadPoints_ = this->quadPoints_.XSize(); + + // Get the basis values at the default quadrature points + this->EvalBasisAtCustPts(this->quadPoints_,this->psi_); + + return; +} + +void PCSet::SetQuadRule(Quad &quadRule) +{ + + // Get the intergation rule information + quadRule.GetRule(this->quadPoints_, this->quadWeights_,this->quadIndices_); + this->nQuadPoints_ = this->quadPoints_.XSize(); + + // Get the basis values at the default quadrature points + this->EvalBasisAtCustPts(this->quadPoints_,this->psi_); + + return; + +} + + +void PCSet::PrintMultiIndex() const +{ + + cout << "====================================================" << endl; + cout << "multi-indices(i,j), with i = 0 ... P, j = 1 ... nDim" << endl; + cout << "with P = " << nPCTerms_ - 1 << ", and nDim = " << nDim_ << endl; + cout << "----------------------------------------------------" << endl; + cout << "i\\j | "; + for(int idim=0; idim < nDim_; idim++){ + cout << idim + 1 << " "; + } + cout << endl; + cout << "------"; + for(int idim=0; idim < nDim_; idim++){ + cout << "---"; + } + cout << endl; + for(int ip=0; ip < nPCTerms_; ip++){ + cout << ip << " | "; + for(int idim=0; idim < nDim_; idim++){ + cout << multiIndex_(ip,idim) << " "; + } + cout << endl; + } + return; +} + +void PCSet::PrintMultiIndexNormSquared() const +{ + + cout << "===================================================================" << endl; + cout << "multi-indices(i,j), and \\Psi^2(i) with i = 0 ... P, j = 1 ... nDim" << endl; + cout << "with P = " << nPCTerms_ - 1 << ", and nDim = " << nDim_ ; + cout << " (terms up to order " << order_ << ")" << endl; + cout << "-------------------------------------------------------------------" << endl; + cout << "i\\j | "; + for(int idim=0; idim < nDim_; idim++){ + cout << idim + 1 << " "; + } + cout << "\\Psi^2" << endl; + cout << "------"; + for(int idim=0; idim < nDim_; idim++){ + cout << "---------"; + } + cout << endl; + for(int ip=0; ip < nPCTerms_; ip++){ + cout << ip << " | "; + for(int idim=0; idim < nDim_; idim++){ + cout << multiIndex_(ip,idim) << " "; + } + cout << psiSq_(ip) << endl; + } + +} + +void PCSet::InitMeanStDv( const double& m, const double& s, double* p ) const +{ + + // Check to make sure we have a 1D PCE + if ( this->nDim_ != 1 ){ + string err_message = (string) "PCSet::InitMeanStDv(): Is only implemented for 1D PCEs"; + throw Tantrum(err_message); + } + + // Check to make sure we have enough terms to set the standard deviation + if ( this->nPCTerms_ < 2){ + string err_message = (string) "PCSet::InitMeanStDv(): At least 2 terms needed to set a standard deviation"; + throw Tantrum(err_message); + } + + // Make sure we have a positive standard deviation s + if ( s < 0.e0 ){ + string err_message = (string) "PCSet::InitMeanStDv(): input standard deviation is negative"; + throw Tantrum(err_message); + } + + // Set the mean + p[0] = m; + + // Set the standard deviation + p[1] = s/(sqrt(this->psiSq_(1))); + + // Set the remainder of coeffients to 0 + for (int k = 2; k < this->nPCTerms_; k++){ + p[k] = 0.e0; + } + + return; + +} + +void PCSet::InitMeanStDv( const double& m, const double& s, Array1D& p ) const +{ + + // Check array sizes + if ( (int) p.Length() != this->nPCTerms_ ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::InitMeanStDv(): array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Initialize Mean and Standard Deviation + this->InitMeanStDv( m, s, p.GetArrayPointer() ) ; + + return; + +} + +void PCSet::Copy(double* p1, const double* p2) const +{ + // p1 = p2 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p1[ip] = p2[ip]; + } + return; +} + +void PCSet::Copy(Array1D& p1, const Array1D& p2) const +{ + // Check array sizes + if( (int) p2.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Copy(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p1.Length() != this->nPCTerms_ ) + p1.Resize(this->nPCTerms_,0.e0); + + // p1 = p2 + this->Copy(p1.GetArrayPointer(), p2.GetConstArrayPointer()); + + return; +} + +void PCSet::Add(const double* p1, const double* p2, double* p3) const +{ + // Add two arrays and return result in p3 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p3[ip] = p1[ip] + p2[ip]; + } + return; +} + +void PCSet::Add(const Array1D& p1, const Array1D& p2, Array1D& p3) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Add(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p3.Length() != this->nPCTerms_ ) + p3.Resize(this->nPCTerms_,0.e0); + + // Add two arrays and return result in p3 + this->Add(p1.GetConstArrayPointer(), p2.GetConstArrayPointer(), p3.GetArrayPointer()); + + return; +} + +void PCSet::AddInPlace(double* p1, const double* p2) const +{ + // Add p2 to p1 and return result in p1 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p1[ip] += p2[ip]; + } + return; +} + +void PCSet::AddInPlace(Array1D& p1, const Array1D& p2) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::AddInPlace(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + // Add p2 to p1 and return result in p1 + this->AddInPlace(p1.GetArrayPointer(), p2.GetConstArrayPointer()); + + return; +} + +void PCSet::Multiply(const double* p1, const double& a, double* p2) const +{ + // Multiply p1 with a and return result in p2 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p2[ip] = p1[ip]*a; + } + return; +} + +void PCSet::Multiply(const Array1D& p1, const double& a, Array1D& p2) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Multiply(): array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Multiply p1 with a and return result in p2 + this->Multiply(p1.GetConstArrayPointer(), a, p2.GetArrayPointer()); + + return; +} + +void PCSet::MultiplyInPlace(double* p1, const double& a) const +{ + // Multiply p1 with a and return result in p1 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p1[ip] *= a; + } + return; +} + +void PCSet::MultiplyInPlace(Array1D& p1, const double& a) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::MultiplyInPlace(): array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + // Multiply p1 with a and return result in p1 + this->MultiplyInPlace(p1.GetArrayPointer(), a); + + return; +} + +void PCSet::Subtract(const double* p1, const double* p2, double* p3) const +{ + // p3 = p1 - p2 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p3[ip] = p1[ip] - p2[ip]; + } + return; +} + +void PCSet::Subtract(const Array1D& p1, const Array1D& p2, Array1D& p3) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Subtract(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p3.Length() != this->nPCTerms_ ) + p3.Resize(this->nPCTerms_,0.e0); + + // p3 = p1 - p2 + this->Subtract(p1.GetConstArrayPointer(), p2.GetConstArrayPointer(), p3.GetArrayPointer()); + + return; +} + +void PCSet::SubtractInPlace(double* p1, const double* p2) const +{ + // p1 = p1 - p2 + for(int ip=0; ip < this->nPCTerms_; ip++){ + p1[ip] = p1[ip] - p2[ip]; + } + return; +} + +void PCSet::SubtractInPlace(Array1D& p1, const Array1D& p2) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::SubtractInPlace(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + // p1 = p1 - p2 + this->SubtractInPlace(p1.GetArrayPointer(), p2.GetConstArrayPointer()); + + return; +} + +void PCSet::Prod(const double* p1, const double* p2, double* p3) const +{ + // work variables + int i; + int j; + double c; + + // Multiply two arrays and return result in p3 + for(int k=0; k < this->nPCTerms_; k++){ + double tmpSum = 0.e0; + // Summation over i, j, using only the terms with non-zero Cijk's + for(int ic=0; ic < (int) (this->psiIJKProd2_(k).Length()); ic++){ + i = this->iProd2_(k)(ic); + j = this->jProd2_(k)(ic); + c = this->psiIJKProd2_(k)(ic); + tmpSum += p1[i] * p2[j] * c; + } + p3[k] = tmpSum/this->psiSq_(k); + } + + return; +} + +void PCSet::Prod(const Array1D& p1, const Array1D& p2, Array1D& p3) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Prod(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p3.Length() != this->nPCTerms_ ) + p3.Resize(this->nPCTerms_,0.e0); + + // Multiply two arrays and return result in p3 + this->Prod(p1.GetConstArrayPointer(), p2.GetConstArrayPointer(), p3.GetArrayPointer()); + + return; +} + +void PCSet::Prod3(const double* p1, const double* p2, const double* p3, double* p4) const +{ + // work variables + int i, j, k; + double c; + + // Multiply two arrays and return result in p3 + for (int l=0; l < this->nPCTerms_; l++){ + double tmpSum = 0.e0; + // Summation over i, j, k, using only the terms with non-zero Cijkl's + for(int ic=0; ic < (int) (this->psiIJKLProd3_(l).Length()); ic++){ + i = this->iProd3_(l)(ic); + j = this->jProd3_(l)(ic); + k = this->kProd3_(l)(ic); + c = this->psiIJKLProd3_(l)(ic); + tmpSum += p1[i] * p2[j] * p3[k] * c; + } + p4[l] = tmpSum/this->psiSq_(l); + } + + return; +} + +void PCSet::Prod3(const Array1D& p1, const Array1D& p2, const Array1D& p3, Array1D& p4) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) || + ( (int) p3.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Prod(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p4.Length() != this->nPCTerms_ ) + p4.Resize(this->nPCTerms_,0.e0); + + // Multiply three arrays and return result in p4 + this->Prod3(p1.GetConstArrayPointer(), p2.GetConstArrayPointer(), p3.GetConstArrayPointer(), p4.GetArrayPointer()); + + return; +} + +void PCSet::Polyn(const double* polycf, const int npoly, const double* p1, double* p2) const +{ + // Work variables + double ptemp[this->nPCTerms_]; + + double ps[npoly-1]; + for(int i=0;i1){ + this->Polyn(ps,npoly-1,p1, ptemp); + this->Prod(p1,ptemp,p2); + } + + p2[0]+=polycf[0]; + + return; +} + +void PCSet::Polyn(const Array1D& polycf, const Array1D& p1, Array1D& p2) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Polyn(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Evaluate a polynomial of p1 and return result in p2 + this->Polyn(polycf.GetConstArrayPointer(), polycf.Length(), p1.GetConstArrayPointer(), p2.GetArrayPointer()); + + return; +} + +void PCSet::PolynMulti(const Array1D& polycf, const Array2D& mindex, const Array2D& p1, Array1D& p2) const +{ + // Work variables + int nd=mindex.YSize(); + int nterms=mindex.XSize(); + + + // Check array sizes + if ( (int) p1.XSize() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::PolynMulti(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + if ( (int) polycf.Length() != nterms ){ + string err_message = (string) "PCSet::PolynMulti(): array sizes do not match" ; + throw Tantrum(err_message); + } + if ( (int) p1.YSize() != nd ){ + string err_message = (string) "PCSet::PolynMulti(): polynomial multiindex array size does not match the number" + + " of PC coefficient vectors"; + throw Tantrum(err_message); + } + + p2.Resize(this->nPCTerms_,0.e0); + + + // Prepare arrays for recursive calls + Array1D zeroind, nzeroind; + Array1D polycf1, polycf2; + for (int ii=0; ii < nterms; ii++){ + if (mindex(ii,0)==0){ + polycf1.PushBack(polycf(ii)); + zeroind.PushBack(ii); + } + else { + polycf2.PushBack(polycf(ii)); + nzeroind.PushBack(ii); + } + } + int nz=zeroind.Length(); + int nnz=nzeroind.Length(); + + + Array2D mindex1(nz,nd-1,0); + for (int i=0; i p1_1(this->nPCTerms_,nd-1,0.e0); + for (int i=0; inPCTerms_; i++) + for(int j=0; j mindex2(nnz,nd,0); + for (int i=0; i pfirst(this->nPCTerms_,0.e0); + for (int i=0; inPCTerms_; i++) + pfirst(i)=p1(i,0); + + // Evaluate recursively + + Array1D ptmp2(this->nPCTerms_,0.e0); + if (nd==1){ + for (int i=0;i0) + this->PolynMulti(polycf1,mindex1,p1_1,p2); + } + + + if (nnz>0){ + Array1D ptmp1; + this->PolynMulti(polycf2,mindex2,p1,ptmp1); + this->Prod(pfirst,ptmp1,ptmp2); + } + + this->AddInPlace(p2,ptmp2); + + return; +} + +void PCSet::Exp(const double* p1, double* p2) const +{ + // work variables + const double maxMult = 1.e3; // max growth in rel. error w/o stopping the run + + // array to store p1 minus its mean + double* x = new double[this->nPCTerms_]; + + x[0] = 0.e0; // random variable with mean zero + for(int k=1; k < this->nPCTerms_; k++){ + x[k] = p1[k]; + } + + // exp() of the mean of p1 + double expMean = exp(p1[0]); + + // + // find exp(x) with Taylor series 1 + x + x^2/2! + x^3/3! + ... + // where each term d_n is computed recursively + // as d_n = d_{n-1}*x/n + // + + // Work array for storing the current term in the Taylor series + double* d = new double[this->nPCTerms_]; + + // Set d equal to the first order term, which is x + for(int k=0; k < this->nPCTerms_; k++){ + d[k] = x[k]; + } + + // Store the first two terms: 1 + x = 1 + d in p2 + p2[0] = 1.e0 + d[0]; + for(int k=1; k < this->nPCTerms_; k++){ + p2[k] = d[k]; + } + + // work variables for progress tracking. Set them to satisfy the while condition initially + int tOrder = 1; // We are up to 1st order in the terms + double rErr = 1.e50; // relative error + double rErrOld = (maxMult + 1.e0)*rErr; // Old relative error + + // other work vars + double sc; + double* dn = new double[this->nPCTerms_]; // term n + double* fac = new double[this->nPCTerms_]; // factor to multiply d_{n-1} with to get d_n + + while (rErr > this->rTolTaylor_ && + tOrder+1 < this->maxTermTaylor_ && + rErr <= maxMult*rErrOld){ + + rErrOld = rErr; + tOrder++; + + sc = 1.e0/(double) tOrder; + for(int k=0; k < this->nPCTerms_; k++){ + fac[k] = x[k]*sc; // fac = x/n + } + + this->Prod(d,fac,dn); // dn = d*x/n + + rErr = 0.e0; + for(int k=0; k < this->nPCTerms_; k++){ + p2[k] += dn[k]; // Update p2 with new term + d[k] = dn[k]; // Save term for next step + rErr = max(rErr,fabs(dn[k]/p2[0])); // error as mag. of PC coeff. over the mean + } + } + + if(uqtkverbose_>0){ + cout << "number of terms in exp(p1) = " << tOrder + 1 << endl; + } + + // Check on exit criteria to see if something went wrong + + if(tOrder >= this->maxTermTaylor_){ + ostringstream buffer1, buffer2; + buffer1 << tOrder+1; // The total # of terms is the order + 1 + buffer2 << rErr; // Relative error at this point + string err_message = (string) "PCSet::Exp(): Rel. tolerance criterium for Taylor" + + "series not met after " + buffer1.str() + " terms.\n" + + "Relative error at this point is " + buffer2.str() + "."; + throw Tantrum(err_message); + } + + if(rErr > maxMult*rErrOld){ + ostringstream buffer1, buffer2; + buffer1 << tOrder+1; // The total # of terms is the order + 1 + buffer2 << rErr; // Relative error at this point + string err_message = (string) "PCSet::Exp(): Taylor series diverging after " + + buffer1.str() + " terms.\n" + + "Relative error at this point is " + buffer2.str() + "."; + throw Tantrum(err_message); + } + + // multiply the result back with exp(p1(0)) to factor in the exp of the mean + for(int k=0; k < this->nPCTerms_; k++){ + p2[k] = p2[k]*expMean; + } + + // clear out work memory + delete[] x; + delete[] d; + delete[] dn; + delete[] fac; + + return; +} + +void PCSet::Exp(const Array1D& p1, Array1D& p2) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Exp(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Take Exp of p1 and return it in p2 + this->Exp(p1.GetConstArrayPointer(), p2.GetArrayPointer()); + + return; +} + +void PCSet::Log(const double* p1, double* p2) const +{ + + + // Computes natural logarithm of PC expansion p1 using Taylor expansion: + if ( logMethod_ == TaylorSeries ) + LogTaylor(p1,p2) ; + else if ( logMethod_ == Integration ) + LogInt(p1,p2) ; + else + { + ostringstream buffer ; + buffer << logMethod_ ; // unknown method for computing natural logarithm + string err_message = (string) "PCSet::Log(): Unknown method : " + + buffer.str() + ", for computing logarithm of a PC expansion "; + throw Tantrum(err_message); + } + + return ; +} + +void PCSet::Log(const Array1D& p1, Array1D& p2) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Log(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Take Log of p1 and return it in p2 + this->Log(p1.GetConstArrayPointer(), p2.GetArrayPointer()); + + return; +} + +void PCSet::Log10(const double* p1, double* p2) const +{ + + // Computes logarithm to base 10 of PC expansion p1 and stores the result in p2 + // First use Log() to compute the natural logarithm and then divide it by log(10) + + this->Log(p1,p2); + + double sc = 1.e0 / log( 1.e1 ) ; + for(int k=0; k < this->nPCTerms_; k++){ + p2[k] *= sc; + } + + return; + +} + +void PCSet::Log10(const Array1D& p1, Array1D& p2) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Log10(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Take Log of p1 and return it in p2 + this->Log10(p1.GetConstArrayPointer(), p2.GetArrayPointer()); + + return; +} + +void PCSet::RPow(const double* p1, double* p2, const double& a) const +{ + + // Compute p2=p1^a as exp(a*log(p1)) + + // allocate intermediate work array + double* pwrk = new double[this->nPCTerms_]; + + // 1) take log of p1 + this->Log(p1,pwrk); + // 2) multiply result by a + this->MultiplyInPlace(pwrk,a) ; + // 3) Compute exp to obtain the final result + this->Exp(pwrk,p2) ; + + delete [] pwrk ; + + return; + +} + +void PCSet::RPow(const Array1D& p1, Array1D& p2, const double& a) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::RPow(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Compute p1^a and return it in p2 + this->RPow(p1.GetConstArrayPointer(), p2.GetArrayPointer(), a); + + return; +} + + +void PCSet::IPow(const double* p1, double* p2, const int& ia) const +{ + + // Set p2 = 1 + p2[0] = 1.0 ; + for ( int k = 1 ; k < this->nPCTerms_ ; k++ ) + p2[k] = 0.0 ; + + // if ia = 0 -> return + if ( ia == 0 ) return; + + // Check if power is negative; if yes, make it positive and remember this + int ialocal = ia ; + bool isneg = false ; + if ( ialocal < 0 ){ + ialocal *= -1 ; + isneg = true ; + } + + // Check if ia is even/odd and re-initialize p2 appropriately + if ( ialocal & 1 ) + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + p2[k] = p1[k] ; + + // allocate intermediate work arrays and initialize + double* pwrk1 = new double[this->nPCTerms_]; + double* pwrk2 = new double[this->nPCTerms_]; + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + pwrk1[k] = p1[k] ; + + // define additional pointer that will switch between pwrk1 and pwrk2 + double *pw1 = 0, *pw2 = 0, *ptmp = 0 ; + pw1 = pwrk1 ; + pw2 = pwrk2 ; + + // determine the number of digits in the binary representation of ia + int ndig ; + ndig = (int) (log( (double) ia + SMALL ) / log(2.0) ) + 1 ; + + // start loop + for ( int idig = 1 ; idig < ndig ; idig++ ){ + + // compute pw2 = pw1^2 + this->Prod(pw1,pw1,pw2) ; + + // check if binary representation of ia contains this power + if ( (ialocal & (1<>idig ) { + this->Prod(p2,pw2,pw1) ; + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + p2[k] = pw1[k] ; + + } + + // Switch pointers + ptmp = pw2 ; + pw2 = pw1 ; + pw1 = ptmp ; + + } + + // if power is negative complete the process by taking the inverse: + // p2 = 1/(p1^|ia|) + if ( isneg ){ + + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + pwrk1[k] = p2[k] ; + + this->Inv(pwrk1,p2) ; + + } + + delete [] pwrk1 ; + delete [] pwrk2 ; + + return; + +} + +void PCSet::IPow(const Array1D& p1, Array1D& p2, const int& ia) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::IPow(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Compute p1^ia and return it in p2 + this->IPow(p1.GetConstArrayPointer(), p2.GetArrayPointer(), ia); + + return; +} + + +void PCSet::Inv(const double* p1, double* p2) const +{ + + // Compute p2=1/p1 + + // allocate and initialize intermediate work array + double* pwrk = new double[this->nPCTerms_]; + pwrk[0] = 1.0 ; + for ( int k = 1 ; k < this->nPCTerms_ ; k++ ) + pwrk[k] = 0.0 ; + + // Compute 1/p1 + this->Div(pwrk,p1,p2) ; + + delete [] pwrk ; + + return; + +} + +void PCSet::Inv(const Array1D& p1, Array1D& p2) const +{ + // Check array sizes + if( (int) p1.Length() != this->nPCTerms_ ) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Inv(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p2.Length() != this->nPCTerms_ ) + p2.Resize(this->nPCTerms_,0.e0); + + // Compute 1/p1 and return it in p2 + this->Inv( p1.GetConstArrayPointer(), p2.GetArrayPointer() ); + + return; +} + + +void PCSet::GMRESMatrixVectorProd(const double* x, const double*a, double* y) const +{ + // Perform matrix vector product as product between two PC variables + this->Prod(x,a,y); + + return; +} + +void PCSet::Div(const double* p1, const double* p2, double* p3) const +{ +#define DIV_USE_GMRES + // Get the division p3 = p1/p2 by solving the system of eqn. p2*p3 = p1 + + // Do a test to see whether p1 happens to be zero, in which case p3 = 0 + // (assuming p2 is not zero) (GMRES would choke if p1 is 0) + double p1_rms = this->GetModesRMS(p1); + + if(p1_rms == 0.e0){ + for(int k=0; k < this->nPCTerms_; k++){ // Set p3 to zero and return + p3[k] = 0.e0; + } + return; + } + + // Initialize p3 with the right hand side p1 + for(int k=0; k < this->nPCTerms_; k++){ + p3[k] = p1[k]; + } + +#ifdef DIV_USE_GMRES + + // Use GMRES to solve the system of equations. GMRES assumes + // a sparse form is used to store the matrix A, but does not + // case what format is used, as long as we provide it with + // a routine to do preconditioning and matrix-vector products + // with. As the matrix-vector multiplication in this case + // comes down to a Product between two PC variables, + // we can just use PCSet::Prod to do the product and + // access all required info through the data members of PCSet. + // So we pass p2 as A and say it has nPCTerms_ non-zero elements + // In this implementation, there is also no preconditioning + // nor scaling of X and B used. + + // Set up parameters and work space for GMRES + // The parameters below correspond to the descriptions given in the dgmres.f + // implementation in the slatec library. For the tolerance parameter, we will + // use rTolGMRESDiv_. The isym argument will be repurposed to pass an index + // to a map containing pointers to this PCSet class object (in order to + // enable the callbacks from GMRES to the matrix-vector and preconditioning + // routines in this class). + int iter; // number of iterations performed + int ierr; // error flag + double err; // to hold error estimate of final solution + int itol = 0; // convergence test on residual + int itmax = 0; // dummy variable + int iunit = 0; // no output desired + int jscal = 0; // no scaling arrays SB and SX used + int jpre = 0; // no preconditioning + int nrmax = 10; // max number of restarts in Krylov iteration + + int maxl = 20; // Max dimension of Krylov subspace + int ligw = 20; // dimension of integer work array + int lrgw = 1 + this->nPCTerms_ * (maxl + 6) + maxl * (maxl+3); // size of real work array + + double* rgwk = new double[lrgw]; // real work array + double* rdum = new double[1]; // dummy real array + int* igwk = new int[ligw]; // integer work array + int* idum = new int[1]; // dummy integer array + int* ia = new int[this->nPCTerms_]; // Arrays for matrix structure of A + int* ja = new int[this->nPCTerms_]; // Arrays for matrix structure of A + + igwk[0] = maxl; + igwk[1] = maxl; + igwk[2] = jscal; + igwk[3] = jpre; + igwk[4] = nrmax; + + // transfer some arguments to maintain the imposed const constraints on original data + int nelt = this->nPCTerms_; + double rtol = this->rTolGMRESDiv_; + + double* p1_w = new double[this->nPCTerms_]; + double* p2_w = new double[this->nPCTerms_]; + + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ){ + p1_w[k] = p1[k]; + p2_w[k] = p2[k]; + } + + // Call GMRES to solve the system of equations, and pass the appropriate + // handles to this class and the static void callback functions for + // matrix vector multiplications and preconditioning. + + int handle = my_index_; + f77_matvecprod matvec_callee = GMRESMatrixVectorProdWrapper; + f77_precond precond_callee = GMRESPreCondWrapper; + + FTN_NAME(dgmres)(&nelt, p1_w, p3, &nelt, ia, ja, + p2_w, &handle, matvec_callee, precond_callee, + &itol, &rtol, &itmax, &iter, &err, &ierr, &iunit, rdum, rdum, + rgwk, &lrgw, igwk, &ligw, rdum, idum); + + if (ierr != 0) { + ostringstream buffer; + buffer << ierr; + string err_message = (string) "PCSet::Div(): error " + buffer.str() + " occurred in GMRES"; + throw Tantrum(err_message); + } + + // Clean up work variables + delete [] rgwk; + delete [] rdum; + delete [] igwk; + delete [] idum; + delete [] ia; + delete [] ja; + delete [] p1_w; + delete [] p2_w; + +#else /* use Gauss Elimination approach */ + + // Allocate work arrays and variables + Array1D rwrk(this->nPCTerms_,0.e0); // real work array + Array1D iwrk(this->nPCTerms_,0); // integer work array + Array2D a(this->nPCTerms_,this->nPCTerms_,0.e0); // matrix + int i; + int j; + double c; + + // Fill matrix A to represent p2*p3 with p3 unknown + for(int k=0; k < this->nPCTerms_; k++){ + // Summation over i, j, using only the terms with non-zero Cijk's + for(int ic=0; ic < this->psiIJKProd2_(k).Length(); ic++){ + i = this->iProd2_(k)(ic); + j = this->jProd2_(k)(ic); + c = this->psiIJKProd2_(k)(ic)/this->psiSq_(k); + a(k,i) += p2[j] * c; + } + } + + /* + cout << "Elements a(k,i) are" << endl; + for(int k=0; k < this->nPCTerms_; k++){ + for(int i=0; i < this->nPCTerms_; i++){ + cout << a(k,i) << " "; + } + cout << endl; + } + */ + + // Solve the system with Gauss Elimination + int itask = 1; + int ind = 0; + int nTerms = this->nPCTerms_; + FTN_NAME(dgefs)(a.GetArrayPointer(),&nTerms,&nTerms,p3,&itask,&ind, + rwrk.GetArrayPointer(),iwrk.GetArrayPointer()); + if(ind < 8){ + cout << "PCSet:Div(), estimated number of accurate digits from dgefs = " << ind << endl; + } + +#endif + + return; +} + +void PCSet::Div(const Array1D& p1, const Array1D& p2, Array1D& p3) const +{ + // Check array sizes + if( ( (int) p1.Length() != this->nPCTerms_ ) || + ( (int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Div(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if ( (int) p3.Length() != this->nPCTerms_ ) + p3.Resize(this->nPCTerms_,0.e0); + + // Divide p1 by p2 and return result in p3 + this->Div(p1.GetConstArrayPointer(), p2.GetConstArrayPointer(), p3.GetArrayPointer()); + + return; +} + +double PCSet::StDv( const double* p ) const +{ + + // work variables + double tsum = 0.e0 ; + + // First calculate the variance + for ( int k = 1 ; k < this->nPCTerms_ ; k++ ){ + tsum += ( p[k] * p[k] * this->psiSq_(k) ) ; + } + + // Next take the square root to get standard deviation and return it + double stdev = sqrt( tsum ) ; + + return stdev ; + +} + +double PCSet::StDv( const Array1D& p ) const +{ + + // Check array sizes + if ( (int) p.Length() != this->nPCTerms_ ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::StDv(): array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Take StDv of p + double stdv = this -> StDv( p.GetConstArrayPointer() ) ; + + return stdv ; + +} + +double PCSet::GetModesRMS(const double* p1) const +{ + // Get the rms of PC coefficients. + double sum = 0; + for(int k=0; k < this->nPCTerms_; k++){ + sum += p1[k]*p1[k]; + } + + return sqrt(sum/(double) this->nPCTerms_); +} + +double PCSet::GetModesRMS(const Array1D& p1) const +{ + // Check array size + if( (int) p1.Length() != this->nPCTerms_){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::GetModesRMS(): array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Get the rms of the PC coeffs + return this->GetModesRMS(p1.GetConstArrayPointer()); +} + +void PCSet::LogTaylor(const double* p1, double* p2) const +{ + // work variables + const double maxMult = 0.8; // max growth in rel. error w/o stopping the run + double sc; // used to compute recursive factors + + // mean of p1 + double p1Mean = p1[0]; + + if( fabs(p1Mean) < SMALL_ ){ + ostringstream buffer ; + buffer << p1Mean; // The mean value of PC expansion p1 + string err_message = (string) "PCSet::Log(): Cannot use Taylor series to compute log(p1)\n" + + "The mean value, " + buffer.str() + ", of PC expansion p1 is too small."; + throw Tantrum(err_message); + } + + // array storing (p1-p1Mean)/p1Mean + double* x = new double[this->nPCTerms_]; + + sc = 1.e0 / p1Mean ; + x[0] = 0.e0 ; + for(int k=1; k < this->nPCTerms_; k++){ + x[k] = p1[k]*sc ; + } + + // Work array for storing the current term in the Taylor series + double* d = new double[this->nPCTerms_]; + + // work variables for progress tracking. Set them to satisfy the while condition initially + int tOrder = 1 ; // Taylor expansion contains at least up to 1st order terms + double rErr = 1.e50 ; // relative error + double rErrOld = (maxMult + 1.e0)*rErr ; // old relative error + + // other work vars + double* dn = new double[this->nPCTerms_]; // term n + double* fac = new double[this->nPCTerms_]; // factor to multiply d_{n-1} with to get d_n + + // Set d equal to the first order term + for(int k=0; k < this->nPCTerms_; k++){ + d[k] = x[k] ; + } + + // Store the first two terms: log(p1Mean)+(p1-p1Mean)/p1 + p2[0] = log( p1Mean ) ; + for(int k=1; k < this->nPCTerms_; k++){ + p2[k] = d[k] ; + } + + // Start loop to add higher order terms + while ( rErr > this->rTolTaylor_ && + tOrder+1 < this->maxTermTaylor_ && + rErr <= maxMult*rErrOld ){ + + rErrOld = rErr; + tOrder++ ; + + sc = - (double) (tOrder-1) / (double) tOrder ; + + for(int k=0; k < this->nPCTerms_; k++){ + fac[k] = x[k]*sc; // fac = (-(n-1)/n)*(p1-p1Mean)/p1Mean + } + + this->Prod(d,fac,dn); // dn = d*fac + + rErr = 0.e0; + for(int k=0; k < this->nPCTerms_; k++){ + p2[k] += dn[k]; // Update p2 with new term + d[k] = dn[k]; // Save term for next step + rErr = max(rErr,fabs(dn[k]/p2[0])); // error as mag. of PC coeff. over the mean + } + } + + if(uqtkverbose_>0){ + cout << "number of terms in log(p1) = " << tOrder + 1 << endl; + } + + // Check on exit criteria to see if something went wrong + + if(tOrder >= this->maxTermTaylor_){ + ostringstream buffer1, buffer2; + buffer1 << tOrder+1; // The total # of terms is the order + 1 + buffer2 << rErr ; // Relative error at this point + string err_message = (string) "PCSet::Log(): Rel. tolerance criterium for Taylor" + + "series not met after " + buffer1.str() + " terms.\n" + + "Relative error at this point is " + buffer2.str() + "."; + throw Tantrum(err_message); + } + + if(rErr > maxMult*rErrOld){ + ostringstream buffer1, buffer2; + buffer1 << tOrder+1; // The total # of terms is the order + 1 + buffer2 << rErr; // Relative error at this point + string err_message = (string) "PCSet::Log(): Taylor series diverging after " + + buffer1.str() + " terms.\n" + + "Relative error at this point is " + buffer2.str() + "."; + throw Tantrum(err_message); + } + + // clear out work memory + delete[] x; + delete[] d; + delete[] dn; + delete[] fac; + + return; +} + +void PCSet::LogInt(const double* p1, double* p2) const +{ + // Computes natural logarithm of PC expansion p1 using numerical integration + + // initial condition array + N_Vector u ; + u = N_VNew_Serial( this->nPCTerms_ ) ; + double p1Mean = p1[0]; + NV_Ith_S(u,0) = log( p1Mean ) ; + for(int k=1; k < (this->nPCTerms_); k++) + NV_Ith_S(u,k) = 0.0 ; + + // initialize tolerances + realtype relT ; + N_Vector absT ; + relT = CVrelt_ ; + absT = N_VNew_Serial( this->nPCTerms_ ) ; + for ( int k = 0 ; k < ( this->nPCTerms_ ) ; k++ ) + NV_Ith_S(absT,k) = CVabst_ ; + + // initialize integration limits + realtype tstart,tend,tret ; + tstart = 0.0 ; + tend = 1.0 ; + + // cvode flag + int cvflag ; + + // initialize f_data (work array to be passed to cvode) + // position 0 contains the index of the current PCSet object + // positions 1...nPCTerms_ contain x0={p1[0],0,0,...,0} + // positions (nPCTerms_+1)....(2*nPCTerms_) contain a ={0,p1[1],p1[2],....,p1[nPCTerms_-1]} + // positions (2*nPCTerms_+1)....(3*nPCTerms_) contain p[t] = x0+a*t + // positions (3*nPCTerms_+1)....(4*nPCTerms_) contain a/p[t] (to be computed by LogIntRhs) + double *f_data ; + f_data = new double[4*(this->nPCTerms_)+1]; + + f_data[0] = (double) (this->my_index_) ; + + f_data[1] = p1[0] ; + for (int k = 1 ; k < (this->nPCTerms_) ; k++) + f_data[k+1] = 0.0 ; + + f_data[(this->nPCTerms_)+1] = 0.0; + for (int k = 1 ; k < (this->nPCTerms_) ; k++) + f_data[k+(this->nPCTerms_)+1] = p1[k] ; + + for (int k = 0 ; k < (this->nPCTerms_) ; k++) + f_data[k+2*(this->nPCTerms_)+1] = 0.0 ; + + for (int k = 0 ; k < (this->nPCTerms_) ; k++) + f_data[k+3*(this->nPCTerms_)+1] = 0.0 ; + + // Create cvode solver + void *cvode_mem = NULL; + cvode_mem = CVodeCreate(CV_ADAMS, CV_NEWTON); + this->Check_CVflag(cvode_mem, "PCSet::LogInt : CVodeCreate", 0) ; + + /* Allocate memory */ + cvflag = CVodeInit(cvode_mem, &LogIntRhsWrapper, tstart, u); + this->Check_CVflag(&cvflag, "CVodeInit", 1) ; + cvflag = CVodeSVtolerances(cvode_mem, relT, absT); + this->Check_CVflag(&cvflag, "CVodeSVtolerances", 1) ; + + // Set dense solver + cvflag = CVDense(cvode_mem, (this->nPCTerms_) ); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVDense", 1) ; + + /* Set work array */ + cvflag = CVodeSetUserData(cvode_mem, (void *) f_data); + this->Check_CVflag(&cvflag, "CVodeSetUserData", 1) ; + + // Set maximum order for the integratiom method + cvflag = CVodeSetMaxOrd(cvode_mem, CVmaxord_); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVodeSetMaxOrd", 1) ; + + // Set maximum number of steps + cvflag = CVodeSetMaxNumSteps(cvode_mem, CVmaxnumsteps_); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVodeSetMaxNumSteps", 1) ; + + // Set initial step size + cvflag = CVodeSetInitStep(cvode_mem, CVinitstep_); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVodeSetInitStep", 1) ; + + // Set maximum step size + cvflag = CVodeSetMaxStep(cvode_mem, CVmaxstep_); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVodeSetMaxStep", 1) ; + + // Set stop value + cvflag = CVodeSetStopTime(cvode_mem, tend); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVodeSetStopTime", 1) ; + + cvflag = CVode(cvode_mem, tend, u, &tret, CV_NORMAL); + this->Check_CVflag(&cvflag, "PCSet::LogInt : CVode", 1) ; + + // Retrieve PC terms + for (int k = 0 ; k < (this->nPCTerms_) ; k++) + p2[k] = NV_Ith_S(u,k) ; + + // Destroy temporary memory + N_VDestroy_Serial( u ) ; + N_VDestroy_Serial( absT ) ; + + CVodeFree( &cvode_mem ) ; + + delete [] f_data ; + + return ; + +} + +int PCSet::LogIntRhs(realtype t, N_Vector y, N_Vector ydot, void *f_data) const +{ + + // do nothing + double *x0,*a,*xat,*abyxat ; + + x0 = & ((double *) f_data) [1] ; + a = x0 +(this->nPCTerms_) ; + xat = a +(this->nPCTerms_) ; + abyxat = xat+(this->nPCTerms_) ; + + // compute x0+a*t + for (int i = 0 ; i < (this->nPCTerms_) ; i++) + xat[i] = x0[i]+a[i]*t ; + + // compute a/(x0+a*t) + this->Div(a,xat,abyxat) ; + + // send rhs back to cvode + for (int i = 0 ; i < (this->nPCTerms_) ; i++) + NV_Ith_S(ydot,i) = abyxat[i] ; + + return ( 0 ) ; + +} + +void PCSet::Derivative(const double* p1, double* p2) const +{ + // Make sure it is 1-d implementation + if (this->nDim_ != 1) + throw Tantrum("PCSet::Derivative(): Derivative computation supports 1d PC only"); + + // Compute p2=p1' + + if(!strcmp(this->pcType_.c_str(),"LU")){ + + // allocate and initialize intermediate work array (x) + double* px = new double[this->nPCTerms_]; + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + px[k] = 0.0 ; + px[1] = 1.0 ; + + // allocate and compute an intermediate work array + double* pn = new double[this->nPCTerms_]; + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + pn[k]= -k*p1[k]; + + // allocate and compute an intermediate work array + double* pnx = new double[this->nPCTerms_]; + this->Prod(pn,px,pnx); + + // allocate and compute an array according to recursive relation + double* ptmp = new double[this->nPCTerms_]; + for ( int k = 0 ; k < this->nPCTerms_-1 ; k++ ) + ptmp[k]=(k+1)*p1[k+1]; + ptmp[this->nPCTerms_-1]=0.0; + + this->AddInPlace(pnx,ptmp); + + // allocate and initialize intermediate work array (1-x^2) + double* p1_x2 = new double[this->nPCTerms_]; + for ( int k = 0 ; k < this->nPCTerms_ ; k++ ) + p1_x2[k] = 0.0 ; + p1_x2[0] = 2.0/3.0 ; + p1_x2[2] = -2.0/3.0 ; + + + // Compute pnx/p1_x2 + this->Div(pnx,p1_x2,p2) ; + + delete [] p1_x2 ; + delete [] px ; + delete [] pn ; + delete [] pnx ; + delete [] ptmp ; + } + + else if(!strcmp(this->pcType_.c_str(),"HG")){ + for ( int k = 0 ; k < this->nPCTerms_-1 ; k++ ) + p2[k]=(k+1)*p1[k+1]; + p2[this->nPCTerms_-1]=0.0; + + } + + else{ + string err_message = (string) "PCSet::Derivative(): PC type "+this->pcType_+" is not supported by derivative computation"; + throw Tantrum(err_message); + + } + + return; + +} + +void PCSet::Derivative(const Array1D& p1, Array1D& p2) const +{ + // Check array sizes + if( ((int) p1.Length() != this->nPCTerms_ ) || + ((int) p2.Length() != this->nPCTerms_ ) ){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::Derivative(): array sizes do not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + // Compute p1*a and return it in p2 + this->Derivative( p1.GetConstArrayPointer(), p2.GetArrayPointer() ); + + return; +} + +int PCSet::Check_CVflag(void *flagvalue, const char *funcname, int opt) const +{ + + int *errflag; + + /* Check if SUNDIALS function returned NULL pointer - no memory allocated */ + if ( ( opt == 0 ) && ( flagvalue == NULL ) ) + { + string err_message = (string) "\nCVODE_ERROR: " + +funcname+" failed - returned NULL pointer\n\n" ; + throw Tantrum(err_message); + } + + /* Check if flag < 0 */ + else if ( opt == 1 ) + { + errflag = (int *) flagvalue; + if ( *errflag < 0 ) + { + ostringstream buffer1 ; + buffer1 << (int *) flagvalue; + string err_message = (string) "\nCVODE_ERROR: " + +funcname+" failed with flag =" + buffer1.str() + "\n\n" ; + throw Tantrum(err_message); + } + } + + return ( 0 ) ; + +} + + +void PCSet::SeedBasisRandNumGen(const int& seed) const +{ + // Seed the PC Basis random number generator + this->p_basis_->SeedRandNumGen(seed); + + return; +} + +void PCSet::DrawSampleSet(const Array1D& p, Array1D& samples) +{ + // Check array size + if( (int) p.Length() != this->nPCTerms_){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::DrawSampleSet: p array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Draw samples + this->DrawSampleSet(p.GetConstArrayPointer(), samples.GetArrayPointer(), samples.Length()); + + return; +} + +void PCSet::DrawSampleSet(const double *p, double *samples, const int &nSamples) +{ + + // Draw samples + for (int js = 0 ; js < nSamples ; js++) { + // Draw a sample of the nDim_ dimensional random number vector xi + Array1D xia(this->nDim_,0.e0); + this->p_basis_->GetRandSample(xia); + + // Evaluate the PC expansion with this sample xia + samples[js] = this->EvalPC(p, xia.GetConstArrayPointer()); + } + + return; +} + +void PCSet::DrawSampleVar(Array2D& samples) const +{ + // Check array size + if( (int) samples.YSize() != this->nDim_){ + ostringstream buffer; + buffer << this->nDim_; + string err_message = (string) "PCSet::DrawSampleVar: samples array size does not match the dimensionality" + + " of PC (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + + int nSamples=samples.XSize(); + + for (int js = 0 ; js < nSamples ; js++) { + // Draw a single nDim_ dimensional random vector xia + Array1D xia(this->nDim_,0.e0); + this->p_basis_->GetRandSample(xia); + for(int idim=0;idimnDim_;idim++) + samples(js,idim)=xia(idim); + } + + return; +} + +void PCSet::DrawSampleVar(double *samples, const int &nS, const int &nD) const +{ + + // Check array size + if( nD != this->nDim_){ + ostringstream buffer; + buffer << this->nDim_; + string err_message = (string) "PCSet::DrawSampleVar: samples array size does not match the dimensionality" + + " of PC (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + for (int js = 0 ; js < nS ; js++) { + // Draw a single nDim_ dimensional random vector xia + Array1D xia(this->nDim_,0.e0); + this->p_basis_->GetRandSample(xia); + for(int idim=0;idimnDim_;idim++) + samples[js*(this->nDim_)+idim]=xia(idim); + } + + return; + +} + +double PCSet::EvalPC(const Array1D& p, Array1D& randVarSamples) +{ + // Check array sizes + if( (int) p.Length() != this->nPCTerms_){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::EvalPC: p array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if( (int) randVarSamples.Length() != this->nDim_){ + ostringstream buffer; + buffer << this->nDim_; + string err_message = (string) "PCSet::EvalPC: randVarSamples array size does not match the number" + + " of PC dimensions (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Evaluate the PC expansion at the random variables given + return this->EvalPC(p.GetConstArrayPointer(), randVarSamples.GetConstArrayPointer()); +} + +double PCSet::EvalPC(const double* p, const double* randVarSamples) +{ + // Evaluate PC expansion at a single point with coefficient vector p + + // Create a single sample in a 2D Array + Array2D singleSample(1,nDim_,0.e0); + for(int id=0;id pa(nPCTerms_,0.e0); + for(int ip=0;ip xch(1,0.e0); + this->EvalPCAtCustPoints(xch,singleSample,pa); + + return xch(0); +} + + +void PCSet::EvalPCAtCustPoints(Array1D& xch,Array2D& custPoints, Array1D& p) +{ + // Evaluate PC expansion at a set of points with coefficient vector p + + // Check array sizes + if( (int) custPoints.YSize() != this->nDim_){ + ostringstream buffer; + buffer << this->nDim_; + string err_message = (string) "PCSet::EvalPCAtCustPoints: randVarSamples array size does not match the number" + + " of PC dimensions (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Check array sizes + if( (int) p.Length() != this->nPCTerms_){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::EvalPCAtCustPoints: p array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + + int nSample=custPoints.XSize(); + xch.Resize(nSample,0.e0); + Array2D psi; + this->EvalBasisAtCustPts(custPoints,psi); + for (int is=0;isnPCTerms_;ip++) + sum += p(ip)*psi(is,ip); + xch(is)=sum; + } + + + return; +} + +void PCSet::EvalBasisAtCustPts(const Array2D& custPoints, Array2D& psi) +{ + + // Check array sizes + if((int) custPoints.YSize() != this->nDim_){ + ostringstream buffer; + buffer << this->nDim_; + string err_message = (string) "PCSet::EvalBasisAtCustPoints: custPoints array size does not match the number" + + " of PC dimensions (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + int npts=custPoints.XSize(); + + // Set array size and fill in with units + psi.Resize(npts,this->nPCTerms_,1.e0); + + // Evaluate the basis functions at each of the points + for(int isp=0; isp < npts; isp++){ + for(int id=0;id basisVals(maxOrdPerDim_(id)+1); + p_basis_->EvalBasis(custPoints(isp,id),basisVals); + for(int ipc=0; ipc < this->nPCTerms_; ipc++){ + psi(isp,ipc)*=basisVals(this->multiIndex_(ipc,id)); + } + } + } + + return; + +} + +void PCSet::EvalBasisAtCustPts(const double* custPoints0, const int npts, double* psi){ + + // convert custPoints as double * to Array2D + Array2D custPoints(npts,nDim_,0.0); + for (int i = 0; i < npts; i++){ + for (int j = 0; j < this->nDim_; j++){ + custPoints(i,j) = custPoints0[i*this->nDim_ + j]; + } + } + + Array2D Psi; + this->EvalBasisAtCustPts(custPoints,Psi); + // convert Psi back to double* + for (int i = 0; i < npts; i++){ + for (int j = 0; j < this->nPCTerms_; j++){ + psi[i + j*npts] = Psi(i,j); // column major instead + } + } +} +// void PCSet::EvalBasisAtCustPts(const int npts, const int ndim, const int npc, +// const double *custPoints, double *psi) +// { + +// // Check array sizes +// if ( ndim != this->nDim_){ +// ostringstream buffer; +// buffer << this->nDim_; +// string err_message = (string) "PCSet::EvalBasisAtCustPoints: custPoints array size does not match the number" +// + " of PC dimensions (" + buffer.str() + ")"; +// throw Tantrum(err_message); +// } + +// if ( npc != this->nPCTerms_){ +// ostringstream buffer; +// buffer << this->nPCTerms_; +// string err_message = (string) "PCSet::EvalBasisAtCustPoints: psi array size does not match the number" +// + " of PC terms (" + buffer.str() + ")"; +// throw Tantrum(err_message); +// } + +// // Evaluate the basis functions at each of the points +// for ( int isp=0; isp < npts; isp++ ) { +// for ( int id=0; id < ndim; id++ ) { + +// // Define a temporary array to store the basis values in for this point +// double *basisVals = new double[maxOrdPerDim_(id)+1]; +// p_basis_->EvalBasis(custPoints[isp*ndim+id],maxOrdPerDim_(id),basisVals); + +// for ( int ipc=0; ipc < npc; ipc++ ) +// psi[isp*npc+ipc] *= basisVals[this->multiIndex_(ipc,id)]; + +// delete [] basisVals; + +// } + +// } + +// } + +void PCSet::GalerkProjection(const Array1D& fcn, Array1D& ck) +{ + + // Performs Galerkin projection, given function evaluations at quadrature points + + ck.Resize(nPCTerms_,0.e0); + + // Check array sizes + if( (int) fcn.Length() != this->nQuadPoints_){ + ostringstream buffer; + buffer << this->nQuadPoints_; + string err_message = (string) "PCSet::GalerkProjection: fcn array size does not match the number" + + " of quadrature points (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + + if(uqtkverbose_>1){ + cout << "PCSet::GalerkinProjection() : using " << nQuadPoints_ << " quadrature points" << endl; + } + + // Compute the projection integral + for(int ipc=0;ipc1){ + cout << "PCSet::GalerkinProjection() : Computing " << ipc << " th coefficient out of " << nPCTerms_ << endl; + } + + double num=0.0 ; + //double den=0.0 ; + for(int iqp=0;iqppsi_(iqp,ipc)*this->quadWeights_(iqp); + // den+=this->psi_(iqp,ipc)*this->psi_(iqp,ipc)*this->quadWeights_(iqp); + } + //ck(ipc)=num/den; + ck(ipc)=num/psiSq_(ipc); + } + + + if(uqtkverbose_>1){ + cout << "PCSet::GalerkinProjection() : Done" << endl; + } + + return; + +} + + + + + +void PCSet::GalerkProjectionMC(const Array2D& x, const Array1D& fcn, Array1D& ck) +{ + // Performs Galerkin projection by Monte Carlo integration, given function evaluations at any points + + ck.Resize(nPCTerms_,0.e0); + + int npts = x.XSize(); + + // Check array sizes + if( (int) fcn.Length() != npts){ + string err_message = (string) "PCSet::GalerkProjectionMC: fcn array size does not match the number" + + " of given points "; + throw Tantrum(err_message); + } + if( (int) x.YSize() != this->nDim_){ + ostringstream buffer; + buffer << this->nDim_; + string err_message = (string) "PCSet::GalerkProjectionMC: data array size does not match the number" + + " of dimensions (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + if(uqtkverbose_>1){ + cout << "Galerkin Projection via Monte-Carlo: using " << npts << " points" << endl; + } + + // Compute the projection integral + for(int ipc=0;ipcnPCTerms_;ipc++){ + + if(uqtkverbose_>1){ + cout << "Galerkin ProjectionMC: Computing " << ipc << " th coefficient out of " << nPCTerms_ << endl; + } + + Array2D psi; + this->EvalBasisAtCustPts(x,psi); + + double num=0.0 ; + + for(int ip=0;ip1){ + cout << "Galerkin ProjectionMC: Done" << endl; + } + + return; + +} + + + +int PCSet::ComputeOrders(Array1D& orders) +{ + int maxOrder=0; + orders.Resize(this->nPCTerms_,0); + + // Loop over all basis terms + for(int ipc=0;ipcnPCTerms_;ipc++){ + + // Add the orders of the current basis term + for(int id=0;idnDim_;id++) + orders(ipc) += multiIndex_(ipc,id); + + // Check to store the maximal order + if (orders(ipc)>maxOrder) + maxOrder=orders(ipc); + + } + + return maxOrder; +} + + +int PCSet::ComputeEffDims(int *effdim) { + + int maxEffDim = 0; + + // Loop over all basis terms + for(int ipc=0;ipcnPCTerms_;ipc++) { + + // Compute the number of dimensions with non-zero order in the + // current basis term + effdim[ipc] = 0; + for(int id=0;idnDim_;id++) + effdim[ipc] += (multiIndex_(ipc,id)>0); + + // Check and store the maximum dimensionality among all bases + // Note: this is not the classical definition of effective dimenionality, + // since all dimensions can still be involved. + if ( effdim[ipc] > maxEffDim) maxEffDim=effdim[ipc]; + + } + + return maxEffDim; +} + +int PCSet::ComputeEffDims(Array1D& effdim) +{ + + effdim.Resize(this->nPCTerms_,0); + + int maxEffDim = this->ComputeEffDims(effdim.GetArrayPointer()); + + return (maxEffDim); + +} + +void PCSet::EncodeMindex(Array1D< Array2D >& sp_mindex) +{ + + // Compute the effective dimensionailities of all terms + Array1D effdim; + int maxEffDim=ComputeEffDims(effdim); + + // Compute and store the number of terms with a given effective dimensionality + Array1D num_effdim(maxEffDim+1,0); + for(int ipc=0;ipcnPCTerms_;ipc++) + num_effdim(effdim(ipc))+=1; + + + + // Resize for storage + sp_mindex.Resize(maxEffDim+1); + for(int i_effdim=0;i_effdim<=maxEffDim;i_effdim++) + // \todo what if num_effdim==0? (clear instead of resize?) or i_effdim==0? be ready for segfaults! + sp_mindex(i_effdim).Resize(num_effdim(i_effdim),2*i_effdim); + Array1D ii(maxEffDim+1,0); + + + + // Store the multiindices in the sparse format, i.e. + // the i-th element of sp_mindex is a 2D int matrix correspoding to bases with i non zero orders + // each row of that 2D-int matrix corresponds to a basis and has 2*f terms: + // first f are the indices of the non-zero dimensions, and the second half are the correponding orders. + // E.g. a term with multiindex (3,0,2,1,2,0) will correspond to a row (0,2,3,4,3,2,1,2) in the 2D array sp_mindex(4) + for(int ipc=0;ipcnPCTerms_;ipc++){ + int cur_effdim=effdim(ipc); + + int jj=0; + for(int id=0;idnDim_;id++){ + + if(multiIndex_(ipc,id)){ + sp_mindex(cur_effdim)(ii(cur_effdim),jj)=id; + sp_mindex(cur_effdim)(ii(cur_effdim),jj+cur_effdim)=multiIndex_(ipc,id); + jj++; + } + + } + ii(cur_effdim)++; + + } + + + return; +} + +double PCSet::ComputeMean(const double *coef) +{ + + // Compute the effective dimensionalities + int *effdim = new int[this->nPCTerms_]; + int maxEffDim = this->ComputeEffDims(effdim); + + // Search for the term with effective dimensionality = 0, i.e. the 0th order term + // Note: most often it is the very first term in the multiindex + // list, hence this may be an overkill. + for(int ipc=0;ipcnPCTerms_;ipc++){ + if ( effdim[ipc] == 0) { + delete [] effdim ; + return coef[ipc] ; + } + } + + delete [] effdim ; + return 0.e0; + +} + +double PCSet::ComputeMean(Array1D& coef) +{ + + // Check array sizes + if( (int) coef.Length() != this->nPCTerms_){ + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::ComputeMean: coef array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + return (ComputeMean(coef.GetConstArrayPointer())); + +} + +double PCSet::ComputeVarFrac(const double *coef, double *varfrac) +{ + // Compute the second moment + double var = 0.e0; + for (int ipc=0; ipc < this->nPCTerms_; ipc++){ + varfrac[ipc] = pow(coef[ipc],2.e0)*psiSq_(ipc); + var+=varfrac[ipc]; + } + + // Subtract the mean-squared to compute the variance + double mean=ComputeMean(coef); + var -= pow(mean,2.e0); + + // Scale the fractional contributions for all terms + for(int ipc=0;ipcnPCTerms_;ipc++) + varfrac[ipc] /= var; + + + return var; +} + +double PCSet::ComputeVarFrac(Array1D& coef, Array1D& varfrac) +{ + + // Check array sizes + if( (int) coef.Length() != this->nPCTerms_) { + ostringstream buffer; + buffer << this->nPCTerms_; + string err_message = (string) "PCSet::ComputeVarFrac: coef array size does not match the number" + + " of PC terms (" + buffer.str() + ")"; + throw Tantrum(err_message); + } + + // Compute the second moment + varfrac.Resize(this->nPCTerms_,0.e0); + double var = this->ComputeVarFrac(coef.GetConstArrayPointer(), varfrac.GetArrayPointer()); + + return (var) ; + +} + +void PCSet::ComputeMainSens(Array1D& coef, Array1D& mainsens) +{ + // Compute effective dimensionalities for all basis terms + Array1D effdim; + int maxEffDim=ComputeEffDims(effdim); + Array1D varfrac; + + // Compute variance fractions per basis term + double var=ComputeVarFrac(coef,varfrac); + + mainsens.Resize(this->nDim_,0.e0); + // Loop over all basis terms + for(int ipc=0;ipcnPCTerms_;ipc++){ + // Search for univariate terms only + if (effdim(ipc)==1){ + // Add the variance contributions for the univariate terms + for(int id=0;idnDim_;id++){ + if ( multiIndex_(ipc,id) != 0 ){ + mainsens(id)+=varfrac(ipc); + break; + } + } + } + } + + + return; +} + +void PCSet::ComputeTotSens(Array1D& coef, Array1D& totsens) +{ + + // Compute variance fractions + Array1D varfrac; + double var=ComputeVarFrac(coef,varfrac); + + totsens.Resize(this->nDim_,0.e0); + + // Loop over all basis terms + for(int ipc=0;ipcnPCTerms_;ipc++){ + for(int id=0;idnDim_;id++){ + if ( multiIndex_(ipc,id) != 0 ){ + // Add the appropriate variance contribution to the corresponding element in totsens + totsens(id)+=varfrac(ipc); + } + } + + } + + return; +} + +void PCSet::ComputeJointSens(Array1D& coef, Array2D& jointsens) +{ + + // Compute variance fractions + Array1D varfrac; + double var=ComputeVarFrac(coef,varfrac); + + jointsens.Resize(this->nDim_,this->nDim_,0.e0); + + + for(int ipc=0;ipcnPCTerms_;ipc++){ + Array1D nz; + // Store the order non-zero elements + for(int id=0;idnDim_;id++) + if ( multiIndex_(ipc,id) != 0 ) + nz.PushBack(id); + + // Add the appropriate variance contribution to the corresponding element in jointsens + for(int iz=0;iz<(int) nz.Length();iz++) + for(int jz=iz+1;jz<(int) nz.Length();jz++) + jointsens(nz(iz),nz(jz))+=varfrac(ipc); + + } + + return; +} + + +void PCSet::EvalNormSq(Array1D& normsq) +{ + normsq.Resize(nPCTerms_,1.e0); + + // Get the 1d norms-squared + Array1D norms1d; + p_basis_->Get1dNormsSq(norms1d); + + // FOr each term, multiply appropriate 1d norms-squared + for(int ipc=0; ipc normsq0; + normsq0.Resize(nPCTerms_,1.e0); + + // Get the 1d norms-squared + Array1D norms1d; + p_basis_->Get1dNormsSq(norms1d); + + // FOr each term, multiply appropriate 1d norms-squared + for(int ipc=0; ipc& normsq) +{ + p_basis_->Eval1dNormSq_Exact(this->maxorddim_); + + + normsq.Resize(nPCTerms_,1.e0); + + // Get the 1d norms-squared + Array1D norms1d; + p_basis_->Get1dNormsSqExact(norms1d); + + // FOr each term, multiply appropriate 1d norms-squared + for(int ipc=0; ipcGetPCType(); + + // For LU and JB, the domain is [-1,1] + if( !strcmp(type.c_str(),"LU") or !strcmp(type.c_str(),"JB") or !strcmp(type.c_str(),"LU_N") ) + if(fabs(x)>1) + return false; + + // For GLG and SW, the domain is [0,\infty) + if( !strcmp(type.c_str(),"GLG") or !strcmp(type.c_str(),"SW") ) + if(x<0) + return false; + + return true; +} + diff --git a/cpp/lib/pce/PCSet.h b/cpp/lib/pce/PCSet.h new file mode 100644 index 00000000..078be098 --- /dev/null +++ b/cpp/lib/pce/PCSet.h @@ -0,0 +1,966 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file PCSet.h +/// \author B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 - +/// \brief Header file for the Multivariate PC class + +#ifndef PCSET_H_SEEN +#define PCSET_H_SEEN + +#include +#include +#include +#include +#include +#include "Array1D.h" +#include "Array2D.h" +#include "error_handlers.h" +#include "ftndefs.h" +#include "quad.h" + +/* CVODE headers */ +#include /* prototypes for CVODE fcts., consts. */ +#include /* serial N_Vector types, fcts., macros */ +#include /* prototype for CVDense */ +#include /* definitions DlsMat DENSE_ELEM */ +#include /* definition of type realtype */ + +#include +#include +#include +#include +using namespace std; // needed for python string conversion + +class PCBasis; +class Quad; + +typedef enum {TaylorSeries=0, Integration} LogCompMethod; + +/// \class PCSet +/// \brief Defines and initializes PC basis function set and provides functions +/// to manipulate PC expansions defined on this basis set. + +class PCSet { +public: + + /// \brief Constructor: initializes the PC basis set for the + /// order, number of dimensions and type that are passed in. + /// + /// Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), + /// or "NISPnoq" (non-intrusive without quadrature initialization) + /// \note alpha and betta are parameters only relevant for GLG, JB or SW chaoses + PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, + const double alpha=0.0, const double betta=1.0); + + + /// \brief Constructor: initializes the PC basis set for the + /// order, number of dimensions and type that are passed in. It also + /// customizes the multiindex sequence ( lexicographical-lex, + /// colexicographical-colex, reverse lexicographical-revlex, and + /// reverse clexicographical-revcolex). + /// + /// Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), + /// or "NISPnoq" (non-intrusive without quadrature initialization) + /// \note alpha and betta are parameters only relevant for GLG, JB or SW chaoses + PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, const string pc_seq, + const double alpha=0.0, const double betta=1.0); + + + /// \brief Constructor: initializes the PC basis set ordered in an HDMR fashion + /// given order per each HDMR rank (univariate, bivariate, etc...) + /// + /// Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), + /// or "NISPnoq" (non-intrusive without quadrature initialization) + /// \note alpha and betta are parameters only relevant for GLG, JB or SW chaoses + PCSet(const string sp_type, const Array1D& maxOrders, const int n_dim, const string pc_type, + const double alpha=0.0, const double betta=1.0); + + /// \brief Constructor: initializes the PC basis set for a given + /// custom multiIndex + /// + /// Implementation type sp_type has three options + /// "ISP" (intrusive methods), "NISP" (non-intrusive), + /// or "NISPnoq" (non-intrusive without quadrature initialization) + /// \note alpha and betta are parameters only relevant for GLG, JB or SW chaoses + PCSet(const string sp_type, const Array2D& customMultiIndex, const string pc_type, + const double alpha=0.0, const double betta=1.0); + + /// \brief Destructor: cleans up all memory and destroys object + ~PCSet(); + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Set Gradient and Hessian operators + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Evaluate Gradient at a single d-dim point + /// and d-dim basis polynomial + void dPhi_alpha(Array1D& x, Array1D& alpha, Array1D& grad); + /// \brief Evaluate Gradient at a single d-dim point + /// for a PCSet object + void dPhi(Array1D& x, Array2D& mindex, Array1D& grad, Array1D& ck); + /// \brief Evaluate Gradient at a multiple d-dim x points + /// for a PCSet object + void dPhi(Array2D& x, Array2D& mindex, Array2D& grad, Array1D& ck); + + /// \brief Evaluate Hessian at a single d-dim point + /// and d-dim basis polynomial + void ddPhi_alpha(Array1D& x, Array1D& alpha, Array2D& grad); + /// \brief Evaluate Gradient at a single d-dim point + /// for a PCSet object + void ddPhi(Array1D& x, Array2D& mindex, Array2D& grad, Array1D& ck); + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Set the quadrature rule + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Obtain 1d quadrature points and weights + /// \note This is used in triple or quadruple product computation for which the default quadrature is not enough + void SetQd1d(Array1D& qdpts1d,Array1D& wghts1d, int nqd); + + /// \brief Set the quadrature points by specifying + /// a grid type, a full/sparse indicator, and an integer parameter + /// + /// Full/sparse switch fs_type can be either 'full' or 'sparse' + /// The parameter param is the number of points per dimension for + /// full quadrature, and the level for sparse quadrature + /// Options for grid_type are, besides the standard PC types, + /// 'CC' (Clenshaw-Curtis), 'CCO' (Clenshaw-Curtis open), + /// 'NC' (Newton-Cotes), 'NCO' (Newton-Cotes open), + /// where open means that endpoints are expluded + /// \note 'NC', 'NCO' quadratures are the same as uniformly spaced grids + void SetQuadRule(const string grid_type,const string fs_type,int param); + + /// \brief Set a custom quadrature rule by pointing to the corresponding object + void SetQuadRule(Quad &quadRule); + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Print information on the screen + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Print the multi-indices for all terms on the screen + void PrintMultiIndex() const; + + /// \brief For all terms, print their multi-index and norm^2 on the screen + void PrintMultiIndexNormSquared() const; + + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Get and set variables/arrays inline + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Get the PC type + string GetPCType() const {return pcType_;} + + /// \brief Get the value of the parameter alpha + double GetAlpha() const {return alpha_;} + + /// \brief Get the value of the parameter beta + double GetBeta() const {return beta_;} + + /// \brief Get the multiindex (return Array2D) + void GetMultiIndex(Array2D &mindex) const {mindex=multiIndex_;} + + /// \brief Get the multiindex (return double *) + void GetMultiIndex(int *mindex) const; + + /// \brief Get the norm-squared + /// \todo this seems like a duplication, see below GetPsiSq() + void GetNormSq(Array1D& normsq) const {normsq=psiSq_;} + + /// \brief Get the number of terms in a PC expansion of this order and dimension + int GetNumberPCTerms() const {return nPCTerms_;} + + /// \brief Get the PC dimensionality + int GetNDim() const {return nDim_;} + + /// \brief Get the PC order + int GetOrder() const {return order_;} + + /// \brief Get the number of quadrature points + int GetNQuadPoints() const {return nQuadPoints_;} + + /// \brief Get the quadrature points + void GetQuadPoints(Array2D& quad) const {quad=quadPoints_;} + + /// \brief Get the quadrature points and weights + void GetQuadPointsWeights(Array2D& quad, Array1D& wghts) const { quad=quadPoints_; wghts=quadWeights_;} + + /// \brief Get the quadrature points folded into a one-dimensional array quad + void GetQuadPoints(double* quad) const {for(int i=0;i& wghts) const {wghts=quadWeights_;} + + /// \brief Get the quadrature weights folded into a one-dimensional array wghts + void GetQuadWeights(double* wghts) const {for(int i=0;i& psi) const {psi=psi_;} + + /// \brief Get the polynomials evaluated at the quadrature points + /// folded into a one-dimensional array psi + void GetPsi(double* psi) const {for(int i=0;i& psisq) const {psisq=psiSq_;} + + /// \brief Get the basis polynomial norms-squared in a double* array psisq + void GetPsiSq(double* psisq) const {for(int i=0;i format to have the same distribution as the underlying PC germ, + /// but with a specified mean m and standard deviation s + /// \note This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general + /// \note This function only holds for expansions with one stochastic dimension + /// \note All existing coefficient values in p will be overwritten + /// \todo Make this function work for general multi-indices, and for any number of stochastic dimensions + void InitMeanStDv(const double& m, const double& s, Array1D& p) const; + + /// \brief Copy PC expansion p2 into p1 (i.e. p1 = p2). + /// + /// All arguments in double* format. + void Copy(double* p1, const double* p2) const; + + /// \brief Copy PC expansion p2 into p1 (i.e. p1 = p2). + /// + /// All arguments in Array format + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Copy(Array1D& p1, const Array1D& p2) const; + + /// \brief Add two PC expansions given by double* arguments p1 and p2, and + /// return the result in p3. + void Add(const double* p1, const double* p2, double* p3) const; + + /// \brief Add two PC expansions given by Array1D arguments p1 and p2, and + /// return the result in p3. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Add(const Array1D& p1, const Array1D& p2, Array1D& p3) const; + + /// \brief Add PC expansions given by double* argument p2 to p1 and + /// return the result in p1. + void AddInPlace(double* p1, const double* p2) const; + + /// \brief Add PC expansions given by Array1D argument p2 to p1 and + /// return the result in p1. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void AddInPlace(Array1D& p1, const Array1D& p2) const; + + /// \brief Multiply PC expansion p1 with scalar a and return the result in p2. + /// All PCEs are in double* format + void Multiply(const double* p1, const double& a, double* p2) const; + + /// \brief Multiply PC expansion p1 with scalar a and return the result in p2. + /// All PCEs are in Array1D format + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Multiply(const Array1D& p1, const double& a, Array1D& p2) const; + + /// \brief Multiply PC expansions given by double* argument p1 with scalar a and + /// return the result in p1. + void MultiplyInPlace(double* p1, const double& a) const; + + /// \brief Multiply PC expansions given by Array1D argument p1 with scalar a and + /// return the result in p1. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void MultiplyInPlace(Array1D& p1, const double& a) const; + + /// \brief Subtract PC expansion p2 from p1, and return the result in p3, with + /// all arguments given as double* + void Subtract(const double* p1, const double* p2, double* p3) const; + + /// \brief Subtract PC expansion p2 from p1, and return the result in p3, with + /// all arguments given as Array1D structures. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Subtract(const Array1D& p1, const Array1D& p2, Array1D& p3) const; + + /// \brief Subtract PC expansion p2 from p1, and return the result in p1, with + /// all arguments given as double* + void SubtractInPlace(double* p1, const double* p2) const; + + /// \brief Subtract PC expansion p2 from p1, and return the result in p1, with + /// all arguments given as Array1D structures. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void SubtractInPlace(Array1D& p1, const Array1D& p2) const; + + /// \brief Multiply two PC expansions given by double* arguments p1 and p2, and + /// return the result in p3. + void Prod(const double* p1, const double* p2, double* p3) const; + + /// \brief Multipy two PC expansions given by Array1D arguments p1 and p2, and + /// return the result in p3. + /// \note Requires the size of the input arrays to equal the number of PC terms + void Prod(const Array1D& p1, const Array1D& p2, Array1D& p3) const; + + /// \brief Multiply three PC expansions given by double* arguments + /// p1, p2, and p3, and return the result in p4. + void Prod3(const double* p1, const double* p2, const double* p3, double* p4) const; + + /// \brief Multipy three PC expansions given by Array1D arguments p1, + /// p2, and p3, and return the result in p4. + /// \note Requires the size of the input arrays to equal the number of PC terms + void Prod3(const Array1D& p1, const Array1D& p2, const Array1D& p3, + Array1D& p4) const; + + /// \brief Evaluates a polynomial of PC that is given in double* argument p1. + /// Polynomial coefficients are given in double* argument polycf of size npoly. + /// The output PC is contained in double* argument p2. + /// \note Recursive algorithm is implemented. + void Polyn(const double* polycf, int npoly, const double* p1, double* p2) const; + + /// \brief Evaluates a polynomial of PC that is given by Array1D argument p1. + /// Polynomial coefficients are given in the Array1D argument polycf. + /// The output PC is contained in Array1D argument p2. + /// \note Requires the size of array p1 to equal the number of PC terms + void Polyn(const Array1D& polycf, const Array1D& p1, Array1D& p2) const; + + /// \brief Evaluates a multivariate polynomial of a set of PC inputs given by + /// Array2D argument p1 (each column of p1 is a PC input). + /// Polynomial coefficients are given in Array1D argument polycf. + /// Multiindex set for the multivariate polynomial is given in Array2D argument mindex. + /// The output PC is contained in Array1D argument p2. + /// \note Requires the size of the array polycf to equal the first dimension of argument mindex + /// \note Requires the size of the array p1 to equal (the number of PC terms) X (second dimension of argument mindex) + /// \note Uses a recursive algorithm + /// \note Out of convenience, this function so far is implemented for Array classes, not double* arrays. + /// \todo A double* version should be added. + void PolynMulti(const Array1D& polycf, const Array2D& mindex, const Array2D& p1, Array1D& p2) const; + + /// \brief Take the exp() of the PC expansion given by double* argument p1, and + /// return the result in p2. + /// + /// Relies on Taylor series expansion: exp(x) = 1 + x + x^2/2! + x^3/3! + ... + /// However, for efficiency and to avoid overflow, the terms are computed + /// as d_i = d_{i-1}*x/i. Also, to reduce the number of terms needed in the + /// series, we subtract the mean out of a random variable u as u = u_0 + (u-u_0) + /// and exp(u) = exp(u_0)*exp(u-u_0), where exp(u_0) can be computed with the + /// regular exp(double& ) function + /// \note The Taylor series is truncated after a tolerance criterium is + /// achieved on the relative error defined as the max absolute value of the PC + /// coefficients in the last added term, divided by the mean of exp(p1). + /// The tolerance is set to 1.e-6 by default and can be changed with SetTaylorTolerance(). + /// \note The maximum number of terms in the Taylor series is set by default to 500 + /// and can be changed with SetTaylorTermsMax() + void Exp(const double* p1, double* p2) const; + + /// \brief Take the exp() of the PC expansion given by Array1D argument p1, and + /// return the result in p2. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Exp(const Array1D& p1, Array1D& p2) const; + + /// \brief Take the natural logarithm log() of the PC expansion given by double* + /// argument p1, and return the result in p2. The logarithm is evaluated + /// either via Taylor series or via integration depending on the value of + /// parameter logMethod_ + void Log(const double* p1, double* p2) const; + + /// \brief Take the natural logarithm, log(), of the PC expansion given by + /// Array1D argument p1, and return the result in Array1D argument p2. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Log(const Array1D& p1, Array1D& p2) const; + + /// \brief Take the logarithm to base 10 of the PC expansion given by double* + /// argument p1, and return the result in p2. + /// + /// First use Log() to compute the natural logarithm and then divide it by log(10) + void Log10(const double* p1, double* p2) const; + + /// \brief Take the logarithm to base 10 of the PC expansion given by + /// Array1D argument p1, and return the result in Array1D argument p2. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Log10(const Array1D& p1, Array1D& p2) const; + + /// \brief Evaluate power a (a real number) of PC expansion given by double* + /// argument p1, and return the result in p2. + /// The power is computed as p1^a = exp(a*log(p1)), where log(p1) is evaluated + /// either via Taylor series or via integration depending on the value of + /// parameter logMethod_ + void RPow(const double* p1, double* p2, const double& a) const; + + /// \brief Evaluate power a (a real number) of PC expansion given by + /// Array1D argument p1, and return the result in Array1D argument p2. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void RPow(const Array1D& p1, Array1D& p2, const double& a) const; + + /// \brief Evaluate power ia (an integer number) of PC expansion given by double* + /// argument p1, and return the result in p2. + void IPow(const double* p1, double* p2, const int& ia) const; + + /// \brief Evaluate power ia (an integer number) of PC expansion given by + /// Array1D argument p1, and return the result in Array1D argument p2. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void IPow(const Array1D& p1, Array1D& p2, const int& ia) const; + + /// \brief Evaluate the inverse of PC expansion given by double* + /// argument p1, and return the result in p2. + /// The inverse is computed using the division function + void Inv(const double* p1, double* p2) const; + + /// \brief Evaluate the inverse of PC expansion given by + /// Array1D argument p1, and return the result in Array1D argument p2. + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Inv(const Array1D& p1, Array1D& p2) const; + + /// \brief Divide the PC expansion p1 by p2, and return the result in p3 + /// (All arguments in double* format) + /// + /// The "division" p3 = p1/p2 is performed by solving the system + /// of equations p2*p3 = p1 for the unknown p3. + /// \note When GMRES is used to solve this system of equations (based on a + /// preprocessor flag in the source code for this routine), a relative tolerance + /// criterium is used that is set by default to 1.e-8, and can be + /// changed with SetGMRESDivTolerance(). + /// \todo Remove duplication of data and parameters that was required for + /// enforcing imposed "const" constraints on some of the arguments and the class data + /// members when they are being passed to fortran. + void Div(const double* p1, const double* p2, double* p3) const; + + /// \brief Divide the PC expansion p1 by p2, and return the result in p3 + /// (All arguments in Array1D format) + /// \note Requires the size of the arrays that are passed in to equal the number of PC terms + void Div(const Array1D& p1, const Array1D& p2, Array1D& p3) const; + + /// \brief Returns the standard deviation of PC expansion p in a double* format + /// \note This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general + /// \todo Lift the assumption by looking for the constant term in the multiindex + double StDv(const double* p) const; + + /// \brief Returns the standard deviation of PC expansion p + ///(Argument in Array1D format) + /// \note This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general + /// \todo Lift the assumption by looking for the constant term in the multiindex + /// \note For a more general implementation, see ComputeVarFrac() + double StDv(const Array1D& p) const; + + /// \brief Compute the rms average of the PC coefficients (i.e. the square root + /// of the average of the square of the PC coefficients, not taking into + /// account any basis functions). (Arguments in double* format) + double GetModesRMS(const double* p) const; + + /// \brief Compute the rms average of the PC coefficients (i.e. the square root + /// of the average of the square of the PC coefficients, not taking into + /// account any basis functions). (Arguments in Array1D format) + /// \note Requires the size of the array that is passed in to equal the number of PC terms + double GetModesRMS(const Array1D& p) const; + + /// \brief Computes derivatives of univariate PC given by coefficients p1 + /// returns coefficient vector of the derivative in p2 + /// \note Makes use of intrusive computations on recursive formulae for derivatives + /// \todo Supports LU and HG bases only + /// \todo Supports only for 1d PCs + void Derivative(const double* p1, double* p2) const; + + /// \brief Computes derivatives of univariate PC given by coefficients p1 + /// returns coefficient vector of the derivative in p2 + /// \note Makes use of intrusive computations on recursive formulae for derivatives + /// \todo Supports LU and HG bases only + /// \todo Supports only for 1d PCs + void Derivative(const Array1D& p1, Array1D& p2) const; + + /// \brief Returns number of triple products + int GetNumTripleProd() const; + /// \brief Returns triple products indices (int*/double* version) + void GetTripleProd(int *nTriple, int *iProd, int *jProd, double *Cijk) const; + /// \brief Returns triple products indices (Array version) + void GetTripleProd(Array1D& nTriple, Array1D& iProd, Array1D& jProd, Array1D& Cijk) const; + /// \brief Returns number of quad products + int GetNumQuadProd() const; + /// \brief Returns quad products indices (int*/double* version) + void GetQuadProd(int *nQuad, int *iProd, int *jProd, int *kProd, double *Cijkl) const; + /// \brief Returns quad products indices (Array version) + void GetQuadProd(Array1D &nQuad, Array1D &iProd, Array1D &jProd, Array1D &kProd, + Array1D &Cijkl) const; + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Random sample generator functions + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Reseed the random number generator used for the sampling + /// of the PC variables and expansions + void SeedBasisRandNumGen(const int& seed) const; + + /// \brief Draw a set of samples from the PC expansion p, + /// and return the result in the array samples. + /// All arguments are in Array1D format + /// The number of samples requested is assumed to be the size of the samples array + /// \note The size of the array p that is passed in needs to equal the number of PC terms + void DrawSampleSet(const Array1D& p, Array1D& samples); + + /// \brief Draw a set of samples from the PC expansion given in double* argument p, + /// and return the result in double* array samples. + /// The number of samples requested is the argument nSamples + void DrawSampleSet(const double* p, double* samples, const int& nSamples); + + /// \brief Draw a set of samples of the underlying germ random variable + /// \todo There is no double* version of this function + void DrawSampleVar(Array2D& samples) const; + void DrawSampleVar(double *samples, const int &nS, const int &nD) const; + + ///////////////////////////////////////////////////////////////////////////////////////// + /// PC evaluation functionalities + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Evaluate the given PC expansion p, at the specified + /// values of the random variables, randVarSamples. + /// All arguments in const Array1D format + /// \note The number of elements in p needs to match the number of terms + /// in the PC expansions in this PCSet. + /// \note The number of elements in randVarSamples needs to match the + /// number of dimensions in the PC expansion. + double EvalPC(const Array1D& p, Array1D& randVarSamples); + + /// \brief Evaluate the given PC expansion p, at the specified + /// values of the random variables, randVarSamples. + /// All arguments in const double* format + /// \note The number of elements in p is assumed to match the number of terms + /// in the PC expansions in this PCSet. + /// \note The number of elements in randVarSamples is assumed to match the + /// number of dimensions in the PC expansion. + double EvalPC(const double* p, const double* randVarSamples); + + /// \brief Evaluate the given PC expansion at given set of points with given coefficient vector and + /// return the values in an 1D Array in the first argument. + /// \todo There is no double* version of this function + void EvalPCAtCustPoints(Array1D& xch, Array2D& custPoints,Array1D& p); + + /// \brief Evaluate Basis Functions at given points custPoints and return in the array psi + /// \todo There is no double* version of this function + void EvalBasisAtCustPts(const Array2D& custPoints,Array2D& psi); + + void EvalBasisAtCustPts(const double* custPoints, const int npts, double* psi); + // void EvalBasisAtCustPts(const int npts, const int ndim, const int npc, const double *custPoints, double *psi); + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Galerkin projection functionalities + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Performs (NISP) Galerkin projection, given function evaluations at quadrature points + /// Returns in the coefficient vector in the second argument + /// \note User should make sure that the function HAS BEEN evaluated at the correct quadrature points + /// by first extracting the quadrature points and evaluating the function externally + /// \todo Overload this with forward function pointers + /// \todo There is no double* version of this function + void GalerkProjection(const Array1D& fcn, Array1D& ck); + + /// \brief Galerkin Projection via Monte-Carlo integration + /// \note User should make sure that the function HAS BEEN evaluated at the correct sampling points + /// by first sampling the proper PC germ distribution and evaluating the function externally + /// \todo Overload this with forward function pointers + /// \todo There is no double* version of this function + void GalerkProjectionMC(const Array2D& x, const Array1D& fcn, Array1D& ck); + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Multiindex parsing functionalities + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Computes the order of each basis term and return it in the array orders, + /// also returns the maximal order + /// \todo There is no double* version of this function + int ComputeOrders(Array1D& orders); + + /// \brief Computes the effective dimensionality of each basis term, + /// i.e., the number of dimensions that enter with a non-zero degree. + /// also returns the maximal dimensionality among all basis terms + /// \note This is not the classical effective dimensionality, + /// since all dimensions can still be involved. + int ComputeEffDims(int *effdim); + + /// \brief Computes the effective dimensionality of each basis term, + /// i.e., the number of dimensions that enter with a non-zero degree. + /// also returns the maximal dimensionality among all basis terms + /// \note This is not the classical effective dimensionality, + /// since all dimensions can still be involved. + int ComputeEffDims(Array1D &effdim); + + /// \brief Encode multiIndex into a 'sparse' format where the bases are ordered by their effective dimensionality. + /// The i-th element in sp_mindex stores all the bases that have effective dimensionality equal to i. Also, only non-zero components are stored. + /// \todo There is no double* version of this function + void EncodeMindex(Array1D< Array2D >& sp_mindex); + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Moment/sensitivity extraction given coefficients + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Compute the mean of the PC given coefficients in double *coef + /// (seeking the zero-th order multiindex) + double ComputeMean(const double *coef); + + /// \brief Compute the mean of the PC given coefficient array coef(seeking the zero-th order multiindex) + double ComputeMean(Array1D& coef); + + /// \brief Compute the variance fractions of each basis term given + /// coefficients in double *coef; returns the variance fractions in the double *varfrac + /// \note Also returns the variance + /// \note The value for the zeroth order term has a special meaning: it is equal to mean^2/variance or (mean/std)^2. + double ComputeVarFrac(const double *coef, double *varfrac); + + /// \brief Compute the variance fractions of each basis term given + /// coefficient array coef; returns the variance fractions in the array varfrac + /// \note Also returns the variance + /// \note The value for the zeroth order term has a special meaning: it is equal to mean^2/variance or (mean/std)^2. + double ComputeVarFrac(Array1D& coef, Array1D& varfrac); + + /// \brief Compute main effect sensitivity (Sobol) indices given coefficient array coef; returns the indices in the array mainsens + /// \todo There is no double* version of this function + void ComputeMainSens(Array1D& coef, Array1D& mainsens); + + /// \brief Compute total effect sensitivity (Sobol) indices given coefficient array coeff; returns the indices in the array totsens + /// \todo There is no double* version of this function + void ComputeTotSens(Array1D& coef, Array1D& totsens); + + /// \brief Compute joint effect sensitivity (Sobol) indices given coefficient array coeff; returns the indices in the array jointsens + /// \note jointsens will be populated as a strictly upper-diagonal matrix + /// \todo There is no double* version of this function + void ComputeJointSens(Array1D& coef, Array2D& jointsens); + + + ///////////////////////////////////////////////////////////////////////////////////////// + /// Other + ///////////////////////////////////////////////////////////////////////////////////////// + + /// \brief Set the verbosity level + /// \note Currently, the values of 0, 1 and 2 are implemented + void SetVerbosity(int verbosity) { uqtkverbose_ = verbosity; } + + /// \brief Evaluate norms-squared of all bases and return in the array normsq + /// \todo There is no double* version of this function + void EvalNormSq(Array1D& normsq); + void EvalNormSq(double* normsq, const int npc); + + /// \brief Evaluate norms-squared analytically of all bases and return in the array normsq + /// \todo There is no double* version of this function + /// \note Custom PCs do not have this capability + void EvalNormSqExact(Array1D& normsq); + + /// \brief Check if the point x is in the PC domain + bool IsInDomain(double x); + + + + private: + /// \brief Dummy default constructor, which should not be used as it is not well defined + /// Therefore we make it private so it is not accessible + /// \note All parameters are intialized to dummy values. + PCSet(): order_(0), nDim_(0) {}; + + + /// \brief Dummy copy constructor, which should not be used as it is currently + /// not well defined. Therefore we make it private so it is not accessible. + /// \note I am not sure actually whether the initialization performed below + /// is legal as it requires access to private data members of the class that + /// is passed in. + PCSet(const PCSet &obj):order_(obj.order_), nDim_(obj.nDim_) {}; + + /// \brief Compute maximal order per dimension and fill in the array maxOrdPerDim_ + void ComputeMaxOrdPerDim(); + + /// \brief Initialization of the appropriate variables + /// \note Intrusive implementation only works with TotalOrder multiindes + /// \todo Test and allow intrusive implementation with customized multiindices + void Initialize(const string ordertype); + + /// \brief Initialize quadrature for computing triple products(ISP) and orthogonal projection(NISP) + // void InitQuadrature(); + + /// \brief Initialize variables that are needed only in intrusive computations + void InitISP(); + /// \brief Initialize variables that are needed only in non-intrusive computations + void InitNISP(); + + /// \brief Evaluate the expectation of product of three basis functions + void EvalBasisProd3(); + + /// \brief Evaluate the expectation of product of four basis functions + void EvalBasisProd4(); + + /// \brief Wrapper for Matrix-vector multiplication routine to be called by GMRES. + /// + /// As GMRES is a Fortran77 routine, this routine is + /// defined as a static function. One of the function arguments (obj) + /// was originally isym, a flag for matrix symmetry, but has been + /// repurposed to carry an integer handle to identify this object. + /// \note The matrix vector product here comes down to a product + /// between two PC expansions. + static void GMRESMatrixVectorProdWrapper(int* n, double* x, double* y, int* nelt, + int* ia, int* ja, double* a, int* obj) { + // Look up *obj in the map that relates integer indices to pointers to PCSet + OMap_t::iterator it = omap_->find(*obj); + if(it == omap_->end()) { + string err_message = (string) "GMRESMatrixVectorProdWrapper():" + + " the callback object is not a valid entry in the map"; + throw Tantrum(err_message); + } + // Perform callback to the member function of the proper PCSet instance + it->second->GMRESMatrixVectorProd(x, a, y); + + return; + } + + /// \brief Wrapper for preconditioner routine to be called by GMRES. + /// + /// As GMRES is a Fortran77 routine, this routine is + /// defined as a static function. One of the function arguments (obj) + /// was originally isym, a flag for matrix symmetry, but has been + /// repurposed to carry an integer handle to identify this object. + /// \note Since we currently do not use preconditioning, this routine + /// does nothing. It is a place holder for future use. + static void GMRESPreCondWrapper(int* n, double* r, double* z, int* nelt, + int* ia, int* ja, double* a, int* obj, + double* rwork, int* iwork) { }; + + /// \brief Actual C++ implementation of the matric vector multiplication + /// for GMRES for the division operation. + /// + /// Given the structure of the problem, this boils down to the product + /// between two PC variables. + void GMRESMatrixVectorProd(const double* x, const double*a, double* y) const; + + /// \brief Computes natural logarithm using Taylor expansion: + /// N + /// p2 = ln(p1) = ln(p1Mean) + sum d + /// n=1 n + /// + /// (n+1) + /// (-1) n p1 + /// where d = ---- *x , and x = ------ - 1 + /// n n p1Mean + /// + /// \note See Exp notes for info related to tolerance and maximum number of terms criteria + /// for truncating the Taylor series + void LogTaylor(const double* p1, double* p2) const; + + /// \brief Computes natural logarithm by numerical integration: + /// calculate p2=ln(p1) by integrating du=dx/x to get ln(x) + void LogInt(const double* p1, double* p2) const; + + /// \brief Wrapper for LogIntRhs. The first component of f_data pointer + /// carries an integer handle identifying the appropriate PC object + /// \todo Why is this function a static int instead of static void? Should + /// there be a return statement at the end? + static int LogIntRhsWrapper(realtype t, N_Vector y, N_Vector ydot, void *f_data) + { + double indxobj = ((double*) f_data)[0] ; + + OMap_t::iterator it = omap_->find((int) indxobj); + + if (it == omap_->end()) + { + string err_message = (string) "LogIntRhsWrapper():" + + " the callback object is not a valid entry in the map"; + throw Tantrum(err_message); + } + + // Perform callback to the member function of the proper PCSet instance + it->second->LogIntRhs(t,y,ydot,f_data); + + return ( 0 ) ; + + } + + /// \brief Evaluates rhs necessary to compute natural logarithm via integration + int LogIntRhs(realtype t, N_Vector y, N_Vector ydot, void *f_data) const; + + /// \brief Verbosity level + /// \note Currently the values of 0, 1 or 2 are implemented. + int uqtkverbose_; + + /// \brief String indicator of ISP or NISP implementation type + string spType_; + + /// \brief String indicator of PC type + string pcType_; + + /// \brief String indicator of multiindex ordering + string pcSeq_; + + /// \brief Pointer to the class that defines the basis type and functions + PCBasis* p_basis_; + + /// \brief Order of the PC representation + int order_; + + /// \brief Maximal order within all dimensions + int maxorddim_; + + /// \brief Array of maximum orders requested if custom(HDMR) ordering is requested + Array1D maxOrders_; + + /// \brief Array of maximum orders per dimension + Array1D maxOrdPerDim_; + + /// \brief Number of stochastic dimensions (degrees of freedom) in the PC representation + const int nDim_; + + /// \brief Number of quadrature points used + int nQuadPoints_; + + /// \brief Total number of terms in the PC expansions + int nPCTerms_; + + /// \brief Relative tolerance for Taylor series approximations + double rTolTaylor_; + + /// \brief Max number of terms in Taylor series approximations + int maxTermTaylor_; + + /// \brief Tolerance to avoid floating-point errors + double SMALL_; + + /// \brief GMRES tolerance in Div() + double rTolGMRESDiv_; + + /// \brief Array to store basis functions evaluated at quadrature points + /// for each order: psi_(iqp,ipc) contains the value of the polynomial + /// chaos ipc-th basis at the location of quadrature point iqp. + Array2D psi_; + + /// \brief Array with the norms squared of the basis functions, + /// corresponding to each term in the PC expansion + Array1D psiSq_; + + /// \brief Array to store quadrature points + Array2D quadPoints_; + + /// \brief Array to store quadrature weights + Array1D quadWeights_; + + /// \brief Array to store quadrature point indexing; useful for nested rules + Array2D quadIndices_; + + /// \brief Array to store multi-index: multiIndex_(ipc,idim) contains the order + /// of the basis function associated with dimension idim, for the ipc-th term in the PC + /// expansion. + Array2D multiIndex_; + + /// \brief i-indices of <\\Psi_i \\Psi_j \\Psi_k> terms that are not zero, for all k + /// \note Stored as a vector over k, with each element being a vector of i-indices itself + Array1D > iProd2_; + + /// \brief j-indices of <\\Psi_i \\Psi_j \\Psi_k> terms that are not zero, for all k + /// \note Stored as a vector over k, with each element being a vector of j-indices itself + Array1D > jProd2_; + + /// \brief <\\Psi_i \\Psi_j \\Psi_k> terms that are not zero, for all k + /// \note Stored as a vector over k, with each element being a vector of <\\Psi_i \\Psi_j \\Psi_k> values + Array1D > psiIJKProd2_; + + /// \brief i-indices of <\\Psi_i \\Psi_j \\Psi_k \\Psi_l> terms that are not zero, for all l + /// \note Stored as a vector over l, with each element being a vector of i-indices itself + Array1D > iProd3_; + + /// \brief j-indices of <\\Psi_i \\Psi_j \\Psi_k \\Psi_l> terms that are not zero, for all l + /// \note Stored as a vector over l, with each element being a vector of j-indices itself + Array1D > jProd3_; + + /// \brief k-indices of <\\Psi_i \\Psi_j \\Psi_k \\Psi_l> terms that are not zero, for all l + /// \note Stored as a vector over l, with each element being a vector of k-indices itself + Array1D > kProd3_; + + /// \brief <\\Psi_i \\Psi_j \\Psi_k \\Psi_l> terms that are not zero, for all l + /// \note Stored as a vector over l, with each element being a vector of <\\Psi_i \\Psi_j \\Psi_k \\Psi_l> values + Array1D > psiIJKLProd3_; + + /// \brief Flag for method to compute log: TaylorSeries or Integration + LogCompMethod logMethod_ ; + + /// \brief CVODE parameter: maximal order + int CVmaxord_; + + /// \brief CVODE parameter: maximal number of steps + int CVmaxnumsteps_ ; + + /// \brief CVODE parameter: initial step size + double CVinitstep_; + + /// \brief CVODE parameter: maximal step size + double CVmaxstep_; + + /// \brief CVODE parameter: relative tolerance + double CVrelt_; + + /// \brief CVODE parameter: absolute tolerance + double CVabst_ ; + + /// \brief Check cvode return for errors + int Check_CVflag(void *flagvalue, const char *funcname, int opt) const; + + /// \brief Index of this class + int my_index_; + + /// \brief Number of free parameters to specify the basis + int narg_; + + /// \brief Parameter alpha for PCs that require a parameter (GLG,SW,JB) + double alpha_; + /// \brief Parameter beta for PCs that require two parameters (SW,JB) + double beta_; + + /// \brief Definition of a map to connect integer indexes with pointers to this class + typedef std::map OMap_t; + /// \brief index of next object in map + static int next_index_; + /// \brief Map to connect integer indexes with pointers to this class + static OMap_t *omap_; + +}; + +#endif /* !PCSET_H_SEEN */ diff --git a/cpp/lib/quad/CMakeLists.txt b/cpp/lib/quad/CMakeLists.txt new file mode 100644 index 00000000..e322ec05 --- /dev/null +++ b/cpp/lib/quad/CMakeLists.txt @@ -0,0 +1,17 @@ +project(UQTk) + +SET(quad_HEADERS + quad.h + ) + +add_library(uqtkquad quad.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) + +# Install the library +INSTALL(TARGETS uqtkquad DESTINATION lib) + +# Install the header files +INSTALL(FILES ${quad_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/quad/quad.cpp b/cpp/lib/quad/quad.cpp new file mode 100644 index 00000000..e603aa78 --- /dev/null +++ b/cpp/lib/quad/quad.cpp @@ -0,0 +1,977 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file quad.cpp +/// \author K. Sargsyan, C. Safta 2010 - +/// \brief Quadrature class + +#include +#include +#include +#include "quad.h" + +#include "error_handlers.h" +#include "combin.h" +#include "multiindex.h" +#include "gq.h" +#include "arrayio.h" +#include "arraytools.h" + +// Constructor given quadrature type, sparsity, dimensionaility, grid parameter (ppd or level), and associated PC parameters, if relevant +Quad::Quad(char *grid_type, char *fs_type,int ndim, int param,double alpha, double betta)//Default +{ + + // Initialize the dimensionality, grid types and boundaries + this->ndim_=ndim; + aa_.Resize(ndim,-1.e0); + bb_.Resize(ndim,1.e0); + this->grid_type_=grid_type; + this->fs_type_=fs_type; + + // Initialize parameters + this->alpha_=alpha; + this->beta_=betta; + + this->alphas_.Resize(this->ndim_,alpha); + this->betas_.Resize(this->ndim_,betta); + this->growth_rules_.Resize(this->ndim_,0); + this->grid_types_.Resize(this->ndim_,grid_type); + this->param_.Resize(this->ndim_,param); + + // Set the quadrature level + maxlevel_=param; + + // The rest of initialization + this->init(); + + +} + +// Constructor given quadrature type, sparsity, dimensionaility, grid parameter (ppd or level), and associated PC parameters, if relevant +// Overloaded for unisotropy +Quad::Quad(Array1D& grid_types, char *fs_type, Array1D& param,Array1D& alphas, Array1D& bettas) +{ + + // Initialize the dimensionality, grid types and boundaries + this->ndim_=grid_types.Length(); + aa_.Resize(this->ndim_,-1.e0); + bb_.Resize(this->ndim_,1.e0); + this->growth_rules_.Resize(this->ndim_,0); + + this->grid_types_=grid_types; + this->fs_type_=fs_type; + + // Initialize parameters + this->alphas_=alphas; + this->betas_=bettas; + + // Set the quadrature level + maxlevel_=param(0); + param_=param; + + // The rest of initialization + this->init(); + + +} + + +void Quad::init() +{ + // Hardwired non-verbosity + SetVerbosity(0); + + // Make sure we are not asking for too many quadrature points + if (this->fs_type_=="full"){ + double prod=1.; + for (int i=0;indim_;i++) + prod *= this->param_(i); + if (quadverbose_>0) + cout << "Computing " << prod << " quadrature points in " << this->ndim_ << " dimensions" << endl; + if (this->ndim_*prod > QD_MAX){ + throw Tantrum("Quad::Quad(): The requested number of points is too large"); + } + } + + // Sanity check - do not use 0 ppd with full tensor-product + if (this->fs_type_=="full"){ + if(this->maxlevel_==0) + throw Tantrum("Quad::Quad(): 'full' does not make sense with parameter 0."); + } + + // Set the proper growth rules for sparse quadrature + else if (this->fs_type_=="sparse"){ + if(this->ndim_==1) + throw Tantrum("Quad::Quad(): 'sparse' does not make sense in 1D, use 'full' instead."); + + for (int i=0;indim_;i++){ + if (this->grid_types_(i)=="CC" or this->grid_types_(i)=="NC") + this->growth_rules_(i)=0; + else if (this->grid_types_(i)=="LU") + this->growth_rules_(i)=0; + else if (this->grid_types_(i)=="NCO" or this->grid_types_(i)=="CCO") + this->growth_rules_(i)=1; + else if (this->grid_types_(i)=="HG") + this->growth_rules_(i)=1; + else if (this->grid_types_(i)=="JB") + this->growth_rules_(i)=0; + else if (this->grid_types_(i)=="GLG") + this->growth_rules_(i)=0; + else if (this->grid_types_(i)=="SW") + this->growth_rules_(i)=0; + else if (this->grid_types_(i)=="pdf") + this->growth_rules_(i)=0; + else if (this->grid_types_(i)=="GP3") + this->growth_rules_(i)=0; + else + throw Tantrum("Quad::Quad(): Grid type unrecognized! Options are 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf' or 'GP3'"); + } + } + + else + throw Tantrum("Quad::Quad(): Either 'full' or 'sparse' should be specified"); + + return; + +} + +// Set two-sided domain for quadrature +void Quad::SetDomain(Array1D& aa, Array1D& bb) +{ + // Dimensionality check + if ( (int) aa.XSize() != ndim_ or (int) bb.XSize() != ndim_ ) + throw Tantrum("Quad::SetDomain(): Dimension error!"); + + aa_=aa; + bb_=bb; + + return; +} + +// Set one-sided domain for quadrature +void Quad::SetDomain(Array1D& aa) +{ + // Dimensionality check + if ( (int) aa.XSize() != ndim_ ) + throw Tantrum("Quad::SetDomain(): Dimension error!"); + + aa_=aa; + + return; +} + +// Set quadrature rule (i.e. points and weights) +void Quad::SetRule(Array2D& q, Array1D& w) +{ + // Set a rule + this->SetQdpts(q); + this->SetWghts(w); + + return; +} + + +// Get quadrature rule (i.e. points and weights) +void Quad::GetRule(Array2D& q, Array1D& w) +{ + // Get the rule + this->GetQdpts(q); + this->GetWghts(w); + + return; +} + +// Multiply two rules (tensor product of points and weights) +void Quad::MultiplyTwoRules(QuadRule *rule1,QuadRule *rule2,QuadRule *rule_prod) +{ + + // Get the sizes + int n1=rule1->qdpts.XSize(); + int n2=rule2->qdpts.XSize(); + + int d1=rule1->qdpts.YSize(); + int d2=rule2->qdpts.YSize(); + + // Compute the sizes of the product rule + int n12=n1*n2; + int d12=d1+d2; + + // Resize the product rule containers + rule_prod->qdpts.Resize(n12,d12,0.e0); + rule_prod->wghts.Resize(n12,0.e0); + + for(int in2=0;in2qdpts(in1+in2*n1,id1)=rule1->qdpts(in1,id1); + } + for(int id2=0;id2qdpts(in1+in2*n1,id2+d1)=rule2->qdpts(in2,id2); + } + + // Weights are multiplied + rule_prod->wghts(in1+in2*n1)=rule1->wghts(in1)*rule2->wghts(in2); + + } + } + + + + + + return; +} + + +// Multiple and array of rules +void Quad::MultiplyManyRules(int nrules, QuadRule *rules, QuadRule *rule_prod) +{ + + // Working rules + QuadRule rule_1d; + QuadRule rule_cur; + QuadRule rule_prod_h; + + for(int i=0;iMultiplyTwoRules(&rule_cur,&rule_1d,&rule_prod_h); + + rule_cur=rule_prod_h; + + } + + + rule_prod->qdpts=rule_prod_h.qdpts; + rule_prod->wghts=rule_prod_h.wghts; + + return; +} + +// Subtract two rules +void Quad::SubtractTwoRules(QuadRule *rule1,QuadRule *rule2,QuadRule *rule_sum) +{ + + for(int i=0;i<(int) rule2->wghts.XSize();i++) + rule2->wghts(i) *= -1.; + + this->AddTwoRules(rule1,rule2,rule_sum); + + return; +} + +// Add two rules +void Quad::AddTwoRules(QuadRule *rule1,QuadRule *rule2,QuadRule *rule_sum) +{ + // Get the sizes + int n1=rule1->qdpts.XSize(); + int n2=rule2->qdpts.XSize(); + + int d1=rule1->qdpts.YSize(); + int d2=rule2->qdpts.YSize(); + + // Sanity check + if(d1!=d2){ + printf("Quad::AddTwoRules(): only rules of same dimensionality can be added to each other! %d %d\n",d1,d2); + exit(1); + } + int d=d1; + + // The size of the full sum + int n12=n1+n2; + + merge(rule1->qdpts,rule2->qdpts,rule_sum->qdpts); + merge(rule1->wghts,rule2->wghts,rule_sum->wghts); + + return; +} + +/**********************************************************************************/ +/**********************************************************************************/ + +// Creating 1D rules +void Quad::create1DRule(string gridtype,Array1D& qdpts,Array1D& wghts,int ngr, double a, double b) +{ + if (gridtype=="CC"){ + this->create1DRule_CC(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="NC"){ + this->create1DRule_NC(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="NCO"){ + this->create1DRule_NCO(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="CCO"){ + this->create1DRule_CCO(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="LU" or gridtype=="LU_N"){ + this->create1DRule_LU(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="HG"){ + this->create1DRule_HG(qdpts,wghts,ngr); + } + else if (gridtype=="JB"){ + this->create1DRule_JB(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="GLG"){ + this->create1DRule_GLG(qdpts,wghts,ngr); + } + else if (gridtype=="SW"){ + this->create1DRule_SW(qdpts,wghts,ngr); + } + else if (gridtype=="pdf"){ + this->create1DRule_pdf(qdpts,wghts,ngr,a,b); + } + else if (gridtype=="GP3"){ + this->create1DRule_GP3(qdpts,wghts,ngr,a,b); + } + + else + throw Tantrum("Quad::create1DRule(): Grid type unrecognized! Options are 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf' or 'GP3' "); + + return; +} +/**********************************************************************************/ +/**********************************************************************************/ + +// Legendre-Uniform +void Quad::create1DRule_LU(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + // Work arrays + Array1D endpts(2,0.e0); // real array of length two with zeroed values, needed to pass to gaussqC + Array1D bwork(ngr,0.e0); + Array1D qdpts_1d(ngr,0.e0); + int kind=1; + double alpha=0.0,beta=0.0; + + gq( kind, alpha, beta, qdpts_1d, wghts ); + + // Rescale and index + for(int i=0; i& qdpts,Array1D& wghts, int ngr) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + // Work arrays + Array1D endpts(2,0.e0); // real array of length two with zeroed values, needed to pass to gaussqC + Array1D bwork(ngr,0.e0); + Array1D qdpts_1d(ngr,0.e0); + int kind=4; + double alpha=0.0,beta=0.0; + + const double pi = 4.e0*atan(1.e0); + double spi = sqrt(pi); + double fac = sqrt(2.0); + + gq( kind, alpha, beta, qdpts_1d, wghts ); + // Rescale and index + for(int i=0; i& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + if (ngr==1){ + qdpts(0)=0.0; + wghts(0)=2.0; + } + else{ + for (int i=0;i exact(ngr,0.e0); + for (int i=0;i& qdpts,Array1D& wghts,int ngr, double a, double b) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + for (int i=0;i exact(ngr,0.e0); + for (int i=0;i& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + if (ngr==1){ + qdpts(0)=0.0; + wghts(0)=2.0; + } + + else { + + double pi=4.*atan(1.); + double theta,f; + + for (int i=0;i& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + double pi=4.*atan(1.); + double theta,f; + + for (int i=0;i& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + // The norm + double mu0= pow(2.,alpha_+beta_+1.)*beta(alpha_+1.,beta_+1.); + + gq (5, alpha_, beta_, qdpts, wghts ) ; + + // Rescale and index + for(int i=0; i& qdpts,Array1D& wghts, int ngr) +{ + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + gq (6, alpha_, 0.0, qdpts, wghts ) ; + + // Indexing + for(int i=0; i& qdpts,Array1D& wghts, int ngr) +{ + assert(alpha_>0.0); + + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + // Work arrays + Array1D al(ngr,0.e0); + Array1D be(ngr, 0.e0); + + double ee=exp(beta_*beta_/2.); + double eesq = ee*ee ; + + for(int i=0; i& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + + qdpts.Resize(ngr,0.e0); + wghts.Resize(ngr,0.e0); + + // Work arrays + Array1D al(ngr,0.e0); + Array1D be(ngr, 0.e0); + + // Read the recursion coefficients from the data file + Array2D albe; + read_datafileVS(albe,"ab.dat"); + if ((int)albe.XSize()& qdpts,Array1D& wghts, int ngr, double a, double b) +{ + + int nqp[7]={1,3,7,15,31,63,127}; + + if ((ngr<1) || (ngr>7)) { + printf("Quad::create1DRule_GP3() : ngr=%d !\n",ngr) ; + throw Tantrum("The above Gauss-Patterson rule is not available!"); + } + + qdpts.Resize(nqp[ngr-1],0.e0); + wghts.Resize(nqp[ngr-1],0.e0); + + /* Read the quadrature points and weights from data file */ + stringstream fname; + fname << "gp3rules/gp3_o" << ngr << "_p.dat"; + + Array2D din; + read_datafileVS(din,fname.str().c_str()); + if ((int)din.XSize()!=nqp[ngr]) + { + printf("Quad::create1DRule_GP3() : ngr=%d, nqp=%d vs %d !\n",ngr,(int) din.XSize(), nqp[ngr]) ; + throw Tantrum("The the number of quadrature points does not match the expected value"); + } + for(int i=0; i<(int)din.XSize();i++) qdpts(i) = din(i,0); + + fname.str("gp3rules/gp3_o"); + fname << ngr << "_w.dat"; + + read_datafileVS(din,fname.str().c_str()); + if ((int)din.XSize()!=nqp[ngr]) + { + printf("Quad::create1DRule_GP3() : ngr=%d, nqp=%d vs %d !\n",ngr,(int) din.XSize(), nqp[ngr]) ; + throw Tantrum("The the number of quadrature weights does not match the expected value"); + } + for(int i=0; i<(int)din.XSize();i++) wghts(i) = din(i,0); + + // Rescale + for(int i=0; ifs_type_=="full"){ + + QuadRule rule_1d; + QuadRule rule_cur; + QuadRule rule_prod; + + for(int id=0;idndim_;id++){ + + Array1D qdpts_1d; + this->create1DRule(this->grid_types_(id),qdpts_1d,rule_1d.wghts,param_(id),aa_(id),bb_(id)); + + array1Dto2D(qdpts_1d,rule_1d.qdpts); + + if(id==0) + rule_prod=rule_1d; + else + this->MultiplyTwoRules(&rule_cur,&rule_1d,&rule_prod); + + rule_cur=rule_prod; + + } + + rule_=rule_prod; + } + + + //...or multiply rules in a specific way and combine them to obtain sparse rule + else if (this->fs_type_=="sparse"){ + this->SetLevel(-1); + + // Incremental buildup of levels + for(int il=0;il<=maxlevel_;il++){ + if (quadverbose_ > 0) + cout << "Level " << il << " / " << maxlevel_ << endl; + this->nextLevel(); + } + } + + else + throw Tantrum("Quad::SetRule(): unknown rule type."); + + return; +} + +// Compute the next-level points +void Quad::nextLevel() +{ + + this->SetLevel(nlevel_+1); + + QuadRule rule_level; + QuadRule rule_cur; + QuadRule rule_total; + + Array2D multiIndexLevel; + this->getMultiIndexLevel(multiIndexLevel,nlevel_,ndim_); + + int nMultiIndicesLevel=multiIndexLevel.XSize(); + + Array2D multiIndexLevel_npts(nMultiIndicesLevel,ndim_,0); + + for(int j=0;jgrowth_rules_(id)==0){ //2^l+1 + if ( multiIndexLevel(j,id)==0){ + npts = 1; + npts_1=0; + } + else if ( multiIndexLevel(j,id)==1){ + npts=3; + npts_1=1; + } + else { + npts=(int) pow(2,multiIndexLevel(j,id))+1; + npts_1=(int) pow(2,multiIndexLevel(j,id)-1)+1; + } + } + else if (this->growth_rules_(id)==1){ //2^(l+1)-1 + npts = (int) pow(2,multiIndexLevel(j,id)+1)-1; + npts_1 = (int) pow(2,multiIndexLevel(j,id) )-1; + } + + Array1D qdpts_1d; + Array1D indices_1d; + + this->create1DRule(this->grid_types_(id),qdpts_1d,rules[id].wghts,npts,aa_(id),bb_(id)); + array1Dto2D(qdpts_1d,rules[id].qdpts); + if(npts_1>0){ + this->create1DRule(this->grid_types_(id),qdpts_1d,rules_1[id].wghts,npts_1,aa_(id),bb_(id)); + array1Dto2D(qdpts_1d,rules_1[id].qdpts); + this->SubtractTwoRules(&rules[id],&rules_1[id], &srules[id]); + } + else + srules[id]=rules[id]; + + }//end of id loop + + QuadRule rule_temp; + + this->MultiplyManyRules(ndim_,srules,&rule_temp); + + if(j==0) + rule_level=rule_temp; + else + this->AddTwoRules(&rule_cur,&rule_temp,&rule_level); + + + // if (rule_level.wghts.XSize()>1.e+6) + // this->compressRule(&rule_level); + + rule_cur=rule_level; + + delete []rules; + delete []rules_1; + delete []srules; + } + + if (nlevel_==0) + rule_total=rule_level; + else + this->AddTwoRules(&rule_,&rule_level,&rule_total); + + + rule_=rule_total; + this->compressRule(&rule_); + + + return; +} + +// Auxilliary function: get the level of the multi-index +void Quad::getMultiIndexLevel(Array2D& multiIndexLevel, int level,int ndim) +{ + + int iup=0; + + int nup_level=choose(ndim+level-1,level); + + multiIndexLevel.Resize(nup_level,ndim,0); + + if (ndim==1) + multiIndexLevel(0,0)=level; + + else{ + + for (int first = level; first >= 0; first--){ + + Array2D theRest; + getMultiIndexLevel(theRest,level-first,ndim-1); + + for(int j=0;j<(int)theRest.XSize();j++){ + multiIndexLevel(iup,0)=first; + for(int id=1;idqdpts.XSize(); + int ndim = rule->qdpts.YSize(); + for(int iq=0;iqqdpts(iq,id))<1.e-15) + rule->qdpts(iq,id)=0.e0; + + Array1D ind; + for(int i=0;i qw = rule->qdpts; + paddMatCol(qw,rule->wghts); + + if (quadverbose_==1) + cout << "Sorting quadrature of size " << qw.XSize() << endl; + + quicksort3(qw,0,qw.XSize()-1); + Array1D qw_prev,q_prev; + getRow(qw,0,qw_prev); + subVector(qw_prev,ind,q_prev); + + Array2D qwt=Trans(qw); + Array1D choose_ind(1,0); + int iq_prev=0; + + for(int iq=1; iq qw_cur,q_cur; + getCol(qwt,iq,qw_cur); + subVector(qw_cur,ind,q_cur); + + if(is_equal(q_cur,q_prev)) + qwt(ndim,iq_prev)+=qwt(ndim,iq); + else{ + choose_ind.PushBack(iq); + q_prev = q_cur; + iq_prev=iq; + } + } + qw=Trans(qwt); + + Array2D tmp; + subMatrix_row(qw,choose_ind,tmp); + + subMatrix_col(tmp,ind,rule->qdpts); + getCol(tmp,ndim,rule->wghts); + + if (quadverbose_==1) + cout << "Quadrature size " << choose_ind.XSize() << " points" << endl; + + return; + +} diff --git a/cpp/lib/quad/quad.h b/cpp/lib/quad/quad.h new file mode 100644 index 00000000..c690258d --- /dev/null +++ b/cpp/lib/quad/quad.h @@ -0,0 +1,253 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file quad.h +/// \author K. Sargsyan, C. Safta 2010 - +/// \brief Header file for the quadrature class + +#ifndef QUAD_H_SEEN +#define QUAD_H_SEEN + +#include "Array1D.h" +#include "Array2D.h" + +#include +#include +#include +#include +using namespace std; // needed for python string conversion + +/// \brief Capping the maximum value of quadrature array entries +/// for full tensor-product quadrature, i.e. d*N^d < QD_MAX +#define QD_MAX 20000000 + +/// \class Quad +/// \brief Generates quadrature rules +/// \note Besides quadrature rules corresponding to PC bases (i.e. LU, HG, LG, SW, JB), +/// Clenshaw-Curtis(CC) and Newton-Cotes(NC) +/// as well as their Open (with no endpoints) versions (CCO, NCO) are implemented. +/// Also, Gauss-Patterson (GP3) and custom (pdf) rules are added. +class Quad { +public: + /// \brief Constructor: initializes the rule type, sparseness type, dimensionality, level + /// or ppd parameter, and two optional parameters for quadrature rule + /// \note Options for the arguments are: + /// grid_type : LU, HG, LG, SW, JB, CC, CCO, NC, NCO, GP3, pdf + /// fs_type : full, sparse + /// ndim : integer dimensionality + /// param : integer points-per-dimension (if full), or level (if sparse) + /// alpha : parameter #1 for the corresponding PC type (e.g. LG requires one parameter) + /// betta : parameter #2 for the corresponding PC type (e.g. JB requires two parameters) + Quad(char *grid_type, char *fs_type,int ndim,int param,double alpha=0.0, double betta=1.0); + + /// \brief Constructor, overloaded for dimension-unisotropy: initializes + /// the dimension-specific rule types, sparseness type, dimension-specific ppd or level, + /// and two optional parameters for quadrature rule per each dimension + /// \note Options for the arguments are: + /// grid_types : array with entry options LU, HG, LG, SW, JB, CC, CCO, NC, NCO, GP3, pdf + /// fs_type : full, sparse + /// param : integer array for points-per-dimension (if full), or + /// an array with first element indicating the level (if sparse) + /// alpha : array of parameters #1 for the corresponding PC type (e.g. LG requires one parameter) + /// bettas : array of parameters #2 for the corresponding PC type (e.g. JB requires two parameters) + Quad(Array1D& grid_types, char *fs_type, Array1D& param,Array1D& alphas, Array1D& bettas); + + /// \brief Constructor: empty + Quad() {}; + /// \brief Destructor + ~Quad() {}; + + /// \brief Initialization function + void init(); + + /// \brief Set the parameter alpha + void SetAlpha(double alpha){this->alpha_=alpha; } + /// \brief Set the parameter beta + void SetBeta(double betta){this->beta_=betta; } + + /// \brief Set the domain endpoints (for compact support domains) + void SetDomain(Array1D& aa, Array1D& bb); + /// \brief Set the domain endpoint (for semi-infinite domains) + void SetDomain(Array1D& aa); + /// \brief Get the domain endpoints (for compact support domains) + void GetDomain(Array1D& aa, Array1D& bb) const {aa=aa_; bb=bb_;} + /// \brief Get the domain endpoint (for semi-infinite domains) + void GetDomain(Array1D& aa) const {aa=aa_;} + + /// \brief Set the rule externally (only quadrature points and weights) + void SetRule(Array2D& q, Array1D& w); + /// \brief Set the rule externally (quadrature points, weights and indices) + /// Dummy function for backward compatibility + void SetRule(Array2D& q, Array1D& w, Array2D& ind){this->SetRule(q,w);} + /// \brief Set the rule externally (quadrature points, weights, indices, and the level) + //void SetRule(Array2D& q, Array1D& w, Array2D& ind, int param); + + /// \brief Set the rule (the function that builds quadrature points/weights/indices) + void SetRule(); + + /// \brief Get the quadrature rule + void GetRule(Array2D& q, Array1D& w); + /// \brief Get the quadrature rule with indexing + /// Dummy function for backward compatibility + void GetRule(Array2D& q, Array1D& w, Array2D& ind){this->GetRule(q,w);} + + /// \brief Externally set quadrature points + void SetQdpts(Array2D& q){ rule_.qdpts=q; return;} + /// \brief Externally set the weights + void SetWghts(Array1D& w){ rule_.wghts=w; return;} + /// \brief Externally set the indices + // void SetIndices(Array2D& ind){ rule_.indices=ind; return;} + + /// \brief Get quadrature points + void GetQdpts(Array2D& q){ q=rule_.qdpts; return;} + /// \brief Get the weights + void GetWghts(Array1D& w){ w=rule_.wghts; return;} + /// \brief Get the indices + //void GetIndices(Array2D& ind){ ind=rule_.indices; return;} + + /// \brief Set the level parameter + void SetLevel(int param) {nlevel_=param; return;} + + /// \brief Compute the indices of the next-level points + void nextLevel(); + + /// \brief Get the number of quadrature points + int GetNQ() {return rule_.qdpts.XSize(); } + + /// \brief Set the verbosity level + /// \note Currently, the values of 0, 1 and 2 are implemented + void SetVerbosity(int verbosity) { quadverbose_ = verbosity; } + + + + private: + + /// \brief Dummy copy constructor, which should not be used as it is currently not well defined + Quad(const Quad &) {}; + + /// \brief The left endpoints of the domain + Array1D aa_; + /// \brief the right endpoints of the domain + Array1D bb_; + + /// \brief Verbosity level + /// \note Currently the values of 0, 1 or 2 are implemented. + int quadverbose_; + + /// \brief The first parameter of the rule, if any + double alpha_; + /// \brief The second parameter of the rule, if any + double beta_; + /// \brief The first parameter of the rule, if any + Array1D alphas_; + /// \brief The second parameter of the rule, if any + Array1D betas_; + + /// \brief Rule structure that stores quadrature points, weights and indices + typedef struct + { + /// \brief Quadrature points + Array2D qdpts; + /// \brief Quadrature weights + Array1D wghts; + } QuadRule; + + /// \brief The quadrature rule structure + QuadRule rule_; + + /// \brief The dimensionality + int ndim_; + + /// \brief The current level, working variable for hierarchical construction + int nlevel_; + + /// \brief The level for sparse rules, or the number of grid points per dim + /// for full product rules + int maxlevel_; + Array1D param_; + + /// \brief Multiply two rules (full tensor product) + void MultiplyTwoRules(QuadRule *rule1,QuadRule *rule2,QuadRule *rule_prod); + /// \brief Multiply many rules (full tensor product) + void MultiplyManyRules(int nrules, QuadRule *rules, QuadRule *rule_prod); + /// \brief Add two rules + void AddTwoRules(QuadRule *rule1,QuadRule *rule2,QuadRule *rule_sum); + /// \brief Subtract two rules + void SubtractTwoRules(QuadRule *rule1,QuadRule *rule2,QuadRule *rule_sum); + + /// \brief Compute 1D rules + void create1DRule(string gridtype,Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + + /// \brief Clenshaw-Curtis (includes the endpoints) + /// \note Heavily adopted from http://people.sc.fsu.edu/~jburkardt/cpp_src/sparse_grid_cc/sparse_grid_cc.html (distributed under LGPL) + void create1DRule_CC(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Legendre-Uniform + void create1DRule_LU(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Gauss-Hermite + void create1DRule_HG(Array1D& qdpts,Array1D& wghts, int ngr); + /// \brief Newton-Cotes (i.e. equispaced, includes the endpoints) + void create1DRule_NC(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Newton-Cotes open (i.e. excludes the endpoints) + void create1DRule_NCO(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Clenshaw-Curtis open (i.e. excludes the endpoints) + /// \note Heavily adopted from http://people.sc.fsu.edu/~jburkardt/cpp_src/sparse_grid_cc/sparse_grid_cc.html (distributed under LGPL) + void create1DRule_CCO(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Jacobi-Beta + void create1DRule_JB(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Gamma-Laguerre + void create1DRule_GLG(Array1D& qdpts,Array1D& wghts, int ngr); + /// \brief Stieltjes-Wigert + void create1DRule_SW(Array1D& qdpts,Array1D& wghts,int ngr); + /// \brief Custom rule given the recursive coefficients of the corresponding orthogonal polynomials + /// \todo Recursive coefficients are given in a file 'ab.dat'; will need to make this more friendly + void create1DRule_pdf(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + /// \brief Gauss-Patterson starting with Legendre-Uniform 3 + /// \note Hardwired reading of quadrature points and weights + void create1DRule_GP3(Array1D& qdpts,Array1D& wghts, int ngr, double a, double b); + + /// \brief Auxilliary function: get the level of the multi-index + void getMultiIndexLevel(Array2D& multiIndexLevel, int level, int ndim); + + /// \brief Growth rule: exponential(0) or linear(1) + int growth_rule_; + /// \brief Growth rules: exponential(0) or linear(1) + Array1D growth_rules_; + + /// \brief Grid type: 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf', or 'GP3' + string grid_type_; + /// \brief Vector of grid types: 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf', or 'GP3' + Array1D grid_types_; + + /// \brief Sparseness type (full or sparse) + string fs_type_; + + /// \brief Compress the rule, i.e. merge repeating points + void compressRule(QuadRule *rule); + + + +}; +#endif /* QUAD_H_SEEN */ diff --git a/cpp/lib/sampling/CMakeLists.txt b/cpp/lib/sampling/CMakeLists.txt new file mode 100644 index 00000000..348a8618 --- /dev/null +++ b/cpp/lib/sampling/CMakeLists.txt @@ -0,0 +1,20 @@ +project(UQTk) + +SET(sampling_HEADERS + sampling.hpp + ) + +add_library(uqtksampling lhs.cpp qmc.cpp) + +include_directories (../include) +include_directories (../array) +include_directories (../tools) + +include_directories (../../../dep/dsfmt) +include_directories (../../../dep/figtree) + +# Install the library +INSTALL(TARGETS uqtksampling DESTINATION lib) + +# Install the header files +INSTALL(FILES ${sampling_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/sampling/lhs.cpp b/cpp/lib/sampling/lhs.cpp new file mode 100644 index 00000000..eb895bb9 --- /dev/null +++ b/cpp/lib/sampling/lhs.cpp @@ -0,0 +1,214 @@ +#include "sampling.hpp" + +// Permutes a given array in place +void Sampling::getPerm(const int nn, const int seed, int* perm) +{ + + dsfmt_gv_init_gen_rand(seed); + + int j,t; + for (int is = 0; is getPerm(nsample, seed, perm); + + for(int is=0;is &rvar) { + int ndim = rvar.YSize(); + int nsample = rvar.XSize(); + + this->unifLHS(nsample,ndim,zSeed,rvar.GetArrayPointer()); + + return; + +} + +// Generate an array of uniform random variables with LHS +void Sampling::unifLHS(const int nsample, const int ndim, dsfmt_t *rnstate, double *rvar) { + + int *perm = new int[nsample]; + + int ii=0; + for(int id=0;idgetPerm(nsample, seed, perm); + + for(int is=0; is < nsample; is++) { + double urv=dsfmt_genrand_open_open( rnstate ); + rvar[ii]=(urv+perm[is])/nsample; + ii++; + } + } + + delete []perm; + + return; + +} + +// Generate an array of uniform random variables with LHS +void Sampling::unifLHS(dsfmt_t *rnstate, Array2D &rvar) { + + int nsample = rvar.XSize(); + int ndim = rvar.YSize(); + + this->unifLHS(nsample, ndim, rnstate, rvar.GetArrayPointer()); + + return; + +} + +// Generate an array of standard normal random variables with LHS +void Sampling::normLHS(const int zSeed, Array2D &rvar) { + + int nsample = rvar.XSize(); + int ndim = rvar.YSize(); + + this->unifLHS(zSeed, rvar); + for (int is = 0 ; is < nsample ; is++) + for (int id = 0 ; id < ndim ; id++) + rvar(is,id)=invnormcdf(rvar(is,id)); + + return; + +} + +// Generate an array of uniform random variables with LHS +void Sampling::normLHS(const int nsample, const int ndim, const int zSeed, double *rvar) { + + this->unifLHS(nsample, ndim, zSeed, rvar); + for (int is = 0 ; is < nsample ; is++) + for (int id = 0 ; id < ndim ; id++) + rvar[id*nsample+is]=invnormcdf(rvar[id*nsample+is]); + + return; + +} + +// Generate an array of uniform random variables with IHS +void Sampling::unifIHS(const int dfac, dsfmt_t *rnstate, Array2D &rndnos) { + + int ns = (int) rndnos.XSize() ; + int ndim = (int) rndnos.YSize() ; + double *rndnosPNT = rndnos.GetArrayPointer() ; + this->unifIHS(dfac, rnstate, ndim, ns, rndnosPNT) ; + +} + +// Generate an array of uniform random variables with IHS +void Sampling::unifIHS(const int dfac, dsfmt_t *rnstate, const int ndim, const int ns, double *rndnos) { + + int *ipos = (int *) malloc( ns*ndim*sizeof(int)) ; + + this->getIHSperm(ndim, ns, ipos, dfac, rnstate) ; + for ( int j = 0; j < ndim; j++) + for ( int i = 0; i < ns; i++) + rndnos[j*ns+i] = (((double) ipos[j*ns+i])+dsfmt_genrand_open_open(rnstate))*2.0/((double) ns)-1.0 ; + + free(ipos) ; + + return ; + +} + +void Sampling::getIHSperm(const int ndim, const int ns, int *x, const int dupl, dsfmt_t *rnstate) { + + double opt = ns / pow(ns,1.0/ndim) ; + int nsdup = ns * dupl; + int nsdim = ns * ndim; + vector avail(nsdim); + vector point(ndim*nsdup); + + for ( int i=0; i=1; count--) { + vector list1(count * dupl,0); + for (int i=0; i < ndim; i++) { + for (int k=0; k < dupl; k++) + for (int j=0; j < count; j++) + list1[count*k+j]=avail[i*ns+j]; + for (int k=count*dupl-1;k>=0;k--) { + int ptidx = 0; + if ( k > 0 ) + ptidx=(dsfmt_genrand_uint32(rnstate) % (k+1)); + point[i*nsdup+k] = list1[ptidx]; + list1[ptidx] = list1[k]; + } + } + + double minall = 1.e30; + int best = 0; + + for (int k=0;k &primes) { + + if ( nPrime < 1 ) return (-1) ; // return error if no. of primes is less than 1 + + primes[0] = 2; + + int pTest = 3; + for ( int i = 2 ; i <=nPrime ; ) { + + int status = 1; + for ( int divN = 2 ; divN <= (int)sqrt(pTest) ; divN++ ) { + if ( pTest%divN == 0 ) { + status = 0; + break; + } + } + if ( status != 0 ) { + primes[i-1] = pTest; + i++; + } + status = 1; + pTest++; + } + + return (0); + +} + +/** + \brief Returns nelem elements, dim-dimensional, Halton QMC sequence + */ +void Sampling::getHaltonSeq ( const int nelem, const int dim, std::vector &seq ) { + + + this->getHaltonSeq( nelem, dim, this->hStep_, this->hSkip_, this->hJump_, this->hBase_, seq ); + + this->hStep_ += nelem; + + return; + +} + +/** + \brief Returns nelem elements, dim-dimensional, Halton QMC sequence + */ +void Sampling::getHaltonSeq ( const int nelem, const int dim, const int step, + const std::vector &skip, const std::vector &jump, const std::vector &base, + std::vector &seq) { + + assert(nelem*dim<=seq.size()); + + for ( int i=0; ihBase_[i-1] ); + + while ( seq1D != 0 ) { + int digit = seq1D % this->hBase_[i-1]; + seq[j*dim+i] += ( ( double ) digit ) * obase ; + obase = obase / ( ( double ) this->hBase_[i-1] ); + seq1D = seq1D / this->hBase_[i-1]; + } + } + } + + return ; + +} diff --git a/cpp/lib/sampling/sampling.hpp b/cpp/lib/sampling/sampling.hpp new file mode 100644 index 00000000..a9430d08 --- /dev/null +++ b/cpp/lib/sampling/sampling.hpp @@ -0,0 +1,112 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file Sampling.hpp +/// \author B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2016 - +/// \brief Header file for the Sampling class + +#ifndef SAMPLING_HPP_SEEN +#define SAMPLING_HPP_SEEN + +#include +#include + +#include "gen_defs.h" +#include "probability.h" +#include "Array2D.h" +#include "dsfmt_add.h" + + +/// \class Sampling +/// \brief Provides functions for Monte-Carlo sampling, including +/// Latin Hypercube Sampling and Improved Hypercube Sampling; also +/// provides Quasi Monte Carlo methods + +class Sampling { +public: + + /// \brief Constructor: initializes the Sampling class + Sampling(const std::string sp_type, int ndim) { + assert(ndim>0); + if (sp_type==std::string("qmc")) { + hBase_.resize(ndim,0.0); + int ierr = getPrimes(ndim, hBase_); + hSkip_.resize(ndim,0); + hJump_.resize(ndim,1); + hStep_ = 0; + } + } + + /// \brief Destructor: cleans up all memory and destroys object + ~Sampling() { + // do nothing + } + + /// \brief Latin Hypercube Sampling, uniform distribution in all directions + void unifLHS(const int nsample, const int ndim, const int zSeed, double *rvar); + /// \brief Latin Hypercube Sampling, uniform distribution in all directions + void unifLHS(const int nsample, const int ndim, dsfmt_t *rnstate, double *rvar); + /// \brief Latin Hypercube Sampling, uniform distribution in all directions + void unifLHS(const int zSeed, Array2D &rvar); + /// \brief Latin Hypercube Sampling, uniform distribution in all directions + void unifLHS(dsfmt_t *rnstate, Array2D &rvar); + + /// \brief Latin Hypercube Sampling, normal distribution in all directions + void normLHS(const int nsample, const int ndim, const int zSeed, double *rvar); + /// \brief Latin Hypercube Sampling, normal distribution in all directions + void normLHS(const int zSeed, Array2D &rvar); + + /// \brief Improved Hypercube Sampling, uniform distribution in all directions + void unifIHS(const int dfac, dsfmt_t *rnstate, const int ndim, const int ns, double *rndnos); + /// \brief Improved Hypercube Sampling, uniform distribution in all directions + void unifIHS(const int dfac, dsfmt_t *rnstate, Array2D &rndnos); + + /// \brief Quasi Monte Carlo, Halton sequence + void getHaltonSeq ( const int nelem, const int dim, std::vector &seq ); + /// \brief Quasi Monte Carlo, Halton sequence + void getHaltonSeq ( const int nelem, const int dim, const int step, + const std::vector &skip, const std::vector &jump, const std::vector &base, + std::vector &seq); + /// \brief Quasi Monte Carlo, Hammersley sequence + void getHammersleySeq ( const int nelem, const int dim, double *seq ); + + private: + + /// \brief Permutes a given array in place + void getPerm(const int nn, const int seed, int* perm); + /// \brief Retrieves and Improved Hypercube Sampling permutation + void getIHSperm(const int ndim, const int ns, int *x, const int dupl, dsfmt_t *rnstate); + /// \brief Returns first nPrime prime numbers + int getPrimes(const int nPrime, std::vector &primes); + + int hStep_; + std::vector hSkip_; + std::vector hJump_; + std::vector hBase_; + +}; + +#endif /* !SAMPLING_HPP_SEEN */ diff --git a/cpp/lib/tmcmc/CMakeLists.txt b/cpp/lib/tmcmc/CMakeLists.txt new file mode 100644 index 00000000..4e974748 --- /dev/null +++ b/cpp/lib/tmcmc/CMakeLists.txt @@ -0,0 +1,26 @@ + +SET(tmcmc_HEADERS + tmcmc.h + ) + +add_library(uqtktmcmc tmcmc.cpp) + +include_directories (../include) +include_directories (../array ) +include_directories (../tools ) +include_directories (../quad ) + +include_directories (../../../dep/lapack) +include_directories (../../../dep/dsfmt ) +#if (NOT "${HDF5LibPath}" STREQUAL "") + include_directories(${HDF5LibPath}/include) +#endif() + + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtktmcmc DESTINATION lib) + +# Install the header files +INSTALL(FILES ${tmcmc_HEADERS} DESTINATION include/uqtk) diff --git a/cpp/lib/tmcmc/tmcmc.cpp b/cpp/lib/tmcmc/tmcmc.cpp new file mode 100644 index 00000000..acfcd4f4 --- /dev/null +++ b/cpp/lib/tmcmc/tmcmc.cpp @@ -0,0 +1,1084 @@ +#include "tmcmc.h" + +#define BETA_MAX 0.8 + +extern "C" { + void dpotrf_(char *, int *, double *, int*, int *); +} + +void outProcToFile(const RealVector spls, const int ndim, const int nspl, + const int nprocs) ; +void outProcToFile(const RealVector spls, const int ndim, const int nspl, + std::string fname); +void shuffle_spls(RealVector &spls, RealVector &llik); + +bool fileExists(std::string fname); +void readInitSamples(RealVector &spls, std::string fname); +void parseSetup(dsfmt_t &RandomState, int nspl, int iseed); +void PriorGen(dsfmt_t &RandomState, int nspl, CharVector &distr, + RealVector &means, RealVector &vars, int iseed); +double pearsonCorrCoef(RealVector X, RealVector Y); +double rescaleSTD(RealVector w, double wmean); + +double tmcmc(RealVector &rngs, double gm, int nspl, RealVector dtvec, + int iseed, const int nProcs, int ndim = 2, bool spc = false) { + // Wrapper for systematic tests + double cv = 1.0; + double a = 1.0/9.0; + double b = 8.0/9.0; + double mala = false; + double tauScale = 0.0001; + double betaThres = 0.0; + int MFactor = 1; + bool basis = false; + int CATSteps = 1; + return tmcmc(rngs, gm, nspl, dtvec, iseed, nProcs, ndim, spc, cv, a, b, + mala, tauScale, betaThres, MFactor, basis, CATSteps); +} + +double tmcmc(RealVector &rngs, double gm, int nspl, RealVector dtvec, + int iseed, const int nProcs, int ndim, bool spc, double cv, + double a, double b, bool mala, double tauScale, double betaThres, + int MFactor, bool basis, int CATSteps) { + /* TMCMC Algorithm + Input: rngs - ranges for all samples + gm - initial gamma value + nspl - number of Samples + dtvec - change in Beta (optional) + iseed - random seed + nProcs - number of processors + ndim - number of dimensions + spc - SpectralClustering (on/off) + cv - Coefficient of Variance threshold for adapting Beta + a - gamma multiplier (a + bR)gm + b - gamma multiplier (a + bR)gm, See Minson, Simon, Beck 2013 + mala - MALA Proposal (on/off) + tauScale - tau scaling parameter (MALA), l > 0 + betaThres - Turns off MALA when beta is above betaThres + MFactor - Multiplicative factor for chain length to encourage mixing. + Output: evid - asymptotically unbiased model evidence estimator + */ + #ifdef USE_HDF5 + using namespace H5; + #endif + + /* Initial Tau for MALA */ + if (tauScale < 0) { + tauScale = 0; + } + double tau = pow(tauScale, 2) / (2.0 * pow(ndim, 1.0 / 3.0)); + + /* Read ndims from rngs */ + if (rngs.size() != 0) { + ndim = rngs.size() / 2; + } + int nscal = ndim*nspl; + + std::string nstages; + if (dtvec.size() == 0) { + nstages = "Adaptive"; + } else { + nstages = std::to_string(dtvec.size()); + } + //double dt = 1.0 / Ntemp; + //double dts[] = {0.02,0.03,0.04,0.05,0.06,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1}; + //RealVector dtvec(dts, dts + sizeof(dts) / sizeof(double) ); + + // Roberts and Rosenthal 2011 - Initial gamma if one is not provided. + if (gm < 0) gm = 2.38 / sqrt(ndim); + double gm2 = gm * gm; + + std::ofstream gamma_file("gamma.dat"); + + std::cout<<"----------------------------------------------------"<> i; + TMCMCiter.close(); + std::string stageName = "Stage" + std::to_string(i); + Group stage = h5file.openGroup(stageName.c_str()); + + /* Extract previous set of samples */ + if (i > 0) { + int lastSampleIter; + std::ifstream lastSample("lastSample.dat"); + lastSample >> lastSampleIter; + lastSample.close(); + std::string oldStageName = "Stage" + std::to_string(i - 1); + std::string oldIterName = "Iteration_" + std::to_string(lastSampleIter); + Group oldStage = h5file.openGroup(oldStageName.c_str()); + Group oldIter = oldStage.openGroup(oldIterName.c_str()); + DataSet oldSamples = oldIter.openDataSet("Samples"); + double *sampleArray = new double[nspl*ndim]; + oldSamples.read(sampleArray, PredType::NATIVE_DOUBLE); + for (int i = 0; i < nspl; ++i) { + for (int j = 0; j < ndim; ++j) { + spls.push_back(sampleArray[i*ndim + j]); + } + } + delete[] sampleArray; + usedSample = true; + std::cout << "Samples read from old samples in HDF5\n"; + } else if (fileExists("setup.dat")){ + parseSetup(RandomState, nspl, iseed); + readInitSamples(spls, "samples.dat.0"); + std::cout << "Samples generated from setup.dat, then deleted, (HDF5)\n"; + usedSetup = true; + } else { + std::cout << "Setup file needed for HDF5!"; + exit(0); + } + #else + + /* Generate Initial Random Samples */ + /* Check if an initial sample file exists, or a setup file + last resort, generate from a d-dim hypercube */ + if (fileExists("samples.dat.0")) { + readInitSamples(spls, "samples.dat.0"); + std::cout << "Samples read from samples.dat.0\n"; + usedSample = true; + + } else if (fileExists("setup.dat")) { + parseSetup(RandomState, nspl, iseed); + readInitSamples(spls, "samples.dat.0"); + std::cout << "Samples generated from setup.dat\n"; + usedSetup = true; + + } else { + /* Generate from d-dim hypercube */ + for (int j=0; j> check; + if (check == 0 || check < -pow(10, 300)) { + llik[j] = -pow(10, 300); + } else { + llik[j] = check; + } + } + + RealVector gradLog; + if (mala) { + std::ifstream grad_input("gradlog.dat"); + double check4; + while (grad_input >> check4) { + // Just in case of empty spaces in file + if (check4 == 0) { + continue; + } + gradLog.push_back(check4); + } + } + + /* Compute initial log priors, if applicable */ + RealVector lprior(nspl); + if (usedSetup || usedSample) { + std::string lp_stream = "./tmcmc_getLP.sh " + std::to_string(0); + system(lp_stream.c_str()); + std::ifstream lp_input("tmcmc_lp.dat"); + for (int i = 0; i < nspl; ++i ) { + lp_input >> lprior[i]; + } + } + + + #ifdef USE_HDF5 + /* Put Samples into HDF5 */ + std::string iterName = "Iteration_0"; + Group iterGroup = stage.createGroup(iterName.c_str()); + + DataSet sampleDataset = iterGroup.createDataSet("Samples", + PredType::NATIVE_DOUBLE, sampleDataSpace); + DataSet loglikDataset = iterGroup.createDataSet("LogLikelihood", + PredType::NATIVE_DOUBLE, logDataSpace); + DataSet logpriorDataset = iterGroup.createDataSet("LogPrior", + PredType::NATIVE_DOUBLE, logDataSpace); + + double *splsDatasetData = new double[spls.size()]; + double *llikDatasetData = new double[llik.size()]; + + for (size_t i = 0; i < spls.size(); ++i) { + splsDatasetData[i] = spls[i]; + } + for (size_t i = 0; i < llik.size(); ++i) { + llikDatasetData[i] = llik[i]; + } + + sampleDataset.write(splsDatasetData, PredType::NATIVE_DOUBLE); + loglikDataset.write(llikDatasetData, PredType::NATIVE_DOUBLE); + + + if (usedSetup || usedSample) { + double *lpriorDatasetData = new double[lprior.size()]; + for (size_t i = 0; i < lprior.size(); ++i) { + lpriorDatasetData[i] = lprior[i]; + } + + logpriorDataset.write(lpriorDatasetData, PredType::NATIVE_DOUBLE); + delete[] lpriorDatasetData; + } + + Attribute betaAttr = iterGroup.createAttribute("Beta", + PredType::NATIVE_DOUBLE, attrDataSpace); + double betaAttrData[1] = {0.0}; + betaAttr.write(PredType::NATIVE_DOUBLE, betaAttrData); + iterGroup.close(); + #endif + + /* Output first set of samples to file*/ + outProcToFile(spls,ndim,nspl,std::string("samples.dat.0")); + outProcToFile(llik,1, nspl,std::string("loglik.dat.0") ); + if (usedSetup || usedSample) { + outProcToFile(lprior, 1,nspl,std::string("logprior.dat.0")); + } + + RealVector Sm; + double accRatio = 1.0; + double pearsonR = 1.0; + int iter = 0; + double beta = 0.0, dBeta = 0.0, evid = 0.0; + + do { // Start algorithm + iter++; + + /* shuffle samples */ + shuffle_spls(spls,llik); + + /* compute weights */ + RealVector w(nspl,0.0); + double wsum, wmean, w2mean, wstd; + if (dtvec.size()>=iter) + dBeta = std::min(dtvec[iter-1],1.0-beta); + else + dBeta = std::min(BETA_MAX,1.0-beta); + + /* Adapt delta beta as needed */ + do { + for (int j=0; j < nspl; j++) w[j] = exp(dBeta*llik[j]); + wsum = std::accumulate(w.begin(), w.end(), 0.0); + wmean = wsum / w.size(); + w2mean = std::inner_product(w.begin(), w.end(), w.begin(), 0.0)/ w.size(); + wstd = sqrt(w2mean- pow(wmean, 2)); + + if (wstd/wmean > (cv + 1.0) || wstd == 0) dBeta *= 0.9; + if (wstd/wmean > (cv + 0.5) || wstd == 0) dBeta *= 0.95; + if (wstd/wmean > (cv + 0.05) || wstd == 0) dBeta *= 0.99; + if (wstd/wmean > (cv + 0.005) || wstd == 0) dBeta *= 0.999; + if (wstd/wmean > (cv + 0.0005) || wstd == 0) dBeta *= 0.9999; + if (wstd/wmean > (cv + 0.00005) || wstd == 0) dBeta *= 0.99999; + if (wstd/wmean > (cv + 0.000005) || wstd == 0) dBeta *= 0.999999; + if (wstd/wmean > (cv + 0.0000005) || wstd == 0) dBeta *= 0.9999999; + if (wstd/wmean > (cv + 0.00000005) || wstd == 0) dBeta *= 0.99999999; + + + } while (wstd/wmean > (cv + 0.00000005) || wstd == 0); + + std::cout<<"DBeta: " << dBeta<<" Wmean: "<> cvmat[i]; + } else { + for (int j=0; j < nspl; j++) { + for (int i1=0; i1(),gm2)); + } + + /* Cholesky factorization of the proposal covariance, in-place */ + int chol_info=0; + char lu='L'; + dpotrf_(&lu, &ndim, &cvmat[0], &ndim, &chol_info); + + /* generate random samples into [0,1] */ + RealVector spl01(nspl); + for (int j=0; j0) { + splPos.push_back(j); + splCount.push_back(icount); + } + } + + /* Initialize samples that were retained, cardinality, and + likelihood values */ + RealVector splSt, llikSt, lpriorSt, gradSt; + IntVector splCard; + int nsplSt = splPos.size(); + + /* Resampling Step */ + for (int ispl=0; ispl rngs[2*i+1])) { + isInside[ispl] = false; + break; + } + } /* done generating candidate */ + } + + /* Compute new likelihoods */ + RealVector splsComp; + int compCount=0; + for (int ispl=0; ispl> check2; + if (check2 == 0.0 || check2 < -pow(10, 300)) { + llikComp[j] = -pow(10, 300); + } else { + llikComp[j] = check2; + } + } + + RealVector gradComp; + if (mala) { + std::ifstream gradInput("gradlog.dat"); + double check3; + while (gradInput >> check3) { + if (check3 == 0) { + continue; + } + gradComp.push_back(check3); + } + } + + RealVector lpriorComp(compCount); + if (usedSetup || usedSample) { + std::string lp_stream = "./tmcmc_getLP.sh " + std::to_string(iter - 1); + system(lp_stream.c_str()); + std::ifstream lp_input("tmcmc_lp.dat"); + double check5; + for (int i = 0; i < compCount; ++i) { + lp_input >> check5; + if (check5 == 0.0 || check5 < -pow(10, 300)) { + lpriorComp[i] = -pow(10, 300); + } else { + lpriorComp[i] = check5; + } + } + } + + /* decide who jumps */ + int icomp=0; + int acceptCount = 0; + RealVector splNew(nsplSt*ndim), llikNew(nsplSt), lpriorNew(nsplSt); + RealVector gradNew(nsplSt*ndim); + + for (int ispl=0; ispl0) { + for (int i=0; i0) { + isplEn += 1; + nAdd -= 1; + } + + char fname[20]; + sprintf(fname,"%s%d%s","mcmcstates_",ifile+1,".dat"); + FILE *myfile = fopen(fname,"w") ; + for (int j = isplSt; j < isplEn; j++) { + for (int i = 0; i < ndim; i++) + fprintf(myfile,"%24.18e ",spls[j*ndim+i]); + fprintf(myfile,"\n"); + } + fclose(myfile); + } + assert(isplEn==nspl); + + return ; + +} + +//void outProcToFile(const RealVector spls, const int ndim, +// const int nspl, const int nprocs) { +// +// assert(spls.size()==ndim*nspl); +// +// /* no. of mcmc states per file */ +// int nsplP = (int) nspl/nprocs; +// if ( nsplP*nprocs < nspl) nsplP += 1; +// +// /* save samples to files */ +// for (int ifile=0; ifile < nprocs; ifile++) { +// +// int isplSt = ifile * nsplP; +// int isplEn = isplSt+nsplP ; +// if ( isplEn > nspl ) isplEn = nspl; +// +// char fname[20]; +// sprintf(fname,"%s%d%s","mcmcStates_",ifile+1,".dat"); +// FILE *myfile = fopen(fname,"w") ; +// for (int j = isplSt; j < isplEn; j++) { +// for (int i = 0; i < ndim; i++) +// fprintf(myfile,"%24.18e ",spls[j*ndim+i]); +// fprintf(myfile,"\n"); +// } +// fclose(myfile); +// } +// +// return ; +// +//} + +void outProcToFile(const RealVector spls, const int ndim, const int +nspl, std::string fname) { + // Output sample vector into fname file + assert(spls.size()==ndim*nspl); + + FILE *myfile = fopen(fname.c_str(),"w") ; + for (int j = 0; j < nspl; j++) { + for (int i = 0; i < ndim; i++) + fprintf(myfile,"%24.18e ",spls[j*ndim+i]); + fprintf(myfile,"\n"); + } + fclose(myfile); + + return ; + +} + +void shuffle_spls(RealVector &spls, RealVector &llik) { + // Shuffle the samples randomly + int nspl = llik.size(); + int ndim = spls.size()/nspl; + + IntVector idx(nspl); + for (int j=0; j(), xmean)); + + std::transform(Y.begin(), Y.end(), Ytmp.begin(), + std::bind2nd(std::minus(), ymean)); + double sx = sqrt((1.0 / (X.size() - 1)) * std::inner_product(Xtmp.begin(), + Xtmp.end(), Xtmp.begin(), 0.0)); + double sy = sqrt((1.0 / (Y.size() - 1)) * std::inner_product(Ytmp.begin(), + Ytmp.end(), Ytmp.begin(), 0.0)); + + double num = (std::inner_product(X.begin(), X.end(), Y.begin(), 0.0) + - X.size() * xmean * ymean); + double denom = (X.size() - 1) * sx * sy; + + return (num / denom); +} + +double rescaleSTD(RealVector w, double wmean) { + RealVector wTmp(w.size()); + + std::transform(w.begin(), w.end(), wTmp.begin(), + std::bind2nd(std::minus(), wmean)); + + double lTerm = std::inner_product(wTmp.begin(), wTmp.end(), wTmp.begin(), 0.0); + double rTerm = pow(std::accumulate(wTmp.begin(), wTmp.end(), 0.0), 2.0) / w.size(); + + double var = (lTerm - rTerm) / (w.size() - 1); + + return (sqrt(var)); +} diff --git a/cpp/lib/tmcmc/tmcmc.h b/cpp/lib/tmcmc/tmcmc.h new file mode 100644 index 00000000..2658bd32 --- /dev/null +++ b/cpp/lib/tmcmc/tmcmc.h @@ -0,0 +1,34 @@ +#ifndef TMCMCHEADERSEEN +#define TMCMCHEADERSEEN +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dsfmt_add.h" + +#ifdef USE_HDF5 +#include "H5Cpp.h" +#endif + + +typedef std::vector RealVector; +typedef std::vector IntVector; +typedef std::vector BoolVector; +typedef std::vector CharVector; + +double tmcmc(RealVector &rngs, double gm, int nspl, RealVector dtvec, int iseed, + const int nProcs); + +double tmcmc(RealVector &rngs, double gm, int nspl, RealVector dtvec, int iseed, + const int nProcs, int ndim, bool spc, double cv, double a, + double b, bool mala, double tauScale, double betaThres, int MFactor, bool basis, int CATSteps) ; + +#endif diff --git a/cpp/lib/tools/CMakeLists.txt b/cpp/lib/tools/CMakeLists.txt new file mode 100644 index 00000000..ded34cb7 --- /dev/null +++ b/cpp/lib/tools/CMakeLists.txt @@ -0,0 +1,38 @@ +project(UQTk) + +enable_language(Fortran) + +SET(tools_HEADERS + combin.h + gq.h + minmax.h + multiindex.h + pcmaps.h + probability.h + rosenblatt.h + func.h + tools.h + ) + +FILE(GLOB slsrc "*.cpp") +FILE(GLOB fsrc toolsf.f) + +add_library(uqtktools ${fsrc} ${slsrc}) + +include_directories (../include) +include_directories (../array ) +include_directories (../pce) +include_directories (../quad) + +include_directories (../../../dep/dsfmt ) +include_directories (../../../dep/lapack) +include_directories (../../../dep/figtree) +include_directories (../../../dep/cvode-2.7.0/include) +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +# Install the library +INSTALL(TARGETS uqtktools DESTINATION lib) + +# Install the header files +INSTALL(FILES ${tools_HEADERS} DESTINATION include/uqtk) + diff --git a/cpp/lib/tools/combin.cpp b/cpp/lib/tools/combin.cpp new file mode 100644 index 00000000..cba6fcad --- /dev/null +++ b/cpp/lib/tools/combin.cpp @@ -0,0 +1,666 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file combin.cpp +/// \brief Tools to evaluate combinatorial quantities. + +#include "Array1D.h" +#include "Array2D.h" +#include "gen_defs.h" +#include "probability.h" +#include "combin.h" +#include +#include +#include "error_handlers.h" + +// Calculates binomial formula n-choose-k +int choose(int n,int k) { + + int vmin=MIN(k,n-k); + + if (vmin< 0) return (0); + if (vmin==0) return (1); + + int vmax = MAX(k,n-k); + int vret = vmax+1; + for (int i=2;i& fullInd) +{ + int n_k=choose(n,k); + fullInd.Resize(n_k,k,0); + + for(int ik=0;ik=0){ + if(fullInd(iii,j)& perm,int seed) +{ + + int nn=perm.XSize(); + get_perm(nn,perm.GetArrayPointer(),seed); + + return; +} + +// Permutes a given array in place +void get_perm(int nn, int* perm,int seed) +{ + + dsfmt_gv_init_gen_rand(seed ); + + int j,t; + for(int is=0;is& data_in, Array1D& w,int ncl, Array1D& numData,int *pClusterIndex) +{ + int nsample=data_in.XSize(); + int ndim=data_in.YSize(); + double *pSources; + pSources=new double[ndim*nsample]; + + for (int i=0;i& data_in, Array1D& w,int ncl, Array1D& bestnumData,int *bestClusterIndex,int ntry) +{ + + int nsample=data_in.XSize(); + int ndim=data_in.YSize(); + + double bestExplVar=0; + Array1D mean(ndim,0.e0); + double totVariance=getMean_Variance(data_in,w,mean); + + + for (int itry=0;itry numData(ncl,0); + int *pClusterIndex; + pClusterIndex=new int[nsample]; + + clust(data_in,w,ncl,numData,pClusterIndex); + + double unexplVariance=0.0, explVariance=0.0; + + for (int icl=0;icl data_icl(numData(icl),ndim,0.e0); + int jc=0; + + for(int i=0;i mean_cl(ndim,0.e0); + unexplVariance += (numData(icl)*getMean_Variance(data_icl,w,mean_cl)); + } + + unexplVariance /= nsample; + explVariance=1.-unexplVariance/totVariance; + + if (explVariance >= bestExplVar) { + for(int i=0;i& data_in,Array1D& w,int ntry)// Below one can uncomment either a) or b) or c) for three differnet elbow-like criteria +{ + int maxNumCl=10; + //double explThresh=0.5; + int optNumCl=maxNumCl; + double bestExplVar=0.; + //double oldJump=0.; + double newJump=0.; + double prev_bestExplVar=0.; + //double minSlopeDiff=0.; + double maxJump=0.; + + //int ndim=data_in.YSize();//=w.XSize(); + int nsam=data_in.XSize(); + + for(int tryNumCl=1; tryNumCl<=maxNumCl;tryNumCl++){ + Array1D numData(tryNumCl,0); + int *pClusterIndex; + pClusterIndex=new int[nsam]; + bestExplVar=clust_best(data_in,w,tryNumCl,numData,pClusterIndex,ntry); + + delete []pClusterIndex; + printf("bestExplVarFrac(%d)=%lg\n",tryNumCl,bestExplVar); + + + //a) + // if (bestExplVar > explThresh) {optNumCl=tryNumCl; break;} + + //b) + newJump=bestExplVar-prev_bestExplVar; + if ( newJump > maxJump) {maxJump=newJump; optNumCl=tryNumCl;} + prev_bestExplVar=bestExplVar; + + //c) + //newJump=bestExplVar-prev_bestExplVar; + // if ( newJump-oldJump < minSlopeDiff) {minSlopeDiff=newJump-oldJump; optNumCl=tryNumCl-1;} + // oldJump=newJump; + // prev_bestExplVar=bestExplVar; + + } + + return optNumCl; +} + diff --git a/cpp/lib/tools/combin.h b/cpp/lib/tools/combin.h new file mode 100644 index 00000000..4c9f344c --- /dev/null +++ b/cpp/lib/tools/combin.h @@ -0,0 +1,95 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file combin.h +/// \brief Header for combinatorial tools +/// \note Some functions are likely not optimal and could have been computed more efficiently. + +#ifndef COMBIN_H +#define COMBIN_H + +#include "Array2D.h" + + + +/// \brief Calculates binomial coefficient C(n,k): n-choose-k +int choose(int n,int k); + +/// \brief Calculates the factorial of a number +int factorial(int number); + +/// \brief Calculates the logfactorial of a number +double logfactorial(int number); + +/// \brief Computes all possible k-combinations of the first n non-negative integers +/// and returns them in fullInd +void chooseComb(int n, int k,Array2D& fullInd); + + +/// \brief Computes a random permutation of the first n non-negative integers +/// and returns is in perm +void get_perm(int n, int* perm,int seed); + +/// \brief Computes a random permutation of the first n non-negative integers +/// and returns is in perm +/// \note n is the size of the array argument perm +void get_perm(Array1D& perm, int seed); + + +/// \brief Compute the incomplete Gamma function with parameter a at point x +/// \note This is a slightly modified version of a code distributed by John Burkardt +/// \note see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa147/asa147.html +/// \note see comments under the function definition +double gammai(const double a, const double x); + +/// \brief Compute the Beta function at the point pair (z,w) +double beta(const double z, const double w); + +/// \brief Compute the incomplete Beta function with parameters a and b at point x +/// \note This is a slightly modified version of a code distributed by John Burkardt +/// \note see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa063/asa063.html +/// \note see comments under the function file +double betai(const double p, const double q, const double x); + +/// \brief Computes the digamma, or psi, function, i.e. derivative of the logarithm of gamma function +/// \note This is a slightly modified version of a code distributed by John Burkardt +/// \note see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa103/asa103.cpp +double digama ( double x ); + +/// \brief K-center clustering of data +/// \param[in] data_in : Nxd matrix of data +/// \param[in] w : Array of size d; dimension-wise scaling weights +/// \param[in] ncl : Number of clusters +/// \param[out] numData : Array of size ncl; stores the number of elements for each cluster +/// \param[out] pClusterIndex : Array of size N indicating the cluster index for each data point +void clust(Array2D& data_in, Array1D& w,int ncl, Array1D& numData,int *pClusterIndex); + +/// \brief Multiple trials of K-center clustering and picking the best one according to explained variance criterion +double clust_best(Array2D& data_in, Array1D& w,int ncl, Array1D& bestnumData,int *bestClusterIndex,int ntry); +/// \brief Find the best number of clusters in a dataset according to one of three (hardcoded) criteria +int findNumCl(Array2D& data_in,Array1D& w,int ntry); +//--------------------------------------------------------------------------------------- +#endif // COMBIN_H diff --git a/cpp/lib/tools/func.cpp b/cpp/lib/tools/func.cpp new file mode 100644 index 00000000..053ca783 --- /dev/null +++ b/cpp/lib/tools/func.cpp @@ -0,0 +1,525 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file func.cpp +/// \brief Implements several functions of form \f$y=f(\lambda;x)\f$ + +#include +#include +#include + +#include "func.h" + +#include "gen_defs.h" +#include "PCSet.h" +#include "error_handlers.h" +#include "arrayio.h" +#include "arraytools.h" + + +// Proportionality function f(p,x) = p * x +Array2D Func_Prop(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==1); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_PropQuad(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==2); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_Exp(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==2); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_ExpQuad(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==3); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_Const(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_Linear(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==2); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_BB(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + Array2D y; + + write_datafile(pp,"p.dat"); //np,pdim + write_datafile(x,"x.dat"); //nx,xdim + system("./bb.x"); + read_datafileVS(y,"y.dat"); //np,nx + + CHECKEQ(y.XSize(),np); + CHECKEQ(y.YSize(),nx); + + return y; +} + +// Heat transfer example function f(p,x) = T0 + (x * dw) / (Aw * p) +Array2D Func_HT1(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==1); + assert(xdim==1); + + Array2D y(np,nx); + + double To=273.; + double Aw=0.04; + double dw=0.1; + for(int ip=0;ip Func_HT2(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==2); + assert(xdim==1); + + Array2D y(np,nx); + + double Aw=0.04; + //double kw=1.0; + double Q=20.0; + for(int ip=0;ip Func_FracPower(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==4); + assert(xdim==1); + + + Array2D y(np,nx); + + for(int ip=0;ip Func_ExpSketch(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==2); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_Inputs(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + assert(pdim==nx); + assert(xdim==1); + + Array2D y(np,nx); + + for(int ip=0;ip Func_PCl(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + Array2D mindexx; + + string pctype="LU"; + read_datafileVS(mindexx,"mindexx.dat"); + + // Size checks + CHECKEQ(mindexx.XSize(),pdim); + CHECKEQ(mindexx.YSize(),xdim); + + + PCSet surrmodel("NISPnoq",mindexx,pctype); + + Array2D pcinput=x; + + Array2D y(np,nx); + + for(int ip=0;ip cf_this; + getRow(pp,ip,cf_this); + Array1D moutput; + surrmodel.EvalPCAtCustPoints(moutput,pcinput,cf_this); + + for(int ix=0;ix Func_PCx(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + Array2D mindexpx; + string pctype="LU"; + read_datafileVS(mindexpx,"mindexpx.dat"); + + CHECKEQ(mindexpx.YSize(),pdim+xdim); + + Array1D pccfpx(mindexpx.XSize()); + read_datafile_1d(pccfpx,"pccfpx.dat"); + + PCSet surrmodel("NISPnoq",mindexpx,pctype); + + Array2D pcinput(nx*np,pdim+xdim); + for(int ip=0;ip model_samples_planar; + surrmodel.EvalPCAtCustPoints(model_samples_planar,pcinput,pccfpx); + + Array2D y(np,nx); + + for (int ip=0;ip Func_PC(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int* pred_mode=(int*) funcinfo; + + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + Array2D mindexp; + + string pctype="LU"; + read_datafileVS(mindexp,"mindexp.dat"); + CHECKEQ(mindexp.YSize(),pdim); + + Array2D pccf_all(mindexp.XSize(),nx); + if ((*pred_mode)==0) + read_datafile(pccf_all,"pccf_all.dat"); + else + read_datafile(pccf_all,"pccf_all_pred.dat"); + + PCSet surrmodel("NISPnoq",mindexp,pctype); + + Array2D pcinput=pp; + + Array2D y(np,nx); + + for(int ix=0;ix pccf_this; + getCol(pccf_all,ix,pccf_this); + Array1D moutput; + surrmodel.EvalPCAtCustPoints(moutput,pcinput,pccf_this); + + for(int ip=0;ip Func_PCs(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo) +{ + int np=p.XSize(); + int nx=x.XSize(); + int xdim=x.YSize(); + + Array2D pp=augment(p,fixindnom); + + int pdim=pp.YSize(); + + string pctype="LU"; + + Array1D > mindices(nx); + Array1D > pccfs(nx); + + for (int ix=0;ix pcinput=pp; + + Array2D y(np,nx); + + for(int ix=0;ix moutput; + surrmodel.EvalPCAtCustPoints(moutput,pcinput,pccfs(ix)); + + for(int ip=0;ip augment(Array2D& p, Array2D& fixindnom){ + + int fdim=fixindnom.XSize(); + if (fdim>0){ + quicksort3(fixindnom,0, fdim-1,0); + } + + + Array2D pp=p; + + + for (int i=0;i nomCol(pp.XSize(),fixindnom(i,1)); + pp.insertCol(nomCol,(int)fixindnom(i,0)); + } + + + return pp; +} + diff --git a/cpp/lib/tools/func.h b/cpp/lib/tools/func.h new file mode 100644 index 00000000..0c19d29b --- /dev/null +++ b/cpp/lib/tools/func.h @@ -0,0 +1,117 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file func.h +/// \brief Header for implementation of functions of form \f$y=f(\lambda;x)\f$ +/// \note Functions of form \f$y=f(\lambda;x)\f$ for +/// \f$x\in\mathbf{R}^s\f$ and \f$\lambda\in\mathbf{R}^d\f$ at +/// \f$r\f$ values of model parameters \f$\lambda\f$ and \f$n\f$ values of design parameters \f$x\f$ +/// \param p Model parameters \f$\lambda\f$ as a matrix \f$r\times d\f$ +/// \param x Design parameters \f$x\f$ as a matrix \f$n\times s\f$ +/// \param *funcinfo Potentially function-specific information +/// \return y Output as a matrix \f$r\times n\f$ + +#ifndef FUNC_H_SEEN +#define FUNC_H_SEEN + +#include "Array1D.h" +#include "Array2D.h" + +#include +#include +#include +#include + +using namespace std; // needed for python string conversion + + + +/// \brief \f$y=f(\lambda;x)=\lambda x\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^1\f$ +Array2D Func_Prop(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=\lambda_1 x+\lambda_2x^2\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^2\f$ +Array2D Func_PropQuad(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x}\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^2\f$ +Array2D Func_Exp(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x+\lambda_3x^2}\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^3\f$ +Array2D Func_ExpQuad(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=\lambda\f$ for \f$x\in\mathbf{R}^s\f$ and \f$\lambda\in\mathbf{R}^1\f$ +Array2D Func_Const(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=\lambda_1+\lambda_2x\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^2\f$ +Array2D Func_Linear(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)\f$ a black-box function with a script bb.x which takes p.dat and x.dat and returns output in y.dat +Array2D Func_BB(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief Heat_transfer1: a custom model designed for a tutorial case of a heat conduction problem +/// \brief \f$y=f(\lambda;x)=\frac{x d_w}{A_w \lambda}+T_0\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^1\f$ +/// \note hardwired parameters: \f$d_w=0.1, A_w=0.04, T_0=273\f$ +Array2D Func_HT1(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief Heat_transfer2: a custom model designed for a tutorial case of a heat conduction problem +/// \brief \f$y=f(\lambda;x)=\frac{x Q}{A_w \lambda_1}+\lambda_2\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^2\f$ +/// \note hardwired parameters: \f$A_w=0.04, Q=20.0\f$ +Array2D Func_HT2(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=\lambda_1+\lambda_2 x+\lambda_3 x^2+ \lambda_4 (x+1)^{3.5}\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^4\f$ +Array2D Func_FracPower(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x)=\lambda_2 e^{\lambda_1 x} - 2\f$ for \f$x\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^2\f$ +Array2D Func_ExpSketch(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief \f$y=f(\lambda;x_i)=\lambda_i\f$ for \f$i=1,...,d\f$, \f$x_i\in\mathbf{R}^1\f$ and \f$\lambda\in\mathbf{R}^d\f$ +Array2D Func_Inputs(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief Legendre PC expansion with \f$\lambda\f$'s as coefficients +/// \brief \f$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} \lambda_\alpha \Psi_\alpha(x)\f$ for \f$x\in\mathbf{R}^s\f$ and \f$\lambda\in\mathbf{R}^{|{\cal S}|}\f$ +/// \note hardwired parameter: multiindex set \f${\cal S}\f$ is given in a file mindexx.dat +Array2D Func_PCl(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief Legendre PC expansion with respect to \f$z=(\lambda,x)\f$ +/// \brief \f$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} c_\alpha \Psi_\alpha(\lambda,x)\f$ for \f$x\in\mathbf{R}^s\f$ and \f$\lambda\in\mathbf{R}^d\f$ +/// \note hardwired parameters: multiindex set \f${\cal S}\f$ is given in a file mindexpx.dat, coefficients \f$c_\alpha\f$ given in a file pccfpx.dat +Array2D Func_PCx(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief Legendre PC expansion for each value of \f$x\f$ +/// \brief \f$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}} c_{\alpha,i} \Psi_\alpha(\lambda)\f$ for \f$x\in\mathbf{R}^s\f$ and \f$\lambda\in\mathbf{R}^d\f$ +/// \note hardwired parameters: common multiindex set for all PCs \f${\cal S}\f$ is given in a file mindexp.dat, coefficients \f$c_{\alpha,i}\f$ are given in a file pccf_all.dat +Array2D Func_PC(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + +/// \brief Legendre PC expansion for each value of \f$x\f$ +/// \brief \f$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}_i} c_{\alpha,i} \Psi_\alpha(\lambda)\f$ for \f$x\in\mathbf{R}^s\f$ and \f$\lambda\in\mathbf{R}^d\f$ +/// \note hardwired parameters: multiindex sets for all PCs \f${\cal S}\f$ are given in files mindexp.i.dat, coefficients \f$c_{\alpha,i}\f$ are given in files pccfp.i.dat +Array2D Func_PCs(Array2D& p, Array2D& x, Array2D& fixindnom, void* funcinfo); + + +/// \brief Augments a parameter matrix with 'fixed' columns given indices and nominal values of those +Array2D augment(Array2D& p, Array2D& fixindnom); + + +#endif /* FUNC_H_SEEN */ diff --git a/cpp/lib/tools/gq.cpp b/cpp/lib/tools/gq.cpp new file mode 100644 index 00000000..cc230b05 --- /dev/null +++ b/cpp/lib/tools/gq.cpp @@ -0,0 +1,400 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file gq.cpp +/// \brief Utilities to generate quadrature rules. + +#include "stdio.h" +#include "stdlib.h" +#include +#include + +#include "Array1D.h" +#include "Array2D.h" +#include "deplapack.h" +#include "gq.h" +#include "combin.h" +using namespace std; + +//#define HERMITE_PROB +//#define HERMITE_PHYS + +#define DPI 3.14159265358979323846 + +double lpol_gq (int n, double x) ; +double hpol_gq (int n, double x) ; +double hpol_phys_gq(int n, double x) ; +double jpol_gq (int n, double a, double b, double x) ; +double jpolp_gq(int n, double a, double b, double x) ; +double lgpol_gq(int n, double a, double x) ; +double fact_gq (int n) ; + +/* + Gauss Quadrature for: + kind = 1 -> Legendre + 2 -> Chebyshev, 1st kind + 3 -> Chebyshev, 2nd kind + 4 -> Hermite + 5 -> Jacobi + 6 -> Laguerre + These rules provide the mathematical engine for the quad class. + */ +void gq ( const int kind, const double a, const double b, Array1D &x, Array1D &w ) { + + int n = (int) x.XSize() ; + gq(kind,n,a,b,x.GetArrayPointer(),w.GetArrayPointer()) ; + return ; + +} + + +void gq ( const int kind, const int n, const double a, const double b, double *x, double *w ) { + + if ( ( kind < 1 ) || ( kind > 6 ) ) { + cout<<"ERROR in gq() : kind should be between 1 and 6 : "< 1 -> compute quad points via Golub-Welch methodology */ + double *sdag = new double[n-1]; + if ( kind == 1 ) { /* Legendre */ + for ( int i=0; i& a, Array1D& b, const double amu0, + Array1D& x, Array1D& w) +{ + int i; + int n = (int) a.XSize(); + int ldz = n; + int info ; + + /* take sqrt of the off-diagonal */ + for (i=1;i& x, Array1D& w, Array1D& q) { + + int n = x.XSize() ; + + for (int i=0; i=k+1; i--) + w(i) = w(i)-x(k)*w(i-1); + + for ( int k=n-2; k>=0; k-- ) { + for (int i=k+1; i. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef GQ_H +#define GQ_H + +/** \file gq.h + * \brief Header for quadrature generation utilities + */ + + +/** + \brief Computes abscissas and weights for several quadrature rules. + + \param kind : defines quadrature type (1) Gauss-Legendre, (2) Gauss-Chebyshev 1st kind + (3) Gauss-Chebyshev 2nd kind, (4) Gauss-Hermite, (5) Gauss-Jacobi + (6) Gauss-Laguerre + \param a : optional parameter needed by Gauss-Jacobi and Gauss-Laguerre rules + \param b : optional parameter needed by Gauss-Jacobi rule + \param x : on return it holds quadrature abscissas. Its initial size determines the quadrature order + \param w : on return it holds quadrature weights. + +*/ +void gq ( const int kind, const double a, const double b, Array1D &x, Array1D &w ) ; + +/** + \brief Computes abscissas and weights for several quadrature rules. + + \param kind : defines quadrature type (1) Gauss-Legendre, (2) Gauss-Chebyshev 1st kind + (3) Gauss-Chebyshev 2nd kind, (4) Gauss-Hermite, (5) Gauss-Jacobi + (6) Gauss-Laguerre + \param n : quadrature order + \param a : optional parameter needed by Gauss-Jacobi and Gauss-Laguerre rules + \param b : optional parameter needed by Gauss-Jacobi rule + \param x : on return it holds quadrature abscissas. + \param w : on return it holds quadrature weights. + +*/ +void gq ( const int kind, const int n, const double a, const double b, double *x, double *w ) ; + +/** + \brief Computes abscissas and weights for a generic orthogonal polynomial recursion using the + Golub-Welsch algorithm + + \param a : array of parameters for the orthogonal polynomial recursion. + Its initial size determines the quadrature order + \param b : array of parameters for the orthogonal polynomial recursion + \param amu0 : parameter for custom scaling of quadrature weights + \param x : on return it holds quadrature abscissas + \param w : on return it holds quadrature weights. + +*/ +void gq_gen(Array1D &a, Array1D &b, const double amu0, + Array1D &x, Array1D &w) ; + + +/** + \brief Computes abscissas and weights for Newton-Cotes rules through the solution of a + Vandermonde matrix. This function was tested as an internal function only, called + by the quadrature class + + \param x : holds quadrature abscissas + \param w : on return it holds quadrature weights. + \param q : array of parameters needed to setup the Vandermonde matrix + +*/ +void vandermonde_gq(Array1D &x, Array1D &w, Array1D &q) ; + +/** + \brief Computes abscissas and weights for Chebyshev quadrature rules. + + \param kind : defines quadrature type (1) Gauss-Chebyshev 1st kind + (2) Gauss-Chebyshev 2nd kind + \param n : quadrature order + \param x : on return it holds quadrature abscissas. + \param w : on return it holds quadrature weights. + +*/ +void gchb(const int kind, const int n, double *x, double *w ) ; + +#endif diff --git a/cpp/lib/tools/minmax.cpp b/cpp/lib/tools/minmax.cpp new file mode 100644 index 00000000..997cc1ad --- /dev/null +++ b/cpp/lib/tools/minmax.cpp @@ -0,0 +1,273 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/** \file minmax.cpp + * \brief Tools to find min/max values of arrays. + */ + +#include "Array1D.h" +#include "Array2D.h" +#include +#include "minmax.h" + +// Get the domain bounds given a multidimensional data +void getDomain(Array2D& data_in,Array1D& a, Array1D& b) +{ + // Get the sizes of data + int nsample=data_in.XSize(); + int ndim=data_in.YSize(); + + // Set the sizes of domain bounds + a.Resize(ndim); + b.Resize(ndim); + + // Work array + Array1D data_1d(nsample,0.e0); + + // For each dimension, get the associated data and get the bounds + for (int idim=0;idim& vector) +{ + + double maxVal_ = vector(0); + for(int i=1;i< (int) vector.XSize();i++) + if (vector(i) > maxVal_) maxVal_ = vector(i); + + return maxVal_; + +} + + +int maxVal(const Array1D& vector) +{ + + int maxVal_ = vector(0); + for(int i=1;i< (int) vector.XSize();i++) + if (vector(i) > maxVal_) maxVal_ = vector(i); + + return maxVal_; + +} + +double maxVal(const Array2D& vector) +{ + + double maxVal_ = vector(0,0); + for(int j=0;j< (int) vector.YSize();j++) + for(int i=0;i< (int) vector.XSize();i++) + if (vector(i,j) > maxVal_) maxVal_ = vector(i,j); + + return maxVal_; + +} + +int maxVal(const Array2D& vector) +{ + + int maxVal_ = vector(0,0); + for(int j=0;j< (int) vector.YSize();j++) + for(int i=0;i< (int) vector.XSize();i++) + if (vector(i,j) > maxVal_) maxVal_ = vector(i,j); + + return maxVal_; + +} + +double minVal(const Array1D& vector) +{ + double minVal_ = vector(0); + for(int i=1;i<(int) vector.XSize();i++){ + if (vector(i) < minVal_){ + minVal_ = vector(i); + } + } + return minVal_; +} + +int minVal(const Array1D& vector) +{ + int minVal_ = vector(0); + for(int i=1;i<(int) vector.XSize();i++){ + if (vector(i) < minVal_){ + minVal_ = vector(i); + } + } + return minVal_; +} + +double minVal(const Array2D& vector) +{ + + double minVal_ = vector(0,0); + for(int j=0;j< (int) vector.YSize();j++) + for(int i=0;i< (int) vector.XSize();i++) + if (vector(i,j) < minVal_) minVal_ = vector(i,j); + + return minVal_; + +} + +int minVal(const Array2D& vector) +{ + + int minVal_ = vector(0,0); + for(int j=0;j< (int) vector.YSize();j++) + for(int i=0;i< (int) vector.XSize();i++) + if (vector(i,j) < minVal_) minVal_ = vector(i,j); + + return minVal_; + +} + +int maxIndex(Array1D& vector) +{ + int maxInd_ = 0; + for(int i=1;i< (int) vector.XSize();i++){ + if (vector(i) > vector(maxInd_)){ + maxInd_ = i; + } + } + return maxInd_; +} + +int minIndex(Array1D& vector) +{ + int minInd_ = 0; + for(int i=1;i< (int) vector.XSize();i++){ + if (vector(i) < vector(minInd_)){ + minInd_ = i; + } + } + return minInd_; +} + +int maxIndex(Array1D& vector) +{ + int maxInd_ = 0; + for(int i=1;i< (int) vector.XSize();i++){ + if (vector(i) > vector(maxInd_)){ + maxInd_ = i; + } + } + return maxInd_; +} + + int minIndex(Array1D& vector) + { + int minInd_ = 0; + for(int i=1;i< (int) vector.XSize();i++){ + if (vector(i) < vector(minInd_)){ + minInd_ = i; + } + } + return minInd_; + } + + +// int maxIndexR_2D(const Array2D a2d, const int irow) +// { +// if ( ( irow < 0 ) ||( irow >= (int) a2d.XSize() ) ) { +// printf("Error in maxIndexR_2D() : illegal row index %d\n",irow) ; +// exit(1) ; +// } + +// int maxInd_ = 0; +// for( int j = 1; j < (int) a2d.YSize(); j++){ +// if (a2d(irow,j) > a2d(irow,maxInd_)){ +// maxInd_ = j; +// } +// } + +// return ( maxInd_ ) ; +// } + + +// int minIndexR_2D(const Array2D a2d, const int irow) +// { +// if ( ( irow < 0 ) ||( irow >= (int) a2d.XSize() ) ) { +// printf("Error in minIndexR_2D() : illegal row index %d\n",irow) ; +// exit(1) ; +// } + +// int minInd_ = 0; +// for( int j = 1; j < (int) a2d.YSize(); j++){ +// if (a2d(irow,j) < a2d(irow,minInd_)){ +// minInd_ = j; +// } +// } + +// return ( minInd_ ) ; +// } + + + +int maxIndexC_2D(const Array2D& a2d, const int icol) +{ + if ( ( icol < 0 ) ||( icol >= (int) a2d.YSize() ) ) { + printf("Error in maxIndexC_2D() : illegal column index %d\n",icol) ; + exit(1) ; + } + + int maxInd_ = 0; + for( int i = 1; i < (int) a2d.XSize(); i++){ + if (a2d(i,icol) > a2d(maxInd_,icol)){ + maxInd_ = i; + } + } + + return ( maxInd_ ) ; +} + + + +int minIndexC_2D(const Array2D& a2d, const int icol) +{ + if ( ( icol < 0 ) ||( icol >= (int) a2d.YSize() ) ) { + printf("Error in minIndexC_2D() : illegal column index %d\n",icol) ; + exit(1) ; + } + + int minInd_ = 0; + for( int i = 1; i < (int) a2d.XSize(); i++){ + if (a2d(i,icol) < a2d(minInd_,icol)){ + minInd_ = i; + } + } + + return ( minInd_ ) ; +} diff --git a/cpp/lib/tools/minmax.h b/cpp/lib/tools/minmax.h new file mode 100644 index 00000000..39d4a19d --- /dev/null +++ b/cpp/lib/tools/minmax.h @@ -0,0 +1,81 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef MINMAX_H +#define MINMAX_H + +/** \file minmax.h + * \brief Header for min/max tools + */ + +/// \brief Define M_PI for compatibility with cygwin on Windows +/// \todo See if we could move this to the CMake installation scripts instead +#ifndef M_PI +#define M_PI atan(1.0) * 4.0 +#endif + + +/// \brief Get domain of the data +void getDomain(Array2D& data_in,Array1D& a, Array1D& b); + +/// \brief Returns the maximum value of a 1d double array +double maxVal(Array1D& vector) ; +/// \brief Returns the maximum value of a 1d int array +int maxVal(const Array1D &vector) ; +/// \brief Returns the maximum value of a 2d double array +double maxVal(const Array2D &vector) ; +/// \brief Returns the maximum value of a 2d int array +int maxVal(const Array2D &vector) ; + +/// \brief Returns the minimum value of a 1d double array +double minVal(const Array1D &vector) ; +/// \brief Returns the minimum value of a 1d int array +int minVal(const Array1D &vector) ; +/// \brief Returns the minimum value of a 2d double array +double minVal(const Array2D &vector) ; +/// \brief Returns the minimum value of a 2d int array +int minVal(const Array2D &vector) ; + +/// \brief Returns the index of the maximal value of a 1d double array +int maxIndex(Array1D& vector); +/// \brief Returns the index of the maximal value of a 1d int array +int maxIndex(Array1D& vector); +/// \brief Returns the index of the minimal value of a 1d double array +int minIndex(Array1D& vector); +/// \brief Returns the index of the minimal value of a 1d int array +int minIndex(Array1D& vector); + + +/// \brief Returns the column number of the maximal element in the irow-th row of a 2d double array +//int maxIndexR_2D(const Array2D& vector, const int irow); +/// \brief Returns the column number of the minimal element in the irow-th row of a 2d double array +//int minIndexR_2D(const Array2D& vector, const int irow); +/// \brief Returns the row number of the maximal element in the icol-th column of a 2d double array +int maxIndexC_2D(const Array2D& vector, const int icol); +/// \brief Returns the row number of the minimal element in the icol-th column of a 2d double array +int minIndexC_2D(const Array2D& vector, const int icol); + +#endif // MINMAX_H diff --git a/cpp/lib/tools/multiindex.cpp b/cpp/lib/tools/multiindex.cpp new file mode 100644 index 00000000..bf596a3a --- /dev/null +++ b/cpp/lib/tools/multiindex.cpp @@ -0,0 +1,624 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/** \file multiindex.cpp + * \brief Tools that deal with integer multiindices. + */ + +#include +#include + +#include "gen_defs.h" +#include "tools.h" +#include "arraytools.h" + +// Computes the number of PC terms in a total-order expansion +int computeNPCTerms(int ndim,int norder) +{ + + if (norder==-1) return 0; + + int enume=1; + int denom=1; + + int minNO = min(norder,ndim); + + for(int k=0; k < minNO; k++){ + enume = enume*(norder+ndim-k); + denom = denom*(k+1); + } + + int nPCTerms = enume/denom; + + return nPCTerms; +} + +// Computes total-order multiindex set, also return the number of elements +int computeMultiIndex(int ndim, int norder, Array2D &mi) +{ + if ( ndim==0 ) return 1; + + // Compute the number of PC terms + int npc=computeNPCTerms(ndim,norder); + + // Work arrays + Array1D ic(ndim,1); + + // Reset multi-index + int iup = 0; + mi.Resize(npc,ndim,0); + + if (norder > 0) { + + //-----------first order terms--------------------------- + for(int idim=0; idim < ndim; idim++){ + iup++; + mi(iup,idim) = 1; //multiIndex is a kronecker delta + } + + } // done if order > 0 + + if (norder > 1) { + + //-----------higher order terms-------------------------- + for(int iord=2; iord 1 + + return npc; +} + +// Computes total-order multiindex set in an int* format; also return the number of elements +int computeMultiIndexT(int ndim, int norder, int *mi) +{ + /* + Note that this function stores the multi-index in column-major + format, i.e. mi[j*ndim+i] holds the j-th index for dimension i + */ + + if ( ndim==0 ) return 1; + + // Compute the number of PC terms + int npc=computeNPCTerms(ndim,norder); + + // Work array + int *ic = new int[ndim]; + for (size_t i=0; i < (size_t) ndim; i++ ) ic[i] = 1; + + // Reset multi-index + int iup = 0; + for (size_t i=0; i < (size_t) npc*ndim; i++ ) mi[i]=0; + + if (norder > 0) { + + //-----------first order terms--------------------------- + for(int idim=0; idim < ndim; idim++){ + iup++; + mi[iup*ndim+idim] = 1; //multiIndex is a kronecker delta + } + + } + + if (norder > 1) { + + //-----------higher order terms-------------------------- + for(int iord=2; iord 1 + + delete [] ic; + + return npc; +} + +// Computes total-order multiindex with custom ordering +int computeMultiIndex(int ndim, int norder, Array2D &mi, string ordtype) +{ + + if ( ndim==0 ) return 1; + + // Test ordtype is known + bool isLex = ( ordtype == string("lex") ) || ( ordtype == ("LEX") ); + bool isRevLex = ( ordtype == string("revlex") ) || ( ordtype == ("REVLEX") ); + bool isCoLex = ( ordtype == string("colex") ) || ( ordtype == ("COLEX") ); + bool isRevCoLex = ( ordtype == string("revcolex") ) || ( ordtype == ("REVCOLEX") ); + bool isLexAll = ( ordtype == string("lexall") ) || ( ordtype == ("LEXALL") ); + bool isRevLexAll = ( ordtype == string("revlexall") ) || ( ordtype == ("REVLEXALL") ); + bool isCoLexAll = ( ordtype == string("colexall") ) || ( ordtype == ("COLEXALL") ); + bool isRevCoLexAll= ( ordtype == string("revcolexall") ) || ( ordtype == ("REVCOLEXALL") ); + + if ( not isLex && not isRevLex && not isCoLex && not isRevCoLex + && not isLexAll && not isRevLexAll && not isCoLexAll && not isRevCoLexAll ) { + throw Tantrum(string("computeMultiIndex: The passed in ordtype \"") + + ordtype + string("\" does not match any available option")); + } + + // Compute the number of PC terms + int npc=computeNPCTerms(ndim,norder); + + // Work arrays + Array1D ic(ndim,1); + + // Reset multi-index + int iup = 0; + mi.Resize(ndim,npc,0); + + int npcTmp = computeMultiIndexT(ndim, norder, mi.GetArrayPointer()); + + if ( norder == 0 ) { + Array2D miT; + transpose(mi, miT); + mi=miT; + return npc; + } + + if ( isLexAll || isRevLexAll || isCoLexAll || isRevCoLexAll ) { + int isgn=0, i1=0, j1=0, index=0; + int iordST=1, iordEN = npc; + int nTerms=iordEN-iordST; + do { + + heap_ext_(&nTerms, &isgn, &i1, &j1, &index); + if (index < 0) { + isgn = 0; + if ( isLexAll ) { + for ( int j = 0; j < ndim; j++ ) { + if ( mi(j,iordST+i1-1) < mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) < mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = lex + if ( isRevLexAll ) { + for ( int j = 0; j < ndim; j++ ) { + if ( mi(j,iordST+i1-1) > mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) > mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = revlex + else if ( isCoLexAll ) { + for ( int j = ndim-1; j >= 0; j-- ) { + if ( mi(j,iordST+i1-1) < mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) < mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = colex + else if ( isRevCoLexAll ) { + for ( int j = ndim-1; j >= 0; j-- ) { + if ( mi(j,iordST+i1-1) > mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) > mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = revcolex + } + + if (index > 0) { + int itmp ; + for ( int j = 0; j < ndim; j++ ) { + itmp = mi(j,iordST+i1-1); + mi(j,iordST+i1-1) = mi(j,iordST+j1-1); + mi(j,iordST+j1-1) = itmp; + } + } + + } while (index != 0); + + } /* done if ( isLexAll || isRevLexAll || isCoLexAll || isRevCoLexAll ) */ + + else { + + for (int iord=1; iord mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) > mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = revlex + else if ( ( ordtype == string("colex") ) || ( ordtype == ("COLEX") ) ) { + for ( int j = ndim-1; j >= 0; j-- ) { + if ( mi(j,iordST+i1-1) < mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) < mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = colex + else if ( ( ordtype == string("revcolex") ) || ( ordtype == ("REVCOLEX") ) ) { + for ( int j = ndim-1; j >= 0; j-- ) { + if ( mi(j,iordST+i1-1) > mi(j,iordST+j1-1) ) { + isgn = -1; break; + } + else if ( mi(j,iordST+j1-1) > mi(j,iordST+i1-1) ) { + isgn = 1; + break; + } + } + } // end if ordtype = revcolex + } + + if (index > 0) { + int itmp ; + for ( int j = 0; j < ndim; j++ ) { + itmp = mi(j,iordST+i1-1); + mi(j,iordST+i1-1) = mi(j,iordST+j1-1); + mi(j,iordST+j1-1) = itmp; + } + } + } while (index != 0); + + } /* end loop over orders */ + + } /* end else for order by order re-arrangement */ + + /* return */ + Array2D miT; + transpose(mi, miT); + mi=miT; + + return npc; + +} + +// Computes tensor-product multiindex set, also return the number of elements +int computeMultiIndexTP(Array1D& maxorders, Array2D& mindex) +{ + int ndim=maxorders.XSize(); + int npc; + + + if (ndim==1){ + mindex.Resize(maxorders(0)+1,1,0); + for(int i=0;i<=maxorders(0);i++) + mindex(i,0)=i; + + return maxorders(0)+1; + } + + Array1D maxorders_1(ndim-1,0); + for (int j=0;j mindex_1; + int npc_1=computeMultiIndexTP(maxorders_1,mindex_1); + + npc=npc_1*(maxorders(ndim-1)+1); + mindex.Resize(npc,ndim,-1); + + for (int ib=0;ib<=maxorders(ndim-1);ib++){ + for (int k=0; k& maxorders) +{ + int nhdmr=maxorders.XSize()-1; + + int cnt=0; + for(int i=0;i<=nhdmr;i++){ + cnt+= ( choose(maxorders(i),i)*choose(ndim,i) ); + } + + return cnt; +} + +// Computes HDMR multiindex set, also return the number of elements +int computeMultiIndexHDMR(int ndim,Array1D& maxorders, Array2D& mindex) +{ + int nhdmr=maxorders.XSize()-1; + int npc=computeNPCTermsHDMR(ndim,maxorders); + + mindex.Resize(npc,ndim,0); + int iup=1; + for(int i=1; i<=nhdmr;i++){ + Array2D ind; + chooseComb(ndim,i,ind); + + if (maxorders(i) mi; + computeMultiIndex(i,maxorders(i)-i,mi); + + for(int j=0;j<(int)ind.XSize();j++){ + for(int k=0; k<(int)mi.XSize();k++){ + for(int ii=0;ii >& sp_mindex, int ndim, Array2D& mindex){ + + int npc=0; + for(int i=0;i<(int) sp_mindex.XSize();i++){ + npc+=sp_mindex(i).XSize(); + } + mindex.Resize(npc,ndim,0); + int ipc=0; + for(int i=0;i<(int) sp_mindex.XSize();i++){ + for(int j=0;j<(int) sp_mindex(i).XSize();j++){ + for(int i_effdim=0;i_effdim& mindex_try,Array2D& mindex){ + + bool admis=true; + int npc=mindex.XSize(); + int ndim=mindex.YSize(); + + Array1D tmp; + tmp=mindex_try; + + for(int j=0;j0){ + tmp(j)--; + for(int ipc=0;ipc cur_mindex; + getRow(mindex,ipc,cur_mindex); + + if(is_equal(tmp,cur_mindex)){ + admis=true; + break; + } + admis=false; + + } + + if(admis==false) + break; + + tmp(j)++; + } + + } + + return admis; +} + +// Increase a multiindex set by one order with admissible bases +void upOrder(Array2D& mindex,Array2D& new_mindex){ + + int npc=mindex.XSize(); + int ndim=mindex.YSize(); + + Array1D orders; + getOrders(mindex,orders); + + new_mindex=mindex; + + int imax; + int maxOrd=maxVal(orders,&imax); + + for(int ipc=0;ipc new_mindex_try; + getRow(mindex,ipc,new_mindex_try); + for(int j=0;j<=nzind;j++){ + new_mindex_try(j)++; + if(is_admis(new_mindex_try,new_mindex)){ + paddMatRow(new_mindex,new_mindex_try); + } + + new_mindex_try(j)--; + } + } + } + + return; +} + +// Gets the total degree of each multiindex term +void getOrders(Array2D& mindex,Array1D& orders){ + + int npc=mindex.XSize(); + int ndim=mindex.YSize(); + + orders.Resize(npc,0); + + for (int ipc=0; ipc mi) +{ + + int nd=mi.XSize(); + int ss=0; + + for(int id=0;id mi) +{ + int index=0; + int nd=mi.XSize(); + + int ss=0; + for(int id=0;id1){ + + for(int ii=ss;ii>mi(0);ii--) + index+=computeNPCTerms(nd-2,ss-ii); + + Array1D mic(nd-1,0); + for(int id=0;id. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef MULTIINDEX_H +#define MULTIINDEX_H + +#include "Array1D.h" +#include "Array2D.h" + + +/** \file multiindex.h + * \brief Header for tools that deal with integer multiindices. + * \todo Multiindex could be a separate class and a part of core UQTk. + */ + +extern "C" void heap_ext_(const int *,const int *, int *, int *, int *); + +/// \brief Computes the number of PC basis terms +/// for Total-Order truncation with a given dimensionality and order +/// \note The formula is (ndim+norder)!/(ndim!norder!) +int computeNPCTerms(int ndim,int norder); + +/// \brief Computes the multiindex set of a PC basis +/// for Total-Order truncation with a given dimensionality and order +/// Also, returns the number of terms. +int computeMultiIndex(int ndim,int norder, Array2D &mi); + +/// \brief Computes the multiindex set of a PC basis +/// for Total-Order truncation with a given dimensionality and order +/// Also, returns the number of terms. Note that here, the +/// multiindex array pointer stores indices in column-major format, +/// i.e. mi[j*ndim+i] holds the j-th index for dimension i +int computeMultiIndexT(int ndim,int norder, int *mi); + +/// \brief Computes the multiindex set of a PC basis +/// for Total-Order truncation with a given dimensionality and order +/// Also, returns the number of terms. +int computeMultiIndex(int ndim,int norder, Array2D &mi, string ordtype); + + +/// \brief Computes the multiindex set of a PC basis +/// for Tensor-Product truncation with a given maximum order per dimensionality +/// Also, returns the number of terms. +int computeMultiIndexTP(Array1D& maxorders, Array2D& mindex); + +/// \brief Computes the number of PC basis terms +/// for HDMR truncation with a given dimensionality and maxorders array +/// that contains maximal orders per interaction dimensionalities. +int computeNPCTermsHDMR(int ndim, Array1D& maxorders); + +/// \brief Computes the multiindex set of a PC basis +/// for HDMR truncation with a given dimensionality and maxorders array +/// that contains maximal orders per interaction dimensionalities. +int computeMultiIndexHDMR(int ndim, Array1D& maxorders,Array2D& mindex); + +/// \brief Decode a multiindex set from a sparse format to a regular format +/// \note For encoding and for more details on the format, see encodeMindex function of PCSet class +/// \sa PCSet.h +void decodeMindex(Array1D< Array2D >& sp_mindex, int ndim, Array2D& mindex); + + +/// \brief Given a multiindex set it computes a new multiindex set where only 'admissible' bases are added +/// \note A new basis is admissible, if by subtracting one order from any of the dimensions with +/// non-zero order, one never leaves the set of old multiindices +void upOrder(Array2D& mindex,Array2D& new_mindex); + +/// \brief A boolean check to see if a new basis term is admissible or not +bool is_admis(Array1D& mindex_try,Array2D& mindex); + +/// \brief Given a multiindex set, it returns the orders of each basis term +/// \note Essentially, this function performs sums of each rows +void getOrders(Array2D& mindex,Array1D& orders); + +/// \brief Given a single multiindex, this returns its relative position in the total-order multiindex set +int get_invmindex(Array1D mi); + +/// \brief Given a single multiindex, this returns its relative position in the total-order multiindex set among the bases of the same order +int get_invmindex_ord(Array1D mi); + + +#endif // MULTIINDEX_H diff --git a/cpp/lib/tools/pcmaps.cpp b/cpp/lib/tools/pcmaps.cpp new file mode 100644 index 00000000..c37e71f0 --- /dev/null +++ b/cpp/lib/tools/pcmaps.cpp @@ -0,0 +1,478 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/** \file pcmaps.cpp + * \brief Suite of functions to help map one kind of a PC variable to another. + */ + +#include "Array1D.h" +#include "Array2D.h" +#include "gen_defs.h" +#include "error_handlers.h" +#include "probability.h" +#include "arrayio.h" +#include "pcmaps.h" +#include "combin.h" +#include +#include +#include + + +#define EPS 1e-16 +#define MXEPS 1e+100 + +using namespace std; + +// Implementation of map from one PC germ to another +double PCtoPC(double x, const std::string pcIn, double in1, double in2, const std::string pcOut, double out1, double out2) +{ + // Output variable + double y; + + /////////////////////////////////////// + // Sanity check on PC inputs x + /////////////////////////////////////// + if ( pcIn=="HG" || pcIn=="pdf" ){ + // do nothing + } + else if (pcIn=="LU" or pcIn=="JB"){ + if (fabs(x)>1.0) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input x is out of the range!"); + } + else if (pcIn=="SW" or pcIn=="LG"){ + if (x<0.0) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input x is out of the range!"); + } + else if (pcIn=="TG"){ + if (x>in1) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input x is out of the range!"); + } + else if (pcIn=="RB"){ + if (x>in2/(1.-in1) or x<0) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input x is out of the range!"); + } + else { + printf("pcIn = %s\n",pcIn.c_str()) ; + throw Tantrum("pcmaps.cpp::Input PC is not recognized!\n"); + } + + /////////////////////////////////////// + // Sanity check on input PC parameters + /////////////////////////////////////// + if (pcIn=="LU" or pcIn=="HG" or pcIn=="TG" or pcIn=="pdf"){ + // do nothing + } + else if (pcIn=="JB"){ + if (in1<-1. or in2>1.) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input parameter is out of the range!"); + } + else if (pcIn=="SW"){ + if (in2<=0.) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input parameter is out of the range!"); + } + else if (pcIn=="LG"){ + if (in1<-1.) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input parameter is out of the range!"); + } + else if (pcIn=="RB"){ + if (in2<=0. or in1<=0) + throw Tantrum("pcmaps.cpp:: PCtoPC:: input parameter is out of the range!"); + } + else { + printf("pcIn = %s\n",pcIn.c_str()) ; + throw Tantrum("pcmaps.cpp::Input PC is not recognized!\n"); + } + + /////////////////////////////////////// + // Sanity check on output PC parameters + /////////////////////////////////////// + if (pcOut=="LU" or pcOut=="HG" or pcOut=="TG" or pcOut=="pdf"){ + // do nothing + } + else if (pcOut=="JB"){ + if (out1<-1. or out2>1.) + throw Tantrum("pcmaps.cpp:: PCtoPC:: output parameter is out of the range!"); + } + else if (pcOut=="SW"){ + if (out2<=0.) + throw Tantrum("pcmaps.cpp:: PCtoPC:: output parameter is out of the range!"); + } + else if (pcOut=="LG") { + if (out1<0.) + throw Tantrum("pcmaps.cpp:: PCtoPC:: output parameter is out of the range!"); + } + else if (pcOut=="RB"){ + if (out2<=0. or out1<=0) + throw Tantrum("pcmaps.cpp:: PCtoPC:: output parameter is out of the range!"); + } + else { + printf("pcOut = %s\n",pcOut.c_str()) ; + throw Tantrum("pcmaps.cpp::Output PC is not recognized!\n"); + } + + /////////////////////////////////////// + // Maps when input and output PCs are the same + /////////////////////////////////////// + if (pcIn=="LU" && pcOut=="LU"){ + y=x; + } + else if (pcIn=="HG" && pcOut=="HG"){ + y=x; + } + else if (pcIn=="SW" && pcOut=="SW"){ + y=pow(x,out2/in2)*exp(out1-in1*out2/in2); + } + else if (pcIn=="JB" && pcOut=="JB"){ + if(fabs(x)==1) y=x; + else + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + else if (pcIn=="LG" && pcOut=="LG"){ + if (x==0) y=0.; + else y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"LG",out1,0); + } + else if (pcIn=="TG" && pcOut=="TG"){ + if (x==in1) y=out1; + else if (in1==out1) y=x; + else y=PCtoPC(PCtoPC(x,"TG",in1,0,"LU",0,0),"LU",0,0,"TG",out1,0); + } + else if (pcIn=="RB" && pcOut=="RB"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"LU",0,0),"LU",0,0,"RB",out1,out2); + } + else if (pcIn=="pdf" && pcOut=="pdf"){ + y=x; + } + + /////////////////////////////////////// + // Maps when input and output PCs are not the same + /////////////////////////////////////// + + // Gauss-Hermite ////////////////////// + else if (pcIn=="LU" && pcOut=="HG"){ + if(fabs(x)==1.) + throw Tantrum("pcmaps.cpp::LU->HG: the value at the domain boundary (would map to infinity)!\n"); + y=sqrt(2.0)*inverf(x); + } + else if (pcIn=="HG" && pcOut=="LU"){ + y=erf(x/sqrt(2.0)); + } + + // Gamma-Laguerre ////////////////////// + else if (pcIn=="LG" && pcOut=="LU"){ + y=2.*gammai(in1+1,x)-1.; + } + else if (pcIn=="LU" && pcOut=="LG"){ + y=rtbis_mod(PCtoPC,0.,MXEPS,EPS,x,"LG",out1,out2,"LU",in1,in2); + } + + else if (pcIn=="LG" && pcOut=="HG"){ + y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"HG",0,0); + } + else if (pcIn=="HG" && pcOut=="LG"){ + y=PCtoPC(PCtoPC(x,"HG",0,0,"LU",0,0),"LU",0,0,"LG",out1,0); + } + + // Jacobi-Beta ////////////////////// + else if (pcIn=="JB" && pcOut=="LU"){ + y=2.*betai(in1+1,in2+1,(x+1.)/2.)-1.; + } + else if (pcIn=="LU" && pcOut=="JB"){ + if(fabs(x)==1) y=x; + else + y=rtbis_mod(PCtoPC,-1.,1.,EPS,x,"JB",out1,out2,"LU",in1,in2); + } + + else if (pcIn=="JB" && pcOut=="HG"){ + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"HG",0,0); + } + else if (pcIn=="HG" && pcOut=="JB"){ + y=PCtoPC(PCtoPC(x,"HG",0,0,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + + else if (pcIn=="LG" && pcOut=="JB"){ + y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + else if (pcIn=="JB" && pcOut=="LG"){ + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"LG",out1,0); + } + + // Stieltjes-Wigart ////////////////////// + else if (pcIn=="LU" && pcOut=="SW"){ + y=PCtoPC(PCtoPC(x,"LU",0,0,"HG",0,0),"HG",0,0,"SW",out1,out2); + } + else if (pcIn=="SW" && pcOut=="LU"){ + y=PCtoPC(PCtoPC(x,"SW",in1,in2,"HG",0,0),"HG",0,0,"LU",0,0); + } + + else if (pcIn=="HG" && pcOut=="SW"){ + y=exp(out1+out2*x); + } + else if (pcIn=="SW" && pcOut=="HG"){ + y=(log(x)-in1)/in2; + } + + else if (pcIn=="LG" && pcOut=="SW"){ + y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"SW",out1,out2); + } + else if (pcIn=="SW" && pcOut=="LG"){ + y=PCtoPC(PCtoPC(x,"SW",in1,in2,"LU",0,0),"LU",0,0,"LG",out1,0); + } + + else if (pcIn=="JB" && pcOut=="SW"){ + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"SW",out1,out2); + } + else if (pcIn=="SW" && pcOut=="JB"){ + y=PCtoPC(PCtoPC(x,"SW",in1,in2,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + + // Truncated Gaussian ////////////////////// + else if (pcIn=="TG" && pcOut=="LU"){ + y=normcdf(x)/normcdf(in1)*2.-1.; + } + else if (pcIn=="LU" && pcOut=="TG"){ + if(fabs(x)==1.) + throw Tantrum("pcmaps.cpp::LU->TG: the value at the domain boundary (would map to infinity)!\n"); + y=invnormcdf(0.5*(x+1.)*normcdf(out1)); + } + + else if (pcIn=="TG" && pcOut=="HG"){ + y=PCtoPC(PCtoPC(x,"TG",in1,0,"LU",0,0),"LU",0,0,"HG",0,0); + } + else if (pcIn=="HG" && pcOut=="TG"){ + y=PCtoPC(PCtoPC(x,"HG",0,0,"LU",0,0),"LU",0,0,"TG",out1,0); + } + + else if (pcIn=="TG" && pcOut=="LG"){ + y=PCtoPC(PCtoPC(x,"TG",in1,0,"LU",0,0),"LU",0,0,"LG",out1,0); + } + else if (pcIn=="LG" && pcOut=="TG"){ + y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"TG",out1,0); + } + + else if (pcIn=="TG" && pcOut=="JB"){ + y=PCtoPC(PCtoPC(x,"TG",in1,0,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + else if (pcIn=="JB" && pcOut=="TG"){ + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"TG",out1,0); + } + + else if (pcIn=="TG" && pcOut=="SW"){ + y=PCtoPC(PCtoPC(x,"TG",in1,0,"LU",0,0),"LU",0,0,"SW",out1,out2); + } + else if (pcIn=="SW" && pcOut=="TG"){ + y=PCtoPC(PCtoPC(x,"SW",in1,in2,"LU",0,0),"LU",0,0,"TG",out1,0); + } + + // Roe-Baker ////////////////////// + else if (pcIn=="RB" && pcOut=="LU"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"TG",in1,0),"TG",in1,0,"LU",0,0); + } + else if (pcIn=="LU" && pcOut=="RB"){ + if(fabs(x)==1.) + throw Tantrum("pcmaps.cpp::LU->RB: the value at the domain boundary (would map to infinity)!\n"); + y=PCtoPC(PCtoPC(x,"LU",0,0,"TG",out1,0),"TG",out1,0,"RB",out1,out2); + } + + else if (pcIn=="RB" && pcOut=="HG"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"LU",0,0),"LU",0,0,"HG",0,0); + } + else if (pcIn=="HG" && pcOut=="RB"){ + y=PCtoPC(PCtoPC(x,"HG",0,0,"LU",0,0),"LU",0,0,"RB",out1,out2); + } + + else if (pcIn=="RB" && pcOut=="LG"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"LU",0,0),"LU",0,0,"LG",out1,0); + } + else if (pcIn=="LG" && pcOut=="RB"){ + y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"RB",out1,out2); + } + + else if (pcIn=="RB" && pcOut=="JB"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + else if (pcIn=="JB" && pcOut=="RB"){ + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"RB",out1,out2); + } + + else if (pcIn=="RB" && pcOut=="SW"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"LU",0,0),"LU",0,0,"SW",out1,out2); + } + else if (pcIn=="SW" && pcOut=="RB"){ + y=PCtoPC(PCtoPC(x,"SW",in1,in2,"LU",0,0),"LU",0,0,"RB",out1,out2); + } + + else if (pcIn=="TG" && pcOut=="RB"){ + y=out2/(1.-PCtoPC(x,"TG",in1,0,"TG",out1,0)); + } + else if (pcIn=="RB" && pcOut=="TG"){ + y=PCtoPC(1.-in2/x,"TG",in1,0,"TG",out1,0); + } + + // Custom PDF given by cdf.dat ///////////////// + else if (pcIn=="LU" && pcOut=="pdf"){ + Array2D cdf ; + read_datafileVS(cdf,"cdf.dat"); + linint( cdf, 0.5*(x+1) , y, 1 ) ; + } + else if (pcIn=="pdf" && pcOut=="LU"){ + Array2D cdf ; + read_datafileVS(cdf,"cdf.dat"); + linint( cdf, x , y, 0 ) ; + y = y*2.0-1.0 ; + } + + else if (pcIn=="pdf" && pcOut=="HG"){ + y=PCtoPC(PCtoPC(x,"pdf",0,0,"LU",0,0),"LU",0,0,"HG",0,0); + } + else if (pcIn=="HG" && pcOut=="pdf"){ + y=PCtoPC(PCtoPC(x,"HG",0,0,"LU",0,0),"LU",0,0,"pdf",0,0); + } + + else if (pcIn=="pdf" && pcOut=="LG"){ + y=PCtoPC(PCtoPC(x,"pdf",0,0,"LU",0,0),"LU",0,0,"LG",out1,0); + } + else if (pcIn=="LG" && pcOut=="pdf"){ + y=PCtoPC(PCtoPC(x,"LG",in1,0,"LU",0,0),"LU",0,0,"pdf",0,0); + } + + else if (pcIn=="pdf" && pcOut=="JB"){ + y=PCtoPC(PCtoPC(x,"pdf",0,0,"LU",0,0),"LU",0,0,"JB",out1,out2); + } + else if (pcIn=="JB" && pcOut=="pdf"){ + y=PCtoPC(PCtoPC(x,"JB",in1,in2,"LU",0,0),"LU",0,0,"pdf",0,0); + } + + else if (pcIn=="pdf" && pcOut=="SW"){ + y=PCtoPC(PCtoPC(x,"pdf",0,0,"LU",0,0),"LU",0,0,"SW",out1,out2); + } + else if (pcIn=="SW" && pcOut=="pdf"){ + y=PCtoPC(PCtoPC(x,"SW",in1,in2,"LU",0,0),"LU",0,0,"pdf",0,0); + } + + else if (pcIn=="pdf" && pcOut=="TG"){ + y=PCtoPC(PCtoPC(x,"pdf",0,0,"LU",0,0),"LU",0,0,"TG",out1,0); + } + else if (pcIn=="TG" && pcOut=="pdf"){ + y=PCtoPC(PCtoPC(x,"TG",in1,0,"LU",0,0),"LU",0,0,"pdf",0,0); + } + + else if (pcIn=="pdf" && pcOut=="RB"){ + y=PCtoPC(PCtoPC(x,"pdf",0,0,"LU",0,0),"LU",0,0,"RB",out1,out2); + } + else if (pcIn=="RB" && pcOut=="pdf"){ + y=PCtoPC(PCtoPC(x,"RB",in1,in2,"LU",0,0),"LU",0,0,"pdf",0,0); + } + + else + throw Tantrum("pcmaps.cpp::Input-Output PC pair is not recognized!\n"); + + return y; +} + +// Entrywise map from a 2d-array to a 2-d array +void PCtoPC(Array2D& xx, const std::string pcIn, double in1, double in2, Array2D& yy, const std::string pcOut, double out1, double out2) +{ + + // Set the dimension + int n=xx.XSize(); + int m=xx.YSize(); + + // Output array + yy.Resize(n,m); + + // Entrywise map + for(int i=0;i 0.0) {printf("Root must be bracketed for bisection in rtbis"); exit(1);}// made the inequality strict + rtb = f < 0.0 ? (dx=x2-x1,x1) : (dx=x1-x2,x2); + for (j=0;j &xydata, const double x, double &y, int col ) +{ + + assert(col==0 || col==1) ; + + int n = xydata.XSize() ; + + if ( x < xydata(0,col) ) + y = 0.0 ; + else if ( x > xydata(n-1,col) ) + y = 0.0 ; + + int i = 0 ; + while ( ( x > xydata(i+1,col) ) && ( i < n-2 ) ) i++ ; + + y = xydata(i,1-col) + ( x - xydata(i,col) ) + *( xydata(i+1,1-col) - xydata(i,1-col) ) / ( xydata(i+1,col) - xydata(i,col) ) ; + + return ; + +} + +// Linear interpolation according to first column of a given 2d array +void linint( Array2D &xydata, const double x, double &y ) +{ + + int n = xydata.XSize() ; + + if ( x < xydata(0,0) ) + y = 0.0 ; + else if ( x > xydata(n-1,0) ) + y = 0.0 ; + + int i = 0 ; + while ( ( x > xydata(i+1,0) ) && ( i < n-2 ) ) i++ ; + + y = xydata(i,1) + ( x - xydata(i,0) ) + *( xydata(i+1,1) - xydata(i,1) ) / ( xydata(i+1,0) - xydata(i,0) ) ; + + return ; + +} diff --git a/cpp/lib/tools/pcmaps.h b/cpp/lib/tools/pcmaps.h new file mode 100644 index 00000000..618a24f8 --- /dev/null +++ b/cpp/lib/tools/pcmaps.h @@ -0,0 +1,70 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef PCMAPS_H +#define PCMAPS_H + +/** \file pcmaps.h + * \brief Header for suite of functions to help map one kind of a PC variable to another. + * \todo Perhaps use more robust tools, like dcdflib. + * \todo Need more testing of these tools. + */ + +/// \brief Implements a map y=f(x), where f is a function mapping one PC domain (pcIn with parameters in1,in2) +/// to another (pcOut with parameters out1,out2) +/// \note Besides standard PC types, it also incorporates +/// a) 'TG' : truncated-gaussian variable, +/// b) 'RB' : Roe-Baker PDF from Roe, G. H., & Baker, M. B. (2007). Why is climate sensitivity so unpredictable?. Science, 318(5850), 629-632. +/// c) 'pdf': Given arbitrary cumulative distribution function values in cdf.dat it maps corresponding r.v. to PC variables as well +/// \param[in] x : Input scalar x +/// \param[in] pcIn : PC type for input x (options are LU, HG, LG, JB, SW, TG, RB, pdf) +/// \param[in] in1 : Parameter #1 for input PC (if relevant, i.e. for LG, JB, SW, TG, RB) +/// \param[in] in2 : Parameter #2 for input PC (if relevant, i.e. for JB, SW, RB) +/// \param[in] pcOut : PC type for output y (options are LU, HG, LG, JB, SW, TG, RB, pdf) +/// \param[in] out1 : Parameter #1 for output PC (if relevant, i.e. for LG, JB, SW, TG, RB) +/// \param[in] out2 : Parameter #2 for output PC (if relevant, i.e. for JB, SW, RB) +/// \return y : Output scalar y +/// \note The user is free to choose any value of x that is in the PC domain defined by pcIn +/// \note The map f() is a map frpm pcIn germ to a pcOut germ +/// \note For example, y=PCtoPC(x,'HG',0,0,'LU',0,0) maps \f$(-\infty,\infty)\f$ to \f$[-1,1]\f$ as a map from standard normal r.v. to uniform r.v. +double PCtoPC(double x, const std::string pcIn, double in1, double in2, const std::string pcOut, double out1, double out2); + +/// \brief Implements PCtoPC() map entrywise from array xx to yy +void PCtoPC(Array2D& xx, const std::string pcIn, double in1, double in2, Array2D& yy, const std::string pcOut, double out1, double out2); + +/// \brief Bisection method for root-finding, modified to invert PCtoPC maps +double rtbis_mod(double func(double,const std::string,double,double,const std::string,double,double), const double x1, const double x2, const double xacc,double x, const std::string pcIn, double in1, double in2, const std::string pcOut, double out1, double out2); + +/// \brief Auxiliary linear interpolation function +void linint( Array2D &xydata, const double x, double &y, int col ) ; + +/// \brief Auxiliary linear interpolation function +/// \note Currently not used, as there is an overloaded linint() function that is more general +void linint( Array2D &xydata, const double x, double &y ) ; + + +//--------------------------------------------------------------------------------------- +#endif // PCMAPS_H diff --git a/cpp/lib/tools/probability.cpp b/cpp/lib/tools/probability.cpp new file mode 100644 index 00000000..2115e899 --- /dev/null +++ b/cpp/lib/tools/probability.cpp @@ -0,0 +1,873 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/** \file probability.cpp + * \brief Probability and random number generation- related tools. + */ +#include +#include +#include +#include + +#include "Array1D.h" +#include "Array2D.h" +#include "probability.h" +#include "rosenblatt.h" +#include "combin.h" +#include "arraytools.h" +#include "gen_defs.h" + +#include "minmax.h" + +#ifndef M_PI +#define M_PI atan(1.0) * 4.0 +#endif + +using namespace std; + +// Error function via incomplete gamma function +double erff(const double x) +{ + return x < 0.0 ? -gammai(0.5,x*x) : gammai(0.5,x*x); +} + +// Inverse error function, input scaled to [-1,1] +double inverf(double y0) +{ + double result_; + + double expm2; + double s2pi; + double x; + double y; + double z; + double y2; + double x0; + double x1; + int code; + double p0; + double q0; + double p1; + double q1; + double p2; + double q2; + + + y0=0.5*(y0+1); + + expm2 = 0.13533528323661269189; + s2pi = 2.50662827463100050242; + if( y0<=0 or y0 >=1) + { + cout << "Error in inverting erf, the argument should be -11.0-expm2 ) + { + y = 1.0-y; + code = 0; + } + if( y>expm2 ) + { + y = y-0.5; + y2 = y*y; + p0 = -59.9633501014107895267; + p0 = 98.0010754185999661536+y2*p0; + p0 = -56.6762857469070293439+y2*p0; + p0 = 13.9312609387279679503+y2*p0; + p0 = -1.23916583867381258016+y2*p0; + q0 = 1; + q0 = 1.95448858338141759834+y2*q0; + q0 = 4.67627912898881538453+y2*q0; + q0 = 86.3602421390890590575+y2*q0; + q0 = -225.462687854119370527+y2*q0; + q0 = 200.260212380060660359+y2*q0; + q0 = -82.0372256168333339912+y2*q0; + q0 = 15.9056225126211695515+y2*q0; + q0 = -1.18331621121330003142+y2*q0; + x = y+y*y2*p0/q0; + x = x*s2pi; + result_ = x; + return result_/sqrt(2.); + } + x = sqrt(-2.0*log(y)); + x0 = x-log(x)/x; + z = 1.0/x; + if( x<8.0 ) + { + p1 = 4.05544892305962419923; + p1 = 31.5251094599893866154+z*p1; + p1 = 57.1628192246421288162+z*p1; + p1 = 44.0805073893200834700+z*p1; + p1 = 14.6849561928858024014+z*p1; + p1 = 2.18663306850790267539+z*p1; + p1 = -1.40256079171354495875*0.1+z*p1; + p1 = -3.50424626827848203418*0.01+z*p1; + p1 = -8.57456785154685413611*0.0001+z*p1; + q1 = 1; + q1 = 15.7799883256466749731+z*q1; + q1 = 45.3907635128879210584+z*q1; + q1 = 41.3172038254672030440+z*q1; + q1 = 15.0425385692907503408+z*q1; + q1 = 2.50464946208309415979+z*q1; + q1 = -1.42182922854787788574*0.1+z*q1; + q1 = -3.80806407691578277194*0.01+z*q1; + q1 = -9.33259480895457427372*0.0001+z*q1; + x1 = z*p1/q1; + } + else + { + p2 = 3.23774891776946035970; + p2 = 6.91522889068984211695+z*p2; + p2 = 3.93881025292474443415+z*p2; + p2 = 1.33303460815807542389+z*p2; + p2 = 2.01485389549179081538*0.1+z*p2; + p2 = 1.23716634817820021358*0.01+z*p2; + p2 = 3.01581553508235416007*0.0001+z*p2; + p2 = 2.65806974686737550832*0.000001+z*p2; + p2 = 6.23974539184983293730*0.000000001+z*p2; + q2 = 1; + q2 = 6.02427039364742014255+z*q2; + q2 = 3.67983563856160859403+z*q2; + q2 = 1.37702099489081330271+z*q2; + q2 = 2.16236993594496635890*0.1+z*q2; + q2 = 1.34204006088543189037*0.01+z*q2; + q2 = 3.28014464682127739104*0.0001+z*q2; + q2 = 2.89247864745380683936*0.000001+z*q2; + q2 = 6.79019408009981274425*0.000000001+z*q2; + x1 = z*p2/q2; + } + x = x0-x1; + if( code!=0 ) + { + x = -x; + } + result_ = x; + + return result_/sqrt(2.); +} + +// Inverse of standard normal CDF +double invnormcdf(double y) +{ + // Scaled inverse error function, really + return sqrt(2.)*inverf(2.*y-1.); +} + +// Standard normal CDF +double normcdf(double y) +{ + // Scaled and shifted error function + return 0.5*(1.+erf(y/sqrt(2.))); +} + +// Complementary function for standard normal CDF +double normcdfc(double y) +{ + return 1.-normcdf(y); +} + +// Generate an array of uniform random variables +void generate_uniform(double* rvar,int ns, int nd, int zSeed) +{ + + dsfmt_gv_init_gen_rand(zSeed ); + + + for(int is = 0 ; is < ns*nd ; is++) + rvar[is]=dsfmt_gv_genrand_urv(); + + return; +} + +// Generate an array of uniform random variables +void generate_uniform(Array2D& rvar,int zSeed) +{ + int nsample = (int) rvar.XSize(); + int ndim = (int) rvar.YSize(); + + + generate_uniform(rvar.GetArrayPointer(), nsample, ndim, zSeed); + + return; +} + +// Generate an array of uniform random variables +void generate_uniform(double *rvar, int ns, int nd, dsfmt_t *rnstate) +{ + int i ; + // Need to check allocation? + for ( i=0; i &rvar, dsfmt_t *rnstate) +{ + int nsample = (int) rvar.XSize() ; + int ndim = (int) rvar.YSize() ; + + generate_uniform(rvar.GetArrayPointer(),nsample, ndim, rnstate) ; + + return ; + +} + +// Generate an array of uniform random variables with LHS +void generate_uniform_lhs(double *rvar,int nsample, int ndim, int zSeed) +{ + + int *perm = (int *) malloc(nsample*sizeof(int)) ; + + dsfmt_gv_init_gen_rand(zSeed ); + + int ii=0; + for(int id=0;id& rvar,int zSeed) +{ + int ndim=rvar.YSize(); + int nsample=rvar.XSize(); + + generate_uniform_lhs(rvar.GetArrayPointer(),nsample,ndim,zSeed); + + return; +} + +// Generate an array of uniform random variables with LHS +void generate_uniform_lhs(double *rvar,int nsample, int ndim, dsfmt_t *rnstate) +{ + + int *perm = (int *) malloc(nsample*sizeof(int)) ; + + int ii=0; + for(int id=0;id& rvar,dsfmt_t *rnstate) +{ + int ndim=rvar.YSize(); + int nsample=rvar.XSize(); + + generate_uniform_lhs(rvar.GetArrayPointer(),nsample, ndim,rnstate); + + return; +} + +// Generate an array of standard normal random variables +void generate_normal(Array2D& rvar,int zSeed) +{ + int ndim=rvar.YSize(); + int nsample=rvar.XSize(); + + dsfmt_gv_init_gen_rand( zSeed ); + for(int is = 0 ; is < nsample ; is++){ + for(int id = 0 ; id < ndim ; id++){ + rvar(is,id)=dsfmt_gv_genrand_nrv(); + } + } + + return; +} + +// Generate an array of standard normal random variables with LHS +void generate_normal_lhs(Array2D& rvar,int zSeed) +{ + int ndim=rvar.YSize(); + int nsample=rvar.XSize(); + + generate_uniform_lhs(rvar,zSeed); + for(int is = 0 ; is < nsample ; is++){ + for(int id = 0 ; id < ndim ; id++){ + rvar(is,id)=invnormcdf(rvar(is,id)); + } + } + + return; +} + +// Returns the median of an array of data +double get_median(const Array1D& data) +{ + + int ndata=data.XSize(); + Array1D data_copy; + data_copy=data; + + double median; + if (ndata % 2 == 1){ + int k=(int) ndata/2; + median=select_kth(k,data_copy); + } + else{ + int k=ndata/2; + median=( select_kth(k,data_copy)+select_kth(k-1,data_copy) ) / 2.; + } + return median; + +} + +// Returns the mean of an array of data +double get_mean(const Array1D& data) { + + double mean=0.0; + int ndata=data.XSize(); + + for(int i=0;i& data) { + + double mean=0.0; + int nrows=data.XSize(); + int ncols=data.YSize(); + + for(int i2=0;i2& data) +{ + double std; + double var=get_var(data); + + if (var>=0) + std=sqrt(var); + else{ + cout << "probability.cpp:get_std(): negative variance!. Exiting." << endl; + exit(1); + } + + return std; + +} + +// Returns the unbiased estimator of variance of an array of data +double get_var(const Array1D& data) +{ + double mean=get_mean(data); + double mean2=0.0; + + int ndata=data.XSize(); + + for(int i=0;i& data_c, Array1D& w, Array1D& mean) +{ + double var=0.; + int ndim=data_c.YSize(); + int nsam=data_c.XSize(); + + getMean(data_c,mean); + + Array1D data_1s(ndim,0.e0); + + for (int isam=0;isam& data_c, Array1D& mean) +{ + + int ndim=data_c.YSize();//=mean.XSize() + int nsam=data_c.XSize(); + + CHECKEQ(mean.XSize(), ndim); + + for (int idim=0; idim& matrix, Array1D& mean, char *RC) +{ + + int nrows=matrix.XSize(); + int ncols=matrix.YSize(); + + if ( std::string(RC) == std::string("C")) { + mean.Resize(ncols,0.0); + for (int i2=0; i2 0; k-- ) + { + int j = dsfmt_genrand_uint32(rnstate) % (k+1) ; + int temp = a[j]; + a[j] = a[k]; + a[k] = temp; + } + return ; +} + +// KDE estimation of a PDF +void getPdf_figtree(Array2D& source,Array2D& target,Array1D& sig, Array1D& density, Array1D& weight) +{ + int NSources=source.XSize(); + int Dim=source.YSize(); + + int MTargets=target.XSize(); + + Array2D allpts(NSources+MTargets,Dim,0.e0); + Array1D aa(Dim,0.e0); + Array1D bb(Dim,0.e0); + + merge(source,target,allpts); + getDomain(allpts,aa,bb); + double alpha=sqrt(2.0)*sig(0)/(bb(0)-aa(0)); + for (int i_dim=1;i_dim1) {printf("Source point > 1\n"); source(id,i_dim)=1.;} + } + + for (int i=0;i1) {printf("Heads Up:Target outside [0,1] range\n");} + } + + int W=1; + double * g_auto = new double[W*MTargets]; + + memset( g_auto, 0, sizeof(double)*W*MTargets ); + figtree( Dim, NSources, MTargets, W, pSources, Bandwidth, pWeights, pTargets, epsilon, g_auto, + FIGTREE_EVAL_AUTO, FIGTREE_PARAM_NON_UNIFORM, FIGTREE_TRUNC_CLUSTER, 0 ); + + for (int i=0;i& data, Array2D& points, + Array1D& dens, int ncl, double sfac) +{ + //double pdf_icl; + + const int ndata = data.XSize(); + const int ndim = data.YSize(); + const int npoints=points.XSize();//=dens.XSize(); + + // dimension check + if (ndim != (int) points.YSize()) + {printf("getPdf_cl: dimension error\n"); exit(1);} + + int *bClusterIndex; + bClusterIndex=new int[ndata]; + Array1D sig(ndim,0.e0); + Array1D we(ndata,1.e0); + Array1D point(ndim,0.e0); + + Array1D data_1d(ndata,0.e0); + Array1D w(ndim,1.e0); + for(int idim=0;idim numData(ncl,0); + double bestexpl ; + bestexpl=clust_best(data,w,ncl,numData,bClusterIndex,10); + //clust(data,w,ncl,numData,pClusterIndex); + + + for (int icl=0;icl data_icl(numData(icl),ndim,0.e0); + Array1D dens_icl(npoints,0.e0); + + int jc=0; + for(int i=0;i& x1, Array1D& x2,Array1D& param, string covtype) +{ + + int n=x1.XSize(); + int nn=x2.XSize(); + if (nn!=n ) {printf("Gproc:covariance() : Error message: covariance: matrix dimensions do not match! \n"); exit(1);} + + double cov=0.0; + + if ( covtype == "SqExp" ){ + Array2D B(nn,nn,0.e0); + for(int i=0;i x12; + x12=subtract(x1,x2); + + Array1D Bx12; + prodAlphaMatVec (B, x12, 1.0, Bx12) ; + + cov=exp(-dot(x12,Bx12)); + } + + else if ( covtype == "Exp" ){ + + double absdiff=0.0; + for(int i=0;i &rndnos, const int dfac, dsfmt_t *rnstate) { + + int ns = (int) rndnos.XSize() ; + int ndim = (int) rndnos.YSize() ; + double *rndnosPNT = rndnos.GetArrayPointer() ; + ihsU(ndim, ns, rndnosPNT, dfac, rnstate) ; + +} + +void ihsU(const int ndim, const int ns, double *rndnos, const int dfac, dsfmt_t *rnstate) { + + int *ipos = (int *) malloc( ns*ndim*sizeof(int)) ; + + ihsP(ndim, ns, ipos, dfac, rnstate) ; + for ( int j = 0; j < ndim; j++) + for ( int i = 0; i < ns; i++) + rndnos[j*ns+i] = (((double) ipos[j*ns+i])+dsfmt_genrand_open_open(rnstate))*2.0/((double) ns)-1.0 ; + + free(ipos) ; + + return ; + +} + +void ihsP(const int ndim, const int ns, int *x, const int dupl, dsfmt_t *rnstate) { + + double opt = ns / pow(ns,1.0/ndim) ; + int nsdup = ns * dupl; + int nsdim = ns * ndim; + vector avail(nsdim); + vector point(ndim*nsdup); + + for ( int i=0; i=1; count--) { + vector list1(count * dupl,0); + for (int i=0; i < ndim; i++) { + for (int k=0; k < dupl; k++) + for (int j=0; j < count; j++) + list1[count*k+j]=avail[i*ns+j]; + for (int k=count*dupl-1;k>=0;k--) { + int ptidx = 0; + if (k>0) + ptidx=(dsfmt_genrand_uint32(rnstate) % (k+1)); + point[i*nsdup+k] = list1[ptidx]; + list1[ptidx] = list1[k]; + } + } + + double minall = 1.e30; + int best = 0; + + for (int k=0;k &spl, Array2D &dCor) { + + int nspl = spl.XSize(); + int nvars = spl.YSize(); + //cout< 20000) + printf("Warning ! This might be a lengthy calculation: nspl=%d\n",nspl); + + std::vector< Array2D > As; + for (int i=0; i Amat(nspl,nspl,0.0); + for (int i1=1; i1 Arow, Acol; + getMean(Amat, Arow, "R"); + getMean(Amat, Acol, "C"); + double Amn = get_mean(Arow); + + // subtract/add means (linewise, columnwise, overall) + matPvec(Amat, Arow, -1.0, "R"); + matPvec(Amat, Acol, -1.0, "C"); + addVal(Amat,Amn); + As.push_back(Amat); + } + + Array1D dVarX(nvars,0.0); + for (int i=0; i Atmp = dotmult(As[i],As[i]); + dVarX(i) = sqrt(get_mean(Atmp)); + //printf("%d: %e\n",i,dVarX(i)); + } + + dCor.Resize(nvars,nvars,0.0); + for (int i1=0; i1 Atmp = dotmult(As[i1],As[i2]); + dCor(i1,i2) = sqrt(get_mean(Atmp))/sqrt(dVarX(i1)*dVarX(i2)); + } + + return ; + +} + + diff --git a/cpp/lib/tools/probability.h b/cpp/lib/tools/probability.h new file mode 100644 index 00000000..ceae5825 --- /dev/null +++ b/cpp/lib/tools/probability.h @@ -0,0 +1,148 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/** \file probability.h + * \brief Header for probability and random number generation- related tools. + * \todo There shuold be a RNG class as a part of core UQTk - most of these functions will fit there. + */ + +#ifndef PROBABILITY_H +#define PROBABILITY_H + +#include "Array1D.h" +#include "Array2D.h" + +#define DSFMT_DO_NOT_USE_OLD_NAMES +#include "dsfmt_add.h" + +#include "KCenterClustering.h" +#include "figtree_internal.h" + + +/// \brief An implementation of error function using incomplete gamma function +double erff(const double x); + +/// \brief Inverse error function, input scaled to [-1,1] +/// \note Cephes Math Library Release 2.8: June, 2000. +/// Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier +// The website (http://www.boutell.com/lsm/lsmbyid.cgi/000626) states copying policy=freely distributable as of July 2012 +// \note modified by Sandia UQTk group to scale the input to [-1,1] +double inverf(double y0); + +/// \brief Inverse of the CDF of the normal random variable, uses inverf +double invnormcdf(double y); + +/// \brief Normal random variable CDF +double normcdf(double y); + +/// \brief Complementary function for normcdf +double normcdfc(double y); + +/// \brief Generates a vector of i.i.d. uniform(0,1) random variable samples of size ns*nd, given integer seed +void generate_uniform(double* rvar,int ns, int nd, int zSeed); + +/// \brief Generates a matrix of i.i.d. uniform(0,1) random variable samples, given integer seed +void generate_uniform(Array2D& rvar,int zSeed); + +/// \brief Generates a vector of i.i.d. uniform(0,1) random variable samples of size ns*nd, given pointer to the state of current random number generator +void generate_uniform(double *rvar, int ns, int nd, dsfmt_t *rnstate); + +/// \brief Generates a matrix of i.i.d. uniform(0,1) random variable samples, given pointer to the state of current random number generator +void generate_uniform(Array2D &rvar, dsfmt_t *rnstate); + +/// \brief Generates a vector of i.i.d. uniform(0,1) random variable LHS samples of size ns*nd, given integer seed +void generate_uniform_lhs(double* rvar,int ns, int nd, int zSeed); + +/// \brief Generates a matrix of i.i.d. uniform(0,1) random variable LHS samples, given integer seed +void generate_uniform_lhs(Array2D& rvar,int zSeed); + +/// \brief Generates a vector of i.i.d. uniform(0,1) random variable LHS samples of size ns*nd, given pointer to the state of current random number generator +void generate_uniform_lhs(double *rvar, int ns, int nd, dsfmt_t *rnstate); + +/// \brief Generates a matrix of i.i.d. uniform(0,1) random variable LHS samples, given pointer to the state of current random number generator +void generate_uniform_lhs(Array2D &rvar, dsfmt_t *rnstate); + +/// \brief Generates a matrix of i.i.d. normal(0,1) random variable samples +void generate_normal(Array2D& rvar,int zSeed); + +/// \brief Generates a matrix of i.i.d. normal(0,1) random variable LHS samples +/// \todo LHS generation is far from optimal, it is quite slow +void generate_normal_lhs(Array2D& rvar,int zSeed); + +/// \brief Returns the median of a data array +double get_median(const Array1D& data); + +/// \brief Returns the mean of a 1D data array +double get_mean(const Array1D& data); + +/// \brief Returns the mean of a 2D data array +double get_mean(const Array2D& data); + +/// \brief Returns the std of a data array +double get_std(const Array1D& data); + +/// \brief Returns the std of a data array +double get_var(const Array1D& data); + +/// \brief Vector-mean and weighted variance +double getMean_Variance(Array2D& data_c, Array1D& w, Array1D& mean); + +/// \brief Vector mean, column by column +void getMean(Array2D& data_c, Array1D& mean); + +/// \brief Vector mean, either column by column for RC="C" or +/// row by row for RC="R" +void getMean(Array2D& data_c, Array1D& mean, char *RC); + +/// \brief Random permutation of 0..n-1 +void rperm(int n, int *a, dsfmt_t *rnstate); + +/// \brief KDE estimation of a PDF +void getPdf_figtree(Array2D& source,Array2D& target,Array1D& sig, Array1D& density, Array1D& weight); + +/// \brief Compute the PDF of data at the given points using given +/// number of clusters (if ncl=0, then find the optimal cluster +/// number) and a scale factor for the optimal bandwidth +void getPdf_cl(Array2D& data, Array2D& points, Array1D& dens,int ncl, double sfac); + +/// \brief Compute a few standard covariance functions C(x_1,x_2) +double covariance(Array1D& x1, Array1D& x2,Array1D& param, string covtype); + + +void ihsU(Array2D &rndnos, int dfac, dsfmt_t *rnstate) ; + +void ihsU(int ns, int np, double *rndnos, int dfac, dsfmt_t *rnstate) ; + +void ihsP(int ns, int np, int *rpos, int dfac, dsfmt_t *rnstate); + +/// \brief Compute distance correlation factors given a set of samples +/// (no. of rows in spl) from a collection of random variables (no. of +/// columns in spl). dCor(i,j), with i>j stores the distance +/// correlation values between random variables i and j +void distCorr(const Array2D &spl, Array2D &dCor) ; + +//--------------------------------------------------------------------------------------- +#endif // PROBABILITY_H diff --git a/cpp/lib/tools/rosenblatt.cpp b/cpp/lib/tools/rosenblatt.cpp new file mode 100644 index 00000000..d78098cf --- /dev/null +++ b/cpp/lib/tools/rosenblatt.cpp @@ -0,0 +1,354 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file rosenblatt.cpp +/// \brief Tools related to Rosenblatt transformation +#include +#include +#include +#include "Array1D.h" +#include "Array2D.h" +#include "tools.h" +#include "arraytools.h" + +using namespace std; + +// Implementation of inverse Rosenblatt map given dimension-specific bandwidths +void invRos(Array1D& unif, Array2D& xi, Array1D& newXi, Array1D& sig) +{ + // Accuracy, i.e. the stopping criterion in the bisection algorithm + double xacc=1e-8; + // The initial range of the bisection algorithm [-xmax,xmax] + double xmax = 1.0e+8; + + + // Dimensionality of the transformation + int ndim = unif.XSize(); + int ns = xi.YSize(); + + // Output container + newXi.Resize(ndim,0.e0); + + // Dimension check + if (ndim != (int) xi.XSize() || ndim != (int) sig.XSize()) + {printf("invRos: dimension error\n"); exit(1);} + + + // Work arrays + Array1D kern(ns,1.e0); + Array1D numer(ndim,0.e0); + Array1D denom(ndim,0.e0); + + // Loop over dimensions + for(int id=0; id < ndim; id++){ + + //// including this is equivalent to dropping | conditionals in Rosenblatt transformation + // kern.Resize(ndim,1.e0); + + // Get the corresponding uniform r.v. sample + double Un=unif(id); + + // Starting point of bisection + double xx = 0.0; + + // Cure against extremes + if (Un==0.0) + Un += DBL_EPSILON; + if (Un==1.0) + Un -= DBL_EPSILON; + + // Build denominator + for(int is=0; is < ns; is++) + denom(id) += kern(is); + + // Bisection iteration counter + int ii=0; + + // Bisection looks in the interval [x1,x2] + double x1 = -xmax; + double x2 = xmax; + + // Bisection loop + do{ + + numer(id) = 0 ; + for(int is = 0; is < ns; is++) + numer(id) += (kern(is)/denom(id)) * ( 0.5+0.5*erf( (xx-xi(id,is))/(sqrt(2)*sig(id)) ) ) ;// (xx > xi(id,is)); + + if (Un < numer(id)){ x1 = x1; x2 = xx; } + else { x1 = xx; x2 = x2; } + xx = 0.5*(x1+x2); + ii++; + + } while (fabs(x2-x1) > xacc); + // End of bisection loop + + // Just-in-case warning + if (ii>1000) + printf( "Warning: Inverted CDF in really many (%d) iterations\n", ii); + + // Select the solution as a new sample + newXi(id) = xx; + + // Update the kernel for the next dimension + double sig2 = sig(id)*sig(id); + for(int is=0; is < ns; is++) + kern(is) = kern(is)*exp(-pow(newXi(id)-xi(id,is),2)/(2*sig2)); // (bw*sqrt(2*PI)) cancels; + + } // end of loop over dimensions + + return; + +} + +// Implementation of inverse Rosenblatt map given same bandwidth for all dimensions +void invRos(Array1D& unif, Array2D& xi, Array1D& newXi, double bw) +{ + // Sanity check + if (bw<=0) + {printf("invRos: bandwidth needs to be positive"); exit(1);} + + // Get dimensions + int ndim = unif.XSize(); + + // Dimension check + if (ndim != (int) xi.XSize()) + {printf("invRos: dimension error"); exit(1);} + + // Populate bandwidth vector + Array1D sig(ndim,bw); + + // Perform inverse Rosenblatt + invRos(unif,xi,newXi,sig); + + return; +} + +// Implementation of inverse Rosenblatt map with bandwidths chosen according to a rule-of-thumb +void invRos(Array1D& unif, Array2D& xi, Array1D& newXi) +{ + // Get dimensions + int ndim = unif.XSize(); + const int nr_proj = xi.YSize(); + + // Dimension check + if (ndim != (int) xi.XSize()) + {printf("invRos: dimension error"); exit(1);} + + // Transpose the input for bandwidth selection code + Array2D xi_t(nr_proj,ndim,0.e0); + transpose(xi,xi_t); + + // Get optimal bandwidths for all dimensions + Array1D sig; + get_opt_KDEbdwth(xi_t,sig); + + // Perform inverse Rosenblatt + invRos(unif,xi,newXi,sig); + + return; +} + +// Implementation of inverse Rosenblatt map with bandwidths chosen according to a rule-of-thumb +// operating on a set of uniform samples. +void invRos(Array2D& unif, Array2D& xi, Array2D& newXi) +{ + int npts = unif.XSize(); + int ndim = unif.YSize(); + int nspl = xi.YSize(); + + // dimension check + if (ndim != (int) xi.XSize()) + {printf("invRos: dimension error\n"); exit(1);} + + // Transpose the input for bandwidth selection code + Array2D xi_t(nspl,ndim,0.e0); + transpose(xi,xi_t); + + // Get optimal bandwidths for all dimensions + Array1D sig; + get_opt_KDEbdwth(xi_t,sig); + + // Inverse rosenblatt for each point in unif + Array1D uin(ndim),xiout(ndim); + newXi.Resize(npts,ndim); + for (int is=0; is& data,Array1D& bdwth) +{ + // Get dimensions + int ndata=data.XSize(); + int ndim=data.YSize(); + + // Bandwidth vector container + bdwth.Resize(ndim); + + // Flag that measures proximity to boundary per dimension + Array1D flag(ndim,1.); + + // Initialize minimum and maximum per dimension + Array1D datamin(ndim,1000.0); + Array1D datamax(ndim,-1000.0); + + // Loop over dimensions + for(int idim=0;idimdatamax(idim)) {datamax(idim)=data(idata,idim);} + } + // Define proximity to boundary + double nearBorder=(datamax(idim)-datamin(idim))/20.; + + // Compute the number of samples near boundaries + int numBorder=0; + for(int idata=0;idata ndata/20.) {flag(idim)=0.5;} + } // end loop over dimensions + + // Standard deviation container + Array1D stdd(ndim,0.e0); + + // Auxiliary 1d vector for st-deviation computation + Array1D data_1d(ndata); + + // Loop over dimensions + for(int idim=0;idim& xi, Array2D& xi_data, Array2D& unif, Array1D& sig) +{ + // Get the dimensions + int nsd=xi_data.XSize(); + int ns=xi.XSize(); + int nd=xi.YSize(); + + // Dimension check + if (nd != (int) xi_data.YSize()) + {printf("Rosen: dimension error"); exit(1);} + + // Output samples container + unif.Resize(ns,nd); + + // Loop over samples + for (int js = 0; js < ns; js++) { + + // Setting the 'kernel' for summation + Array1D kern(nsd,1.0); + + // Loop over dimensions + for (int id=0;id& xi, Array2D& xi_data,Array2D& unif, double bw) +{ + // Sanity check + if (bw<=0) + {printf("Rosen: bandwidth needs to be positive"); exit(1);} + + // Get the dimension + int ndim = xi.YSize(); + + // Populate dimension-specific bandwidth vector + Array1D sig(ndim,bw); + + // Perform Rosenblatt map + Rosen(xi,xi_data,unif,sig); + + return; +} + +// Implementation of Rosenblatt map given with optimal dimension-specific bandwidth selection +void Rosen(Array2D& xi,Array2D& xi_data, Array2D& unif) +{ + // Get the dimension + int ndim = xi.YSize(); + + // Compute the optimal bandwidths + Array1D sig; + get_opt_KDEbdwth(xi_data,sig); + + // Perform Rosenblatt map + Rosen(xi,xi_data,unif,sig); + + return; + +} diff --git a/cpp/lib/tools/rosenblatt.h b/cpp/lib/tools/rosenblatt.h new file mode 100644 index 00000000..d90a6ec0 --- /dev/null +++ b/cpp/lib/tools/rosenblatt.h @@ -0,0 +1,80 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +/// \file rosenblatt.h +/// \brief Header for tools related to Rosenblatt transformation +#ifndef ROSENBLATT_H +#define ROSENBLATT_H + + +/// \brief Generates a new sample by inverse Rosenblatt defined by a given sample set (xi) and a 'uniform' sample from the unit hypercube +/// \note Performs inverse Rosenblatt map \f$\xi=R^{-1}(u)\in\mathbf{R}^d\f$ given a single sample of \f$u\in[0,1]^d\f$ +/// \note The command line utility app/pce_quad uses this map; see UQTk Manual entry for the app for technical description of the map +/// \param[in] unif : 1-dimensional array of size \f$d\f$ corresponding to a sample \f$u\in[0,1]^d\f$ +/// \param[in] xi : 2-dimensional array of size \f$d\times M\f$ corresponding to samples that define the target distribution +/// \param[out] newXi : 1-dimensional array of size \f$d\f$ corresponding to a new sample \f$\xi=R^{-1}(u)\in\mathbf{R}^d\f$ +/// \param[in] sig : 1-dimensional array of size \f$d\f$ for dimension-specific KDE bandwidths +void invRos(Array1D& unif, Array2D& xi, Array1D& newXi, Array1D& sig); + +/// \brief This is a version of invRos() with the same bandwidth (bw) for all dimensions +void invRos(Array1D& unif, Array2D& xi, Array1D& newXi, double bw); + +/// \brief This is a version of invRos() with an automatic bandwidth selection based on a rule of thumb. +/// \note The rule of thumb is not always reliable. It is recommended to test various bandwidths. +void invRos(Array1D& unif, Array2D& xi, Array1D& newXi); + +/// \brief This is a version of invRos() with an automatic bandwidth selection based on a rule of thumb, and +/// operating on set of uniform samples (rather than one at a time) +/// \param[in] unif : 2-dimensional array of size \f$N\times d\f$ corresponding to N samples \f$u\in[0,1]^d\f$ (uniform) +/// \param[in] xi : 2-dimensional array of size \f$d\times M\f$ corresponding to samples that define the arbitrary target distribution +/// \param[out] newXi : 2-dimensional array of size \f$N\times d\f$ corresponding to a set of N new samples \f$\xi=R^{-1}(u)\in\mathbf{R}^d\f$ +/// \note The rule of thumb is not always reliable. It is recommended to test various bandwidths. +void invRos(Array2D& unif, Array2D& xi, Array2D& newXi); + +/// \brief Calculates 'rule of thumb' optimal KDE bandwidths for a multi-dimensional data +/// \note Employs Silverman's rule-of-thumb, with a homemade factor adjustment accounting for samples that are near boundaries +/// \note This rule-of-thumb is quite heuristic; use at your own risk +/// \param[in] data : 2-dimensional array of size \f$N\times d\f$ corresponding to samples +/// \param[out] bdwth : 1-dimensional array of size \f$d\f$ for dimension-specific KDE bandwidths +void get_opt_KDEbdwth(const Array2D& data, Array1D& bdwth); + +/// \brief Given input samples (xi), generates uniform samples by Rosenblatt map whose PDF is defined by a given sample set (xi_data) +/// \note Performs Rosenblatt map \f$u=R(\xi)\f$ given multiple samples of \f$\xi\f$ +/// \param[in] xi : 2-dimensional array of size \f$N\times d\f$ for input samples \f$\xi\f$ of the Rosenblatt map +/// \param[in] xi_data : 2-dimensional array of size \f$M\times d\f$ corresponding to samples \f$\xi_d\f$ from PDF defining the Rosenblatt map +/// \param[out] unif : 2-dimensional array of size \f$N\times d\f$ for output samples of the Rosenblatt map; will land in \f$[0,1]^d\f$ if the input \f$\xi\f$ is sampled from the PDF of \f$\xi_d\f$ +/// \param[in] sig : 1-dimensional array of size \f$d\f$ for dimension-specific KDE bandwidths +void Rosen(Array2D& xi, Array2D& xi_data, Array2D& unif, Array1D& sig); + +/// \brief This is a version of Rosen() with the same bandwidth (bw) for all dimensions +void Rosen(Array2D& xi, Array2D& xi_data, Array2D& unif, double bw); + +/// \brief This is a version of Rosen() with an automatic bandwidth selection based on a rule of thumb. +/// \note The rule of thumb is not always reliable. It is recommended to test various bandwidths. +void Rosen(Array2D& xi, Array2D& xi_data, Array2D& unif); + + +#endif // ROSENBLATT_H diff --git a/cpp/lib/tools/tools.h b/cpp/lib/tools/tools.h new file mode 100644 index 00000000..80c53d52 --- /dev/null +++ b/cpp/lib/tools/tools.h @@ -0,0 +1,44 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#ifndef UQTKTOOLS_H +#define UQTKTOOLS_H + +/** \file tools.h + * \brief A header function that includes all tools. + */ + + +#include "probability.h" +#include "combin.h" +#include "minmax.h" +#include "multiindex.h" +#include "pcmaps.h" +#include "gq.h" +#include "rosenblatt.h" +#include "func.h" + +#endif // UQTKTOOLS_H diff --git a/cpp/lib/tools/toolsf.f b/cpp/lib/tools/toolsf.f new file mode 100644 index 00000000..ebebc0cd --- /dev/null +++ b/cpp/lib/tools/toolsf.f @@ -0,0 +1,69 @@ +c$$$===================================================================================== +c$$$ The UQ Toolkit (UQTk) version 3.0.4 +c$$$ Copyright (2017) Sandia Corporation +c$$$ http://www.sandia.gov/UQToolkit/ +c$$$ +c$$$ Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 +c$$$ with Sandia Corporation, the U.S. Government retains certain rights in this software. +c$$$ +c$$$ This file is part of The UQ Toolkit (UQTk) +c$$$ +c$$$ UQTk is free software: you can redistribute it and/or modify +c$$$ it under the terms of the GNU Lesser General Public License as published by +c$$$ the Free Software Foundation, either version 3 of the License, or +c$$$ (at your option) any later version. +c$$$ +c$$$ UQTk is distributed in the hope that it will be useful, +c$$$ but WITHOUT ANY WARRANTY; without even the implied warranty of +c$$$ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +c$$$ GNU Lesser General Public License for more details. +c$$$ +c$$$ You should have received a copy of the GNU Lesser General Public License +c$$$ along with UQTk. If not, see . +c$$$ +c$$$ Questions? Contact Bert Debusschere +c$$$ Sandia National Laboratories, Livermore, CA, USA +c$$$===================================================================================== + subroutine heap_ext(n,isgn,i,j,index) + + implicit none + integer n,isgn,i,j,index + + integer l,l1,n1 + + common /hpwrk/ l,l1,n1 + + if (index) 90,10,80 + 10 n1 = n + l = 1+n/2 + 20 l = l-1 + 30 l1 = l + 40 i = l1+l1 + if (i-n1) 50,60,70 + 50 j = i+1 + index = -2 + return + 60 j = l1 + l1 = i + index = -1 + return + 70 if (l.gt.1) goto 20 + if (n1.eq.1) goto 110 + i = n1 + n1 = n1-1 + j = 1 + index = 1 + return + 80 if (index-1) 30,30,40 + 90 if (index.eq.-1) goto 100 + if (isgn.lt.0) i=i+1 + goto 60 + 100 if (isgn.le.0) goto 70 + index = 2 + return + 110 index = 0 + return + end + + + diff --git a/cpp/lib/xmlutils/CMakeLists.txt b/cpp/lib/xmlutils/CMakeLists.txt new file mode 100644 index 00000000..4d5c0a75 --- /dev/null +++ b/cpp/lib/xmlutils/CMakeLists.txt @@ -0,0 +1,23 @@ + +FILE(GLOB slsrc "*.cpp") + +SET(xml_HEADERS + XMLUtils.h + XMLExpatParser.h + XMLParser.h + XMLElement.h + Object.h + RefPtr.h + MyException.h + XMLAttributeList.h + ) + +add_library(uqtkxmlutils ${slsrc}) + +# Install the library +INSTALL(TARGETS uqtkxmlutils DESTINATION lib) + +# Install the header files +INSTALL(FILES ${xml_HEADERS} DESTINATION include/uqtk) + + diff --git a/cpp/lib/xmlutils/MyException.h b/cpp/lib/xmlutils/MyException.h new file mode 100644 index 00000000..2bfafd9e --- /dev/null +++ b/cpp/lib/xmlutils/MyException.h @@ -0,0 +1,71 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _MyException_ +#define _MyException_ + +#include +#include +#include + +/** + * Just an example exception - feel free to override this. + */ +class MyException : public std::exception { +public: + /// Construct an exception using a C-style character string. + MyException(const char* errormessage) { + std::cerr << "ERROR: " << errormessage << "\n"; + error_ = std::string("MyException: ") + errormessage; + } + + /// Construct an exception using a C++-style string + MyException(const std::string& errormessage) { + std::cerr << "ERROR: " << errormessage << "\n"; + error_ = std::string("MyException: ") + errormessage; + } + + /// Destroy. + virtual ~MyException() throw() { + } + + /// What's going on? + const char* what() const throw() { + try { + return error_.c_str(); + } catch(...) { + ;/// This function is not permitted to throw exceptions. + } + return error_.c_str(); + } + +private: + std::string error_; +}; + +#endif // _MyException_ diff --git a/cpp/lib/xmlutils/Object.h b/cpp/lib/xmlutils/Object.h new file mode 100644 index 00000000..35f31fb5 --- /dev/null +++ b/cpp/lib/xmlutils/Object.h @@ -0,0 +1,78 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _base_class_Object_ +#define _base_class_Object_ + +#include "RefPtr.h" + +/** + * \class Object + * Base class for reference counted objects. + * + * Part of the Particle Simulation Toolkit (pst) + * + * The "friend" classes "RefPtr" and "ConstRefPtr" take care of the + * reference counting and garbage collection. This means that it + * should be safe to create an array of reference counted objects, + * as long as you *do not* assign a reference counted pointer to + * any at the entries in the array at any time. + */ +class Object { + template friend class RefPtr; + template friend class ConstRefPtr; +public: + /// Construct a new reference counted object with a zero reference count + Object() : refs_(0) { + } + + /// Destroy this object + virtual ~Object() { + } + + /// Returns the number of references that are held to this object + long int reference_count() const { + return refs_; + } + +protected: + /// Enables the friends of the class to increment and decrement the + /// reference count. + long int reference_grab() const { + return ++refs_; + } + + long int reference_release() const { + return --refs_; + } + +private: + mutable long int refs_; +}; + +#endif //_utility_ref_Object_ diff --git a/cpp/lib/xmlutils/RefPtr.h b/cpp/lib/xmlutils/RefPtr.h new file mode 100644 index 00000000..ad715a39 --- /dev/null +++ b/cpp/lib/xmlutils/RefPtr.h @@ -0,0 +1,226 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _utility_ref_RefPtr_ +#define _utility_ref_RefPtr_ + +#include "MyException.h" +#include // for dynamic_cast +#include +#include + +/** + * \class RefPtr + * Reference counted pointer that gives the holder + * modification privileges to the pointee. + * + * Part of the Particle Simulation Toolkit (pst) + */ +template +class RefPtr { +public: + /// Make the typename that this pointer holds accessible to other objects. + typedef T Type; + + /// Construct a new RefPtr and initialize the pointee to NULL. + RefPtr() : ptr_(NULL) {} + + /// Construct a new RefPtr and initialize the pointee as given. + RefPtr(T* p) : ptr_(p) { + grab(); + } + + /// Construct a new RefPtr and initialize to the given RefPtr pointee. + RefPtr(const RefPtr& p) : ptr_(p.ptr_) { + grab(); + } + + /// Perform a static cast to initialize this pointee. + /// This cast is only valid if T is a parent class of Other + template + RefPtr(RefPtr p) : ptr_(static_cast(p.pointee())) { + grab(); + } + + /// Destroy this RefPtr. + ~RefPtr() { + release(); + } + + /// Assign the value of this RefPtr to the given pointee. + RefPtr& operator=(T* p) { + if(p != ptr_) { + release(); // release the old pointer + ptr_ = p; // assign our value to this one + grab(); // grab this pointer + } + return *this; + } + + /// Assign the value of this RefPtr to the pointee of the given RefPtr. + RefPtr& operator=(const RefPtr& p) { + if(p.ptr_ != ptr_) { + release(); + ptr_ = p.ptr_; + grab(); + } + return *this; + } + + /// Use dynamic_cast to set the pointee to the + /// pointer that was passed in, and return *this. + /// The returned value is NULL if the cast fails. + template + RefPtr& cast(Other* p) { + if(p != ptr_) { + release(); + + //std::cout << "DEBUG: Dynamic cast from type " << typeid(p).name() + // << " to " << typeid(T).name() << std::endl; + + ptr_ = dynamic_cast(p); + if(p != NULL && ptr_ == NULL) { + throw MyException + (std::string("RefPtr::cast(Other): Failed dynamic cast from ") + + std::string(typeid(Other).name()) + std::string(" to ") + + std::string(typeid(Type).name())); + + } + grab(); + } + return *this; + } + + /// Use dynamic_cast to set the pointee to the + /// pointee of the RefPtr given, and return *this. + /// The returned value is NULL if the cast fails. + template + RefPtr& cast(RefPtr p) { + if(p.ptr_ != ptr_) { + release(); + + //std::cout << "DEBUG: Dynamic cast from type " + // << typeid(p.pointee()).name() + // << " to " << typeid(T).name() << std::endl; + + ptr_ = dynamic_cast(p.pointee()); + if(p != NULL && ptr_ == NULL) { + throw MyException + (std::string("RefPtr::cast(Other): Failed dynamic cast from ") + + std::string(typeid(Other).name()) + std::string(" to ") + + std::string(typeid(Type).name())); + } + grab(); + } + return *this; + } + + /// Return the pointee of this RefPtr. + /// This will throw an exception if the pointee is NULL. + T* operator->() const { + if(ptr_ == NULL) { + std::cerr << "RefPtr<" << typeid(T).name() + << ">::operator->() const invoked on a null pointer\n"; + throw MyException("RefPtr::operator->() const"); + } + return ptr_; + } + + /// Return a reference to the pointee of this RefPtr. + /// This will not work right if the pointee is NULL. + T& operator*() const { + if(ptr_ == NULL) { + std::cerr << "RefPtr<" << typeid(T).name() + << ">::operator*() const invoked on a null pointer\n"; + throw MyException("RefPtr::operator*() const"); + } + return *ptr_; + } + + /// Return the pointee of this RefPtr. + T* pointee() { + return ptr_; + } + + /// Return the pointee of this RefPtr in a const context. + const T* pointee() const { + return ptr_; + } + + /// Compare the pointee of this RefPtr with the given pointer. + bool operator==(const T* p) const { + return ptr_ == p; + } + + /// Compare the value of this pointee with the pointee of the given RefPtr. + bool operator==(const RefPtr& p) const { + return ptr_ == p.pointee(); + } + + /// Test inequality. + bool operator!=(const T* p) const { + return ptr_ != p; + } + + /// Test inequality. + bool operator!=(const RefPtr& p) const { + return ptr_ != p.ptr_; + } + + /// Convenience routine to sort pointer values in standard containers. + inline bool operator<(const RefPtr& p) const { + return ptr_ < p.ptr_; + } + + /// Convenience routine to sort pointer values in standard containers. + template + bool operator<(const RefPtr& p) const { + return ptr_ < p.pointee(); + } + +private: + T* ptr_; + + /// Grab a reference to the current pointee if it is not NULL. + inline void grab() { + if(ptr_ != NULL) + ptr_->reference_grab(); + } + + /// Release the reference to the current pointee if it is not NULL. + /// If this results in the reference count of the pointee dropping to zero, + /// delete the object pointed to. + inline void release() { + if(ptr_ != NULL) { + if(ptr_->reference_release() == 0) + delete ptr_; + } + } +}; + +#endif //_utility_ref_RefPtr_ diff --git a/cpp/lib/xmlutils/XMLAttributeList.cpp b/cpp/lib/xmlutils/XMLAttributeList.cpp new file mode 100644 index 00000000..3db91ab6 --- /dev/null +++ b/cpp/lib/xmlutils/XMLAttributeList.cpp @@ -0,0 +1,377 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// The implementation of a -*-C++-*- attribute list for XML data. + + +#include "XMLAttributeList.h" +#include "MyException.h" +#include +#include +#include + +// Utility routines to convert string to double. +inline double to_double(const std::string& value) { + char* endptr; + double retval = strtod(value.c_str(), &endptr); + // Here you could do some error checking with endptr. + // endptr should point one-past last parsed character. + return retval; +} + +// Utility routine to convert string to int. +inline int to_int(const std::string& value) { + char* endptr; + double retval = strtod(value.c_str(), &endptr); + // Here you could do some error checking with endptr. + // endptr should point one-past last parsed character. + // You could also ensure that retval == int(retval) + // or change the rounding. + return int(retval); +} + +// Utility routine to convert int to string. +// This would be much more classy using the stringstream classes, +// but those are (unfortunately) a little broken in some versions of gcc. +inline std::string to_string(int value) { + char buffer[80]; // unlikely that we'll have more than 80 char int value. + sprintf(buffer, "%i", value); + return std::string(buffer); +} + +// Utility routine to convert double to string. +// Same disclaimer applies as for to_string(int). +inline std::string to_string(double value) { + char buffer[80]; + sprintf(buffer, "%f", value); + return std::string(buffer); +} + +// +// Default constructor. +// +XMLAttributeList::XMLAttributeList() +{} + +// +// Blocked copy constructor. +// +XMLAttributeList::XMLAttributeList(const XMLAttributeList&) : + Object() +{ + throw MyException("XMLAttributList: No copy constructor"); +} + +// +// Destructor. +// +XMLAttributeList::~XMLAttributeList() { +} + +// +// Blocked assignment operator. +// +XMLAttributeList& +XMLAttributeList::operator=(const XMLAttributeList&) { + throw MyException("XMLAttributeList: No assignment operator"); +} + +// +// Get the number of attributes in the list. +// +int XMLAttributeList::size() const { + return attribute_.size(); +} + +// +// Return true if a key is defined. +// +bool XMLAttributeList::has(const std::string& key) const { + return (get_location(key) != end()); +} + +// +// Return the value associated with the given key. +// +const std::string& XMLAttributeList::get(const std::string& key) const { + const_iterator it = get_location(key); + if(it == end()) + throw MyException + (std::string("XMLAttributeList::get: Invalid key \"") + key + "\""); + else + return it->second; + } + +// +// Return the value for the given key or the given default value. +// +std::string XMLAttributeList::get(const std::string& key, + const std::string& def) const +{ + const_iterator it = get_location(key); + if(it == end()) + return def; + else + return it->second; +} + +// +// Get the value for the given key as an integer value. +// +int XMLAttributeList::get_int(const std::string& key) const { + const_iterator it = get_location(key); + if(it == end()) { + throw MyException + (std::string("XMLAttributeList::get_int: Invalid key ") + key); + } + else { + try { + // Unfortunately, the lexical cast to integer is very fragile + // (core dumps on some gcc versions when given a non-integer number). + double temp = to_double(it->second); + return int(temp); + } catch(std::exception&) { + throw MyException(std::string("XMLAttributeList::get_int: ") + + it->second + " is not a valid integer"); + } + } +} + +// +// Get the value for the given key as an integer or return a defaul value. +// +int XMLAttributeList::get_int(const std::string& key, int def) const { + const_iterator it = get_location(key); + if(it == end()) { + return def; + } + else { + try { + return to_int(it->second); + } catch(std::exception&) { + throw MyException(std::string("XMLAttributeList::get_int: \"") + + it->second + "\" is not a valid integer"); + } + } +} + +// +// Get the value for the given key as a real value. +// +double XMLAttributeList::get_double(const std::string& key) const { + const_iterator it = get_location(key); + if(it == end()) { + throw MyException + (std::string("XMLAttributeList::get_double: Invalid key ") + key); + } + else { + try { + return to_double(it->second); + } catch(std::exception&) { + throw MyException(std::string("XMLAttributeList::get_double: \"") + + it->second + "\" is not a valid number"); + } + } +} + +// +// Get the value for the given key as an integer or return a defaul value. +// +double +XMLAttributeList::get_double(const std::string& key, double def) const +{ + const_iterator it = get_location(key); + if(it == end()) { + return def; + } + else { + try { + return to_double(it->second); + } catch(std::exception&) { + throw MyException(std::string("XMLAttributeList::get_double: \"") + + it->second + " is not a valid number"); + } + } +} + +// +// Get the value for the given key as a boolean value. +// +bool XMLAttributeList::get_bool(const std::string& key) const { + const_iterator it = get_location(key); + if(it == end()) + throw MyException + (std::string("XMLAttributeList::get_bool: Invalid key ") + key); + else + return boolean_value(it->second, "get_bool"); +} + +// +// Get the value for the given key as a boolean value or return the default. +// +bool XMLAttributeList::get_bool(const std::string& key, bool def) const { + const_iterator it = get_location(key); + if(it == end()) + return def; + else + return boolean_value(it->second, "get_bool"); +} + +// +// Assign an attribute to the given key. +// +void XMLAttributeList::set(const std::string& key, const std::string& val) +{ + std::string low = key; + //make_lower_case(low); + attribute_[low] = val; +} + +// +// Assign an integer value to the given key. +// +void XMLAttributeList::set_int(const std::string& key, int val) { + std::string low = key; + //make_lower_case(low); + attribute_[low] = to_string(val); +} + +// +// Assign a real value to the given key. +// +void XMLAttributeList::set_double(const std::string& key, double val) { + std::string low = key; + //make_lower_case(low); + // lexical_cast seems to discard almost all my precision here + // so I am using sprintf instead + static const int capacity = 51; + char buf[capacity + 1]; + buf[capacity] = '\0'; + // I would like to make this snprintf, but xlC doesn't like std::snprintf. + sprintf(buf, "%.5e", val); + attribute_[low] = buf; +} + +// +// Assign a boolean value to the given key. +// +void XMLAttributeList::set_bool(const std::string& key, bool val) { + std::string low = key; + make_lower_case(low); + if(val == true) + attribute_[low] = "true"; + else + attribute_[low] = "false"; +} + +// +// Get an iterator to the first element. +// +XMLAttributeList::iterator XMLAttributeList::begin() { + return attribute_.begin(); +} + +// +// Get an iterator past the last element. +// +XMLAttributeList::iterator XMLAttributeList::end() { + return attribute_.end(); +} + +// +// Get an iterator to the first element in a const context. +// +XMLAttributeList::const_iterator XMLAttributeList::begin() const{ + return attribute_.begin(); +} + +// +// Get an iterator past the last element in a const context. +// +XMLAttributeList::const_iterator XMLAttributeList::end() const { + return attribute_.end(); +} + +// +// Private method to convert a std::string to lower case. +// +void XMLAttributeList::make_lower_case(std::string& str) const { + const int length = str.size(); + for(int i = 0; i < length; ++i) + str[i] = tolower(str[i]); +} + +// +// Get the location of the given key. +// Returns end() if the key is not found. +// +XMLAttributeList::iterator +XMLAttributeList::get_location(const std::string& key) +{ + // make sure the key is lower case. (disabled by BD 3/13/08) + std::string low = key; + //make_lower_case(low); + + // find the string. + return attribute_.find(low); +} + +// +// Get the location of the given key in a const context. +// Returns end() if the key is not found. +// +XMLAttributeList::const_iterator +XMLAttributeList::get_location(const std::string& key) const +{ + // make sure the key is lower case. (disabled by BD 3/13/08) + std::string low = key; + //make_lower_case(low); + + // find the string. + return attribute_.find(low); +} + +// +// Return the boolean value of the given string. +// +bool XMLAttributeList::boolean_value(const std::string& str, + const char* where) const +{ + // convert the string to lower case + std::string low = str; + make_lower_case(low); + + // test the string. + if((low == "1") || (low == "true") || (low == "yes")) + return true; + else if((low == "0") || (low == "false") || (low == "no")) + return false; + else + throw MyException(std::string("XMLAttributeList::") + where + + ": The string \"" + str + "\" is not a valid " + + "boolean value"); +} + diff --git a/cpp/lib/xmlutils/XMLAttributeList.h b/cpp/lib/xmlutils/XMLAttributeList.h new file mode 100644 index 00000000..63df6928 --- /dev/null +++ b/cpp/lib/xmlutils/XMLAttributeList.h @@ -0,0 +1,174 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _util_xml_class_XMLAttributeList_ +#define _util_xml_class_XMLAttributeList_ + +#include "Object.h" +#include + +/** + * \class XMLAttributeList + * + * The implementation of a container for XML attributes. + * + * Attributes are stored as key-value pairs, both of which are stored + * as text strings. The keys are stored and handled in a case-sensitive + * manner, whereas the values are stored exactly as given. + * + * The order in which attributes were added is not preserved. + * I am not sure whether this is a problem or not. + * + * Boolean values are a special case. They are treated in a + * case-insensitive manner. True boolean values are returned for + * the strings 'true', 'yes', and non-zero numerical values. False boolean + * values are returned for the strings 'false', 'no', and zero values. + * All other strings are considered unacceptable boolean values. + * + * Written by Helgi Adalsteinsson + * Modified by Bert Debusschere, 3/13/08 to make keys case-sensitive + */ +class XMLAttributeList : public Object { + template friend class RefPtr; + template friend class ConstRefPtr; +public: + /// The container type used to hold the attributes. + typedef std::map< std::string, std::string > Map_t; + + /// The iterator type returned by this implementation. + typedef Map_t::iterator iterator; + typedef Map_t::const_iterator const_iterator; + + /// Construct a blank attribute list. + XMLAttributeList(); + +private: + /// Blocked copy constructor. Throws an exception. + XMLAttributeList(const XMLAttributeList&); + +public: + /// Destroy this list. + virtual ~XMLAttributeList(); + +private: + /// Blocked assignment operator. + /// \throw MyException + XMLAttributeList& operator=(const XMLAttributeList&); + +public: + /// Get the number of attributes in the list. + int size() const; + + /// Return true if the given key is defined. + bool has(const std::string&) const; + + /// Get the attribute associated with the given key. + /// \throw MyException if the key is not defined. + const std::string& get(const std::string&) const; + + /// Get the attribute associated with the given key + /// _or_ return the given default value if the key is not defined. + std::string get(const std::string&, const std::string&) const; + + /// Get the given attribute as an integer value. + /// \throw MyException if the key is not defined. + /// \throw MyException if the value is not a valid integer. + int get_int(const std::string&) const; + + /// Get the given attribute as an integer value + /// _or_ return the given default value if the key is not defined. + /// \throw MyException if the value is set and is not a valid integer. + int get_int(const std::string&, int) const; + + /// Get the given attribute as a real value. + /// \throw MyException if the key is not defined. + /// \throw MyException if the value is not a valid number. + double get_double(const std::string&) const; + + /// Get the given attribute as a real value + /// _or_ return the given default value if the key is not defined. + /// \throw MyException if the value is set and is not a valid number. + double get_double(const std::string&, double) const; + + /// Get the given attribute as a boolean value. + /// \throw MyException if the key is not defined. + /// \throw MyException if the value is not a valid boolean value. + /// True boolean values are "yes", "true", and 'non-zero' numerical values. + /// False boolean values are "no" "false", and 'zero' numerical values. + bool get_bool(const std::string&) const; + + /// Get the given attribute as a boolean value + /// _or_ return the given default value if the key is not defined. + /// \throw MyException if the value is not a valid boolean value. + bool get_bool(const std::string&, bool) const; + + /// Assign a text attribute to the given key. + void set(const std::string&, const std::string&); + + /// Assign an integer value to the given key. + void set_int(const std::string&, int); + + /// Assign a numerical value to the given key. + void set_double(const std::string&, double); + + /// Assign a boolean attribute to the given key. + /// True boolean values are added as "true", false as "false" + void set_bool(const std::string&, bool); + + /// Get an iterator to the first element + iterator begin(); + + /// Get an iterator past the last element. + iterator end(); + + /// Get an iterator to the first element in a const context. + const_iterator begin() const; + + /// Get an iterator past the last element in a const context. + const_iterator end() const; + +private: + /// The attributes. + Map_t attribute_; + + /// Convert a string to lower case (conversion in place). + /// (needed to handle boolean values) + void make_lower_case(std::string&) const; + + /// Get an iterator pointing to the location of the given string. + iterator get_location(const std::string&); + + /// Get an iterator to a location in a const context. + const_iterator get_location(const std::string&) const; + + /// Return the boolean value of the given string. + /// \throw MyException if the string is not a valid boolean value. + bool boolean_value(const std::string&, const char* where) const; +}; + +#endif // _util_xml_class_XMLAttributeList_ diff --git a/cpp/lib/xmlutils/XMLElement.cpp b/cpp/lib/xmlutils/XMLElement.cpp new file mode 100644 index 00000000..b62245bb --- /dev/null +++ b/cpp/lib/xmlutils/XMLElement.cpp @@ -0,0 +1,251 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// The implementation of a -*-C++-*- class to hold xml element data. +// +// Helgi +// Feb. 25, 2002. + +#include "XMLElement.h" +#include "MyException.h" +#include // std::find + + // + // Construct a new node and give it a label. + // + XMLElement::XMLElement(const std::string& lbl) : + Object(), label_(lbl), attributes_(new XMLAttributeList) + {} + + // + // Blocked copy constructor. + // + XMLElement::XMLElement(const XMLElement&) : + Object() + { + throw MyException("XMLElement: Blocked copy constructor"); + } + + // + // Destructor. + // + XMLElement::~XMLElement() { + } + + // + // Blocked assignment operator. + // + XMLElement& XMLElement::operator=(const XMLElement&) { + throw MyException("XMLElement: Blocked assignment operator"); + } + + // + // Get the label of this node. + // + const std::string& XMLElement::label() const { + return label_; + } + + // + // Assign a new label to this node. + // + void XMLElement::set_label(const std::string& lbl) { + label_ = lbl; + } + + // + // Return the number of attributes held by this element. + // + int XMLElement::count_attributes() const { + return attributes_->size(); + } + + // + // Return the attribute list held by this element. + // + RefPtr XMLElement::attributes() { + return attributes_; + } + + // + // Assign an attribute list to this element. + // + void XMLElement::set_attributes(RefPtr att) { + attributes_ = att; + } + + // + // Return the number of children held by this element. + // + int XMLElement::count_children() const { + return children_.size(); + } + + // + // Get the child vertex with the given index. + // + RefPtr XMLElement::get_child(int index) { + if(index < 0 || index >= int(children_.size())) + throw MyException("XMLElement::get_child: Invalid index"); + else + return children_[index]; + } + + // + // Get the first instance of a child with the given label + // + RefPtr XMLElement::get_child(const std::string& lbl) { + // Couldn't quite figure out how to easily create a predicate w/o first becoming an + // expert in the STL, so I programmed a simple search algorithm myself... + //child_iterator index = std::find_if(children_.begin(), children_.end(), predicate ); + + bool done = 0; + int index = 0; + while(!done && index < int(children_.size())){ + if(strcmp(children_[index]->label().c_str(),lbl.c_str())==0){ + done=1; + } else { + index++; + } + } + + if(!done) + throw MyException("XMLElement::get_child: child label not found"); + else + return children_[index]; + } + + // + // Add a child vertex to this node. + // + void XMLElement::add_child(RefPtr kid) { + // first, make sure that this element is not a current child. + // Note, this checks whether a given pointer value has already been stored, + // not whether a child with a given label has been stored. Child labels do not + // have to be unique + if(std::find(children_.begin(), children_.end(), kid) != children_.end()) + return; + + // make sure the kid is not a NULL pointer. + if(kid == NULL) + throw MyException("XMLElement::add_child: NULL pointer given."); + // make sure we are not adding this vertex as a kid. + if(kid == this) + throw MyException + ("XMLElement::add_child: Can't add self as child."); + + // and, finally, make sure we don't have a cyclic relationship. + std::set< RefPtr > seen; + recurse(kid, seen); + + // If we get here, it is safe to add the child vertex. + children_.push_back(kid); + } + + // + // Add a non-unique child vertex to this node. + // + void XMLElement::add_child_rpt(RefPtr kid) { + // The same as add_child, only it allows repeating children (Kh.S. July, 2010) + + + // make sure the kid is not a NULL pointer. + if(kid == NULL) + throw MyException("XMLElement::add_child: NULL pointer given."); + // make sure we are not adding this vertex as a kid. + if(kid == this) + throw MyException + ("XMLElement::add_child: Can't add self as child."); + + // and, finally, make sure we don't have a cyclic relationship. + std::set< RefPtr > seen; + recurse(kid, seen); + + // If we get here, it is safe to add the child vertex. + children_.push_back(kid); + } + + + // + // Clear all children from this element. + // + void XMLElement::clear_children() { + children_.clear(); + } + + // + // Return the number of lines of content held by this element. + // + int XMLElement::count_content() const { + return content_.size(); + } + + // + // Return the content line with the given index. + // + const std::string& XMLElement::get_content_line(int index) { + if(index < 0 || index >= int(content_.size())) + throw MyException("XMLElement::get_content_line: Invalid index."); + else + return content_[index]; + } + + // + // Add a line of content. + // + void XMLElement::add_content_line(const std::string& text) { + content_.push_back(text); + } + + // + // Clear all the content lines. + // + void XMLElement::clear_content() { + content_.clear(); + } + + // + // Private routine to ensure that we don't have a cyclic relationship. + // + void XMLElement::recurse(RefPtr kid, + std::set< RefPtr > seen) { + // Only step on each node once. + if(seen.find(kid) != seen.end()) + return; + + // If this element has been seen before, we have a cyclic graph. + // The same holds true if this element is the same as the current element. + if(kid == this) + throw MyException(std::string("XMLElement::add_child: Adding ") + + "this vertex would yield a cyclic relationship"); + + // add this kid to the set + seen.insert(kid); + + int offspring = kid->count_children(); + for(int i = 0; i < offspring; ++i) + recurse(kid->get_child(i), seen); + } diff --git a/cpp/lib/xmlutils/XMLElement.h b/cpp/lib/xmlutils/XMLElement.h new file mode 100644 index 00000000..ac902a4d --- /dev/null +++ b/cpp/lib/xmlutils/XMLElement.h @@ -0,0 +1,158 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _util_xml_class_XMLElement_ +#define _util_xml_class_XMLElement_ + +#include "Object.h" +#include "XMLAttributeList.h" +#include +#include + +/** + * \class XMLElement + * + * This is the implementation of a node in an XML parse tree. + * Each node contains the following three containers, any (or all) of which + * may be empty. + * + * attributes (XMLAttributeList): Contains attributes (key/value pairs). + * children (Vector): Contains children of this node. + * content (Vector): Contains content (text) data. + * + * The implementation is very limited. In particular, the following + * advanced features are missing: + * + * encoding: Support for character types other than char/std::string. + * comments: Allowing comment blocks to accompany each element. + * other xml types (control statements, etc.). + * + * This implementation is heavily based on Kevin Long's XMLObject. + */ +class XMLElement : public Object { + template friend class RefPtr; + template friend class ConstRefPtr; +public: + /// Construct a new xml element object and give it a label. + XMLElement(const std::string&); + +private: + /// Blocked copy constructor. + /// \throw MyException. + XMLElement(const XMLElement&); + +public: + /// Destructor. + virtual ~XMLElement(); + +private: + /// Blocked assignment operator. + /// \throw MyExcepiton. + XMLElement& operator=(const XMLElement&); + +public: + /// Get the label of this node. + const std::string& label() const; + + /// Assign a new label to this node. + void set_label(const std::string&); + + /// Utility function to check how many attributes this element has. + /// This amounts to the same as calling '.attributes().size()' + int count_attributes() const; + + /// Get access to the attribute list. + RefPtr attributes(); + + /// Assign an attribute list to this element. + void set_attributes(RefPtr); + + /// Utility function to check how many children this element has. + int count_children() const; + + /// Get the child with the given index. + /// \throw MyException if the index is invalid. + RefPtr get_child(int); + + /// Find the first instance of a child with a given + /// label and return a pointer to it. + /// \note Since child labels do not need to be unique, there may + /// be multiple instances matching children + /// \throw MyException if the child label can not be found + /// \todo Make this more elegant with the STL find_if function + RefPtr get_child(const std::string&); + + /// Add a child to the back of the list. + /// Ignored if the child is already in the list. + /// \throw MyException if adding the child would + /// result in a cyclic relationship. + /// \throw MyException if the child holds a NULL pointer. + void add_child(RefPtr); + + /// Same as add_child, but this allows for repeating children + void add_child_rpt(RefPtr); + + /// Erase all child elements from this node. + void clear_children(); + + /// Utility function to check how many lines of text content + /// are associated with this element. + int count_content() const; + + /// Get a line of content by index. + /// \throw MyException if the index is out of range. + const std::string& get_content_line(int); + + /// Add a line of content. + void add_content_line(const std::string&); + + /// Clear all text content. + void clear_content(); + + /// The iterator type returned for list of children + //typedef std::vector< RefPtr >::iterator child_iterator; + +private: + /// The label of this element. + std::string label_; + + /// The list of attributes associated with this element. + RefPtr attributes_; + + /// The list of children associated with this element. + std::vector< RefPtr > children_; + + /// The list of content associated with this element. + std::vector content_; + + /// A private routine called recursively to ensure that we don't + /// have a cyclic relationship. + void recurse(RefPtr, std::set< RefPtr >); +}; + +#endif // _util_xml_class_XMLElement_ diff --git a/cpp/lib/xmlutils/XMLExpatParser.cpp b/cpp/lib/xmlutils/XMLExpatParser.cpp new file mode 100644 index 00000000..a4b069f4 --- /dev/null +++ b/cpp/lib/xmlutils/XMLExpatParser.cpp @@ -0,0 +1,232 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// The implementation part of a -*-C++-*- class +// that uses Expat to parse an XML file. +// +// Helgi +// March 11, 2002. + +#include "XMLExpatParser.h" +#include "MyException.h" +#include +#include + +// Utility routine to convert int to string. +// This would be much more classy using the stringstream classes, +// but those are (unfortunately) a little broken in some versions of gcc. +inline std::string to_string(int value) { + char buffer[80]; // unlikely that we'll have more than 80 char int value. + sprintf(buffer, "%i", value); + return std::string(buffer); +} + +// +// Construct a new Expat parser. +// +XMLExpatParser::XMLExpatParser() : + XMLParser(), parser_(NULL) +{ + init(); +} + +// +// Blocked copy constructor. +// +XMLExpatParser::XMLExpatParser(const XMLExpatParser&) : + Object(), XMLParser() +{ + throw MyException("XMLExpatParser: No copy constructor."); +} + +// +// Destructor. Hopefully, this is exception safe enough. +// +XMLExpatParser::~XMLExpatParser() throw() { + try { + XML_ParserFree(parser_); } catch(...) { + ; // ignore exceptions at this point. + } +} + +// +// Blocked copy constructor. +// +XMLExpatParser& XMLExpatParser::operator=(const XMLExpatParser&) { + throw MyException("XMLExpatParser: No assignment operator"); +} + +// +// Parse the given buffer and return a parse tree. +// +RefPtr XMLExpatParser::parse(std::istream& buf) { + //std::cerr << "XMLExpatParser::parse\n"; + + int line_number = 0; + bool done = false; + std::string line; + while(! done) { + getline(buf, line); + + done = !(buf.good()); + ++line_number; + + //std::cerr << "XMLExpatParser: line = \"" << line << "\ : done = " + // << done << "\n"; + + if(XML_Parse(parser_, line.c_str(), line.length(), done) == 0) { + // we only get here if we had a parse error + std::cerr << "Parse error on \"" << line << "\": done = " + << done << "\n"; + + throw MyException + (std::string("XMLExpatParser::parse: \"") + + XML_ErrorString(XML_GetErrorCode(parser_)) + + "\" on line number " + to_string(line_number)); + } + } + + // Return a parse tree and clear the data from this class. + if(path_.size() < 1) + throw MyException("XMLExpatParser::parse: No XML data found."); + // I am not dealing with path_.size() > 1, which would indicate that + // some tags were left unclosed. These tags are automatically matched. + + RefPtr ret = path_[0]; + path_.clear(); + init(); + + return ret; +} + +// +// Parse a start tag. +// +void XMLExpatParser::do_start(const XML_Char* lbl, const XML_Char** attr) +{ + //std::cerr << "XMLExpatParser::do_start \"" << lbl << "\"\n"; + + // Construct a new element to contain this info. + RefPtr leaf = new XMLElement(lbl); + for(int i = 0; attr[i] != NULL; i += 2) + leaf->attributes()->set(attr[i], attr[i+1]); + + // Make sure we keep track of the path we have taken so far. + if(path_.size() == 0) { + path_.push_back(leaf); + } + else { + // add this node as a child of the most recently parsed node. + path_.back()->add_child(leaf); + path_.push_back(leaf); + } +} + +// +// Parse an end tag. +// +void XMLExpatParser::do_end(const XML_Char* /*lbl*/) { + //std::cerr << "XMLExpatParser::do_end \"" << lbl << "\"\n"; + + // We don't really need to check that the tags match up (expat does that). + if(path_.size() > 1) { + // we don't want to pop the top node (which is when path_.size() == 1). + path_.pop_back(); + } +} + +// +// Parse character data (content). +// The content string is not NULL-terminated. +// +void XMLExpatParser::do_character_data(const XML_Char* data, int size) { + //std::cerr << "XMLExpatParser::do_character_data\n"; + + // This should never happen. + if(path_.size() < 1 || size < 0) { + throw MyException + ("XMLExpatParser::parse: Character data with no node."); + } + + // Skip lines that contain only spaces and newline + static const char* blank = " \t\n\r"; + std::string str(data, size); + size_t first_char = str.find_first_not_of(blank); + if(size != 0 && first_char != std::string::npos) { + size_t last_char = str.find_last_not_of(blank); + if(last_char != std::string::npos && last_char > first_char) { + str = str.substr(first_char, last_char); + path_.back()->add_content_line(str); + } + } +} + +// +// Initialize the parser. +// +void XMLExpatParser::init() { + // Unfortunately, the parser doesn't seem to clean up its state fully. + if(parser_ != NULL) + XML_ParserFree(parser_); + + // Build the parser + parser_ = XML_ParserCreate(NULL); + // Associate the parser with this object. + XML_SetUserData(parser_, this); + // Set up the 'start' and 'end' methods. + XML_SetElementHandler(parser_, + &XMLExpatParser::start_, + &XMLExpatParser::end_); + // Set up the character data handler. + XML_SetCharacterDataHandler(parser_, &XMLExpatParser::character_data_); +} + +// +// Static wrapper method to perform callback on 'start' tags. +// +void XMLExpatParser::start_(void* object, + const XML_Char* label, + const XML_Char** attributes) +{ + ( (XMLExpatParser*)object )->do_start(label, attributes); +} + +// +// Static wrapper method to perform callback on 'end' tags. +// +void XMLExpatParser::end_(void* object, const XML_Char* label) { + ( (XMLExpatParser*)object )->do_end(label); +} + +// +// Static wrapper method to perform callback on character data. +// +void XMLExpatParser::character_data_(void* object, + const XML_Char* data, + int size) +{ + ( (XMLExpatParser*)object )->do_character_data(data, size); +} diff --git a/cpp/lib/xmlutils/XMLExpatParser.h b/cpp/lib/xmlutils/XMLExpatParser.h new file mode 100644 index 00000000..1eceb883 --- /dev/null +++ b/cpp/lib/xmlutils/XMLExpatParser.h @@ -0,0 +1,110 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _util_xml_class_XMLExpatParser_ +#define _util_xml_class_XMLExpatParser_ + +#include "XMLParser.h" +#include +#include +#include + +/** + * An XML parser that uses the Expat library to handle the gruntwork. + * This class requires that the Expat be installed on your system. + * + * Expat is available + * at the Expat site + * + * This class may not be fully exception safe, since there is no + * good way of enforcing that the Expat parser is destroyed cleanly. + */ +class XMLExpatParser : public XMLParser { + template friend class RefPtr; + template friend class ConstRefPtr; +public: + /// Construct a new parser. + XMLExpatParser(); + +private: + /// Blocked copy constructor. It is not safe to copy this object + /// since the Expat parser may save state which cannot be duplicated. + XMLExpatParser(const XMLExpatParser&); + +public: + /// Destructor. + virtual ~XMLExpatParser() throw(); + +private: + /// Blocked assignment operator. Not for public consumption. + XMLExpatParser& operator=(const XMLExpatParser&); + +public: + /// Parse the given input buffer and return a parse tree. + RefPtr parse(std::istream&); + +private: + /// The Expat parser. + XML_Parser parser_; + + /// The path that we have traversed so far in building the tree. + std::vector< RefPtr > path_; + + /// The current leaf of the parse tree. + RefPtr leaf_; + + /// The method used to parse the start tag. + void do_start(const XML_Char*, const XML_Char**); + + /// The method used to parse the end tag. + void do_end(const XML_Char*); + + /// The method used to parse character (content) data. + void do_character_data(const XML_Char*, int); + + /// Initialize the state of the parser. + void init(); + +public: + /// Static wrapper method used as a callback to get the 'start' tag. + /// This method is for internal use only. Calling this method + /// directly will most likely result in a segmentation fault. + static void start_(void*, const XML_Char*, const XML_Char**); + + /// Static wrapper method used as a callback to get the 'end' tag. + /// This method is for internal use only. Calling this method + /// directly will most likely result in a segmentation fault. + static void end_(void*, const XML_Char*); + + /// Static wrapper method used as a callback to get character data. + /// This method is for internal use only. Calling this method + /// directly will most likely result in a segmentation fault. + static void character_data_(void*, const XML_Char*, int); +}; + +#endif // _util_xml_class_XMLExpatParser_ diff --git a/cpp/lib/xmlutils/XMLParser.cpp b/cpp/lib/xmlutils/XMLParser.cpp new file mode 100644 index 00000000..a89edbf6 --- /dev/null +++ b/cpp/lib/xmlutils/XMLParser.cpp @@ -0,0 +1,43 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// The implementation part of a pure abstract XML parser class in -*-C++-*- + +#include "XMLParser.h" + +// +// Default constructor. +// +XMLParser::XMLParser() : + Object() +{} + +// +// Destructor. +// +XMLParser::~XMLParser() { +} + diff --git a/cpp/lib/xmlutils/XMLParser.h b/cpp/lib/xmlutils/XMLParser.h new file mode 100644 index 00000000..4d0db0cb --- /dev/null +++ b/cpp/lib/xmlutils/XMLParser.h @@ -0,0 +1,55 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +// -*- C++ -*- + +#ifndef _util_xml_class_XMLParser_ +#define _util_xml_class_XMLParser_ + +#include "XMLElement.h" +#include + +/** + * \class XMLParser + * A pure abstract base class for parsers that read data from + * an XML file and return the top node of a parse tree. + * The parse tree node is a RefPtr< XMLElement >. + */ +class XMLParser : virtual public Object { + template friend class RefPtr; + template friend class ConstRefPtr; +public: + /// Default constructor. Intended for derived classes. + XMLParser(); + + /// Destructor. + virtual ~XMLParser(); + + /// Parse the given input buffer and return the parse tree. + virtual RefPtr parse(std::istream&) = 0; +}; + +#endif // _util_xml_class_XMLParser_ diff --git a/cpp/lib/xmlutils/XMLUtils.cpp b/cpp/lib/xmlutils/XMLUtils.cpp new file mode 100644 index 00000000..94d0aa5a --- /dev/null +++ b/cpp/lib/xmlutils/XMLUtils.cpp @@ -0,0 +1,57 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include "XMLUtils.h" + +// +// Dump out XML tree to a file or output stream +// +void dump_xml_tree(RefPtr tree, const std::string& indentation,std::ostream& outfile) { + // Print the 'header' for this node. + outfile << indentation << "<" << tree->label(); + + // Dump all attributes associated with this node. + RefPtr att = tree->attributes(); + XMLAttributeList::iterator it, end = att->end(); + for(it = att->begin(); it != end; ++it) + outfile << " " << it->first << "=\"" << it->second << "\""; + + if(tree->count_children() == 0) { + // If this node has no children, we're done. + outfile << " />\n"; + } + else { + // ... otherwise, we recursively dump all the child nodes. + outfile << ">\n"; + int children = tree->count_children(); + std::string new_indent = indentation + " "; + for(int kid = 0; kid < children; ++kid) + dump_xml_tree(tree->get_child(kid), new_indent, outfile); + // .. and print the closing bracket for this element. + outfile << indentation << "label() << ">\n"; + } +} + diff --git a/cpp/lib/xmlutils/XMLUtils.h b/cpp/lib/xmlutils/XMLUtils.h new file mode 100644 index 00000000..0c837991 --- /dev/null +++ b/cpp/lib/xmlutils/XMLUtils.h @@ -0,0 +1,31 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include "XMLExpatParser.h" +#include + +/// \brief Recursively dump XML tree to an output file or stream +void dump_xml_tree(RefPtr , const std::string& ,std::ostream& ); diff --git a/cpp/tests/Array1DMiscTest/CMakeLists.txt b/cpp/tests/Array1DMiscTest/CMakeLists.txt new file mode 100644 index 00000000..5b078041 --- /dev/null +++ b/cpp/tests/Array1DMiscTest/CMakeLists.txt @@ -0,0 +1,56 @@ +project (UQTk) + +add_executable (Array1DMiscTest main.cpp) + +target_link_libraries (Array1DMiscTest uqtk ) + +target_link_libraries (Array1DMiscTest depdsfmt ) +target_link_libraries (Array1DMiscTest depcvode ) +target_link_libraries (Array1DMiscTest depnvec ) +target_link_libraries (Array1DMiscTest depslatec) +target_link_libraries (Array1DMiscTest deplapack) +target_link_libraries (Array1DMiscTest depblas ) +target_link_libraries (Array1DMiscTest deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (Array1DMiscTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (Array1DMiscTest ifcore ifport) + else() + target_link_libraries (Array1DMiscTest ${IntelLibPath}/libifcore.a) + target_link_libraries (Array1DMiscTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (Array1DMiscTest gfortran stdc++) + else() + target_link_libraries (Array1DMiscTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS Array1DMiscTest DESTINATION bin/tests/) + +add_test(Array1DMiscTest Array1DMiscTest) diff --git a/cpp/tests/Array1DMiscTest/main.cpp b/cpp/tests/Array1DMiscTest/main.cpp new file mode 100644 index 00000000..096902b0 --- /dev/null +++ b/cpp/tests/Array1DMiscTest/main.cpp @@ -0,0 +1,101 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /********************************** + Read and write 1D Array + *********************************/ + + int dim = 3; + + // Create dim-D array with all ones + Array1D x(dim,1); + + // Write array to file + write_datafile_1d(x,"x.dat"); + + // create dim-D array of zeros + Array1D y(dim,0); + + // read in data file to y + read_datafile_1d(y,"x.dat"); + + /********************************** + Fill in normal r.v.'s to 1D Array + *********************************/ + + // Feed in normal random numbers to array + dsfmt_t RandomState; + int seed = 1; + dsfmt_init_gen_rand(&RandomState,seed); + for (int i = 0; i < dim; i++){ + x(i) = dsfmt_genrand_nrv(&RandomState); + } + + // Write array to file + write_datafile_1d(x,"x_nrv.dat"); + + /********************************** + Elementary operations on arrays + *********************************/ + + // add two arrays and print output + Array1D z = add(x,y); + printarray(z); + + // multiply array by scalar and print output + z = scale(z,3.14159); + printarray(z); + + // dot product of array + double a = dot(z,z); + cout << a << endl; + + // delete ith element of array + z.erase(1); + printarray(z); + + // add element to end of array + z.PushBack(1); + printarray(z); + + return 0; + +} diff --git a/cpp/tests/Array2DMiscTest/CMakeLists.txt b/cpp/tests/Array2DMiscTest/CMakeLists.txt new file mode 100644 index 00000000..e02fc2c2 --- /dev/null +++ b/cpp/tests/Array2DMiscTest/CMakeLists.txt @@ -0,0 +1,56 @@ +project (UQTk) + +add_executable (Array2DMiscTest main.cpp) + +target_link_libraries (Array2DMiscTest uqtk ) + +target_link_libraries (Array2DMiscTest depdsfmt ) +target_link_libraries (Array2DMiscTest depcvode ) +target_link_libraries (Array2DMiscTest depnvec ) +target_link_libraries (Array2DMiscTest depslatec) +target_link_libraries (Array2DMiscTest deplapack) +target_link_libraries (Array2DMiscTest depblas ) +target_link_libraries (Array2DMiscTest deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (Array2DMiscTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (Array2DMiscTest ifcore ifport) + else() + target_link_libraries (Array2DMiscTest ${IntelLibPath}/libifcore.a) + target_link_libraries (Array2DMiscTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (Array2DMiscTest gfortran stdc++) + else() + target_link_libraries (Array2DMiscTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS Array2DMiscTest DESTINATION bin/tests/) + +add_test(Array2DMiscTest Array2DMiscTest) diff --git a/cpp/tests/Array2DMiscTest/main.cpp b/cpp/tests/Array2DMiscTest/main.cpp new file mode 100644 index 00000000..a3b2c791 --- /dev/null +++ b/cpp/tests/Array2DMiscTest/main.cpp @@ -0,0 +1,128 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /********************************** + Read and write 1D Array + *********************************/ + + int m = 3; + int n = 3; + + // Create nxm array with all ones + Array2D A(m,n,1); + + // Write array to file + write_datafile(A,"A.dat"); + + // create dim-D array of zeros + Array2D B(m,n,0); + + // read in data file to B + read_datafile(B,"A.dat"); + + /********************************** + Fill in normal r.v.'s to 1D Array + *********************************/ + + // Feed in uniform random numbers to array + dsfmt_t RandomState; + int seed = 1; + dsfmt_init_gen_rand(&RandomState,seed); + for (int i = 0; i < m; i++){ + for (int j = 0; j < n; j++){ + A(i,j) = dsfmt_genrand_urv(&RandomState); + } + } + + // Write array to file + write_datafile(A,"A_nrv.dat"); + cout << "\nA : " << endl; + printarray(A); + + /********************************* + Linaer alg. operations on arrays + ********************************/ + + // matrix vector product + Array1D x(3,1); + Array1D b = dot(A,x); + cout << "\nb = " << endl; + printarray(b); + + // print transpose + Array2D AT = Trans(A); + cout << "\nTranspose:" << endl; + printarray(AT); + + // get inverse of square matrix A + if ( n == m){ + Array2D Ainv = INV(A); + cout << "\nA inverse:" << endl; + printarray(Ainv); + } + + // get least squares solution + x.Resize(3,0); + LSTSQ(A,b,x); + cout << "\nleast squares solution:" << endl; + printarray(x); + + // get QR factorization + Array2D Q,R; + QR(A,Q,R); + cout << "\nQ:" << endl; + printarray(Q); + cout << "\nR:" << endl; + printarray(R); + + // get SVD factorization + Array2D U,VT; + Array1D S; + SVD(A,U,S,VT); + cout << "\nU:" << endl; + printarray(U); + cout << "\nS:" << endl; + printarray(S); + cout << "\nVT:" << endl; + printarray(VT); + + +} diff --git a/cpp/tests/ArrayDelColumn/CMakeLists.txt b/cpp/tests/ArrayDelColumn/CMakeLists.txt new file mode 100644 index 00000000..2349d98c --- /dev/null +++ b/cpp/tests/ArrayDelColumn/CMakeLists.txt @@ -0,0 +1,55 @@ +project (UQTk) + +add_executable (ArrayDelColumn main.cpp) + +target_link_libraries (ArrayDelColumn uqtk ) + +target_link_libraries (ArrayDelColumn depdsfmt ) +target_link_libraries (ArrayDelColumn depcvode ) +target_link_libraries (ArrayDelColumn depnvec ) +target_link_libraries (ArrayDelColumn depslatec) +target_link_libraries (ArrayDelColumn deplapack) +target_link_libraries (ArrayDelColumn depblas ) +target_link_libraries (ArrayDelColumn deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (ArrayDelColumn gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (ArrayDelColumn ifcore) + else() + target_link_libraries (ArrayDelColumn ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (ArrayDelColumn gfortran stdc++) + else() + target_link_libraries (ArrayDelColumn ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS ArrayDelColumn DESTINATION bin/tests/) + +add_test(ArrayDelColumn ArrayDelColumn) diff --git a/cpp/tests/ArrayDelColumn/main.cpp b/cpp/tests/ArrayDelColumn/main.cpp new file mode 100644 index 00000000..9f94ea9b --- /dev/null +++ b/cpp/tests/ArrayDelColumn/main.cpp @@ -0,0 +1,74 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + + /************************************************* + Array2D Test + This test deletes the last column from a 2d array + *************************************************/ + // create empty 1D array + int m = 100; + int n = 3; + Array2D x2d(m,n,0); + + // fill in with uniform random numbers + dsfmt_t RandomState2; // define state + int seed2 = 10; + dsfmt_init_gen_rand(&RandomState2,seed2); + for (int i = 0; i < m; i++){ + for (int j = 0; j < n; j++){ + x2d(i,j) = dsfmt_genrand_urv(&RandomState2); + } + } + + // write array to file + write_datafile(x2d,"array2d.txt"); + + // delete last column of 2d array + Array2D y2d = mtxdel(x2d,2,1); + assert(y2d.YSize() == n-1); + + return 0; + +} diff --git a/cpp/tests/ArrayReadAndWrite/CMakeLists.txt b/cpp/tests/ArrayReadAndWrite/CMakeLists.txt new file mode 100644 index 00000000..b12717ea --- /dev/null +++ b/cpp/tests/ArrayReadAndWrite/CMakeLists.txt @@ -0,0 +1,55 @@ +project (UQTk) + +add_executable (ArrayReadAndWrite main.cpp) + +target_link_libraries (ArrayReadAndWrite uqtk ) + +target_link_libraries (ArrayReadAndWrite depdsfmt ) +target_link_libraries (ArrayReadAndWrite depcvode ) +target_link_libraries (ArrayReadAndWrite depnvec ) +target_link_libraries (ArrayReadAndWrite depslatec) +target_link_libraries (ArrayReadAndWrite deplapack) +target_link_libraries (ArrayReadAndWrite depblas ) +target_link_libraries (ArrayReadAndWrite deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (ArrayReadAndWrite gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (ArrayReadAndWrite ifcore) + else() + target_link_libraries (ArrayReadAndWrite ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (ArrayReadAndWrite gfortran expat stdc++) + else() + target_link_libraries (ArrayReadAndWrite ${ClangLibPath}/libgfortran.dylib expat ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS ArrayReadAndWrite DESTINATION bin/tests/) + +add_test(ArrayReadAndWrite ArrayReadAndWrite) diff --git a/cpp/tests/ArrayReadAndWrite/main.cpp b/cpp/tests/ArrayReadAndWrite/main.cpp new file mode 100644 index 00000000..2ef8667e --- /dev/null +++ b/cpp/tests/ArrayReadAndWrite/main.cpp @@ -0,0 +1,100 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /************************************************* + Array1D Test + *************************************************/ + // create empty 1D array + int N = 100; + Array1D x(N,0); + + // fill in with integer variables + for (int i = 0; i < N; i++){ + x(i) = i; + } + + // write array to file + write_datafile_1d(x,"array1d.txt"); + + // read back data file + Array1D xnew(N,0); + read_datafile_1d(xnew,"array1d.txt"); + + // check to make sure xnew is right + for (int i = 0; i < N; i++){ + assert(xnew(i) == i); + } + + + /************************************************* + Array2D Test + *************************************************/ + // create empty 1D array + int m = 100; + int n = 3; + Array2D x2d(m,n,0); + + // fill in with uniform random numbers + for (int i = 0; i < m; i++){ + for (int j = 0; j < n; j++){ + x2d(i,j) = i*j; + } + } + + // write array to file + write_datafile(x2d,"array2d.txt"); + + Array2D y2d(m,n); + read_datafile(y2d,"array2d.txt"); + + // check to make sure y2d is right + for (int i = 0; i < m; i++){ + for (int j = 0; j < n; j++){ + assert(y2d(i,j) == i*j); + } + } + + return 0; + +} diff --git a/cpp/tests/ArraySortTest/CMakeLists.txt b/cpp/tests/ArraySortTest/CMakeLists.txt new file mode 100644 index 00000000..6b1a5880 --- /dev/null +++ b/cpp/tests/ArraySortTest/CMakeLists.txt @@ -0,0 +1,59 @@ +project (UQTk) + +add_executable (ArraySortTest main.cpp) + +target_link_libraries (ArraySortTest uqtk ) + +target_link_libraries (ArraySortTest depdsfmt ) +target_link_libraries (ArraySortTest depcvode ) +target_link_libraries (ArraySortTest depnvec ) +target_link_libraries (ArraySortTest depslatec) +target_link_libraries (ArraySortTest deplapack) +target_link_libraries (ArraySortTest depblas ) +target_link_libraries (ArraySortTest deplbfgs ) +target_link_libraries (ArraySortTest depfigtree ) +target_link_libraries (ArraySortTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (ArraySortTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (ArraySortTest ifcore) + else() + target_link_libraries (ArraySortTest ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (ArraySortTest gfortran stdc++) + else() + target_link_libraries (ArraySortTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS ArraySortTest DESTINATION bin/tests/) + +add_test(ArraySortTest ArraySortTest) diff --git a/cpp/tests/ArraySortTest/main.cpp b/cpp/tests/ArraySortTest/main.cpp new file mode 100644 index 00000000..710152f3 --- /dev/null +++ b/cpp/tests/ArraySortTest/main.cpp @@ -0,0 +1,123 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "probability.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + int nrow=10; + int ncol=3; + Array2D unsorted_array(nrow,ncol); + int seed = 13; + generate_uniform(unsorted_array,seed); + + Array1D oldInd(nrow); + for (int i=0; i newInd; + + cout << "====> Testing sort-by-column:" << endl; + + int sorting_col = 1; + Array2D array = unsorted_array; + shell_sort_col(array,sorting_col,newInd, oldInd); + + for (int i=0; i Sort-by-column test passed." << endl; + + // Sorting by columns sequentially, i.e. if elements are equal in the first column, the next column breaks the tie, and so on. + cout << "====> Testing sort-by-all:" << endl; + for (int i=0; i Sort-by-all test passed." << endl; + + //void shell_sort_incr(Array2D& array,int col, Array1D& newInd, Array1D& oldInd); + + + for (int i=0; i. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "arrayio.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "arraytools.h" +#include "dsfmt_add.h" +#include "bcs.h" +#include "assert.h" + + +using namespace std; + + +int main(){ + +int nord = 8; +int ndim = 1; +int level = 16; +Quad q("LU","full",ndim,level); + +Array2D x; +Array1D w; +Array2D index; +q.SetRule(); +q.GetRule(x,w,index); + +// get pc object +PCSet pcmodel("NISPnoq",nord,ndim,"LEG"); + +// get projection matrix +Array2D Phi; +pcmodel.EvalBasisAtCustPts(x,Phi); + +// get y at x points +Array1D y(x.XSize(),0.0); +for (int i = 0; i < x.XSize(); i++){ +y(i) = 1.0/(1.0 + x(i,0)*x(i,0)); +} + +// Main inputs are Phi, ydata, sigma +double sigma = 1e-8; + +// params +double eta = 1e-8; +Array1D lambda_init; +double scale = .1; + +// outputs +Array1D weights, errbars, basis, alpha; +Array1D used; +double lambda = 0.0; + +int adaptive=1; +int optimal=1; +int verbose=0; +// run bcs +//bcs(Phi,y,sigma,eta,scale,weights,used,errbars); +BCS(Phi,y,sigma,eta,lambda_init,adaptive,optimal,scale,verbose,weights,used,errbars,basis,alpha,lambda); + +printarray(weights); +printarray(used); +printarray(errbars); + +cout << fabs(0.785397 - weights(0)) << endl; +cout << fabs(-0.353987 - weights(1)) << endl; +cout << fabs(0.00316971 - weights(4)) << endl; +cout << fabs(used(1) - 2) << endl; +cout << fabs(used(2) - 4) << endl; +cout << fabs(used(4) - 8) << endl; + +assert(fabs(0.785397 - weights(0)) < 1e-6); +assert(fabs(-0.353987 - weights(1)) < 1e-6); +assert(fabs(0.00316971 - weights(4)) < 1e-6); +assert(fabs(used(1) - 2) < 1e-16); +assert(fabs(used(2) - 4) < 1e-16); +assert(fabs(used(4) - 8) < 1e-16); + + + + +return 0; + +} diff --git a/cpp/tests/BCS2dTest/CMakeLists.txt b/cpp/tests/BCS2dTest/CMakeLists.txt new file mode 100644 index 00000000..5fee4ab9 --- /dev/null +++ b/cpp/tests/BCS2dTest/CMakeLists.txt @@ -0,0 +1,65 @@ +project (UQTk) + +add_executable (BCS2dTest main.cpp) + +# SET(copy_FILES +# mindex_2d.dat +# ck_2d.dat +# ) +# INSTALL(FILES ${copy_FILES} DESTINATION bin/tests/) + +target_link_libraries (BCS2dTest uqtk ) + +target_link_libraries (BCS2dTest depdsfmt ) +target_link_libraries (BCS2dTest depcvode ) +target_link_libraries (BCS2dTest depnvec ) +target_link_libraries (BCS2dTest depslatec) +target_link_libraries (BCS2dTest deplapack) +target_link_libraries (BCS2dTest depblas ) +target_link_libraries (BCS2dTest deplbfgs ) +target_link_libraries (BCS2dTest depfigtree ) +target_link_libraries (BCS2dTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (BCS2dTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (BCS2dTest ifcore ifport) + else() + target_link_libraries (BCS2dTest ${IntelLibPath}/libifcore.a) + target_link_libraries (BCS2dTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (BCS2dTest gfortran stdc++) + else() + target_link_libraries (BCS2dTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/bcs ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS BCS2dTest DESTINATION bin/tests/) + +add_test(BCS2dTest BCS2dTest) diff --git a/cpp/tests/BCS2dTest/main.cpp b/cpp/tests/BCS2dTest/main.cpp new file mode 100644 index 00000000..9096b636 --- /dev/null +++ b/cpp/tests/BCS2dTest/main.cpp @@ -0,0 +1,132 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "arrayio.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "arraytools.h" +#include "dsfmt_add.h" +#include "bcs.h" +#include "assert.h" + + +using namespace std; + + +int main(){ + + // get pc object + Array1D ck(10,0.0); + Array2D mindex(10,2); + + // set ck values + ck(0) = 0.666666666666664; + ck(1) = 1.600000000000499; + ck(2) = 1.000000000000289; + ck(5) = -0.6666666666668039; + ck(6) = 0.4000000000008473; + + // set mindex values + mindex(0,0) = 0; mindex(0,1) = 0; + mindex(1,0) = 1; mindex(1,1) = 0; + mindex(2,0) = 0; mindex(2,1) = 1; + mindex(3,0) = 2; mindex(3,1) = 0; + mindex(4,0) = 1; mindex(4,1) = 1; + mindex(5,0) = 0; mindex(5,1) = 2; + mindex(6,0) = 3; mindex(6,1) = 0; + mindex(7,0) = 2; mindex(7,1) = 1; + mindex(8,0) = 1; mindex(8,1) = 2; + mindex(9,0) = 0; mindex(9,1) = 3; + + // set pc model given multiindex + PCSet pcmodel("NISPnoq",mindex,"LEG"); + + // get 2d quadrature points + Quad q("LU","sparse",2,5); + Array2D x; + Array1D w; + q.SetRule(); + q.GetRule(x,w); + // printarray(x); + + // evaluate PCE at quadrature points + Array1D y(x.XSize(),0.0); + pcmodel.EvalPCAtCustPoints(y,x,ck); + // printarray(y); + + // get projection matrix + Array2D Phi; + pcmodel.EvalBasisAtCustPts(x,Phi); + // printarray(Phi); + + // Main inputs are Phi, ydata, sigma + double sigma = 1e-8; + + // params + double eta = 1e-12; + Array1D lambda_init; + double scale = .1; + + // outputs + Array1D weights, errbars, basis, alpha; + Array1D used; + double lambda=0.0; + + + int adaptive=1; + int optimal=1; + int verbose=0; + + // run bcs + //bcs(Phi,y,sigma,eta,scale,weights,used,errbars); + BCS(Phi,y,sigma,eta,lambda_init,adaptive,optimal,scale,verbose,weights,used,errbars,basis,alpha,lambda); + + + printarray(weights); + printarray(used); + printarray(mindex); + printarray(ck); + + assert(used(0) == 1); + assert(used(1) == 2); + assert(used(2) == 0); + + assert(fabs(weights(0) - 1.6) < 1e-8); + assert(fabs(weights(1) - 1) < 1e-8); + assert(fabs(weights(2) - 2./3) < 1e-8); + + + + + return 0; + +} diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt new file mode 100644 index 00000000..aeb6fa42 --- /dev/null +++ b/cpp/tests/CMakeLists.txt @@ -0,0 +1,33 @@ +project (UQTk) + +# array tests +add_subdirectory (ArrayReadAndWrite) +add_subdirectory (ArrayDelColumn ) +add_subdirectory (Array1DMiscTest ) +add_subdirectory (Array2DMiscTest ) +add_subdirectory (ArraySortTest ) + +# # other tests +add_subdirectory (MultiIndexTest ) +add_subdirectory (CorrTest ) + +# # quadrature class tests +add_subdirectory (QuadLUTest ) + +# # MCMC class tests +add_subdirectory (MCMC2dTest ) +add_subdirectory (MCMCRandomTest ) +add_subdirectory (MCMCNestedTest ) + +# # PCBasis and PCSet tests +add_subdirectory (Deriv1dTest ) +add_subdirectory (SecondDeriv1dTest) +add_subdirectory (GradHessianTest ) +add_subdirectory (GradientPCETest ) +add_subdirectory (PCE1dTest ) +add_subdirectory (PCEImplTest ) +add_subdirectory (Hessian2dTest ) + +# # BCS tests +add_subdirectory (BCS1dTest ) +add_subdirectory (BCS2dTest ) diff --git a/cpp/tests/CorrTest/CMakeLists.txt b/cpp/tests/CorrTest/CMakeLists.txt new file mode 100644 index 00000000..41b5491a --- /dev/null +++ b/cpp/tests/CorrTest/CMakeLists.txt @@ -0,0 +1,76 @@ +project (UQTk) + +SET(copy_FILES + set_1_w1.dat + set_1_w2.dat + set_2_w1.dat + set_2_w2.dat + set_3_w1.dat + set_3_w2.dat + set_4_w1.dat + set_4_w2.dat + set_5_w1.dat + set_5_w2.dat + set_6_w1.dat + set_6_w2.dat + ) +file(COPY ${copy_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +add_executable (CorrTest main.cpp) + +target_link_libraries (CorrTest uqtk ) + +target_link_libraries (CorrTest depdsfmt ) +target_link_libraries (CorrTest depcvode ) +target_link_libraries (CorrTest depnvec ) +target_link_libraries (CorrTest depslatec) +target_link_libraries (CorrTest deplapack) +target_link_libraries (CorrTest depblas ) +target_link_libraries (CorrTest deplbfgs ) +target_link_libraries (CorrTest depfigtree ) +target_link_libraries (CorrTest depann ) + + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (CorrTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (CorrTest ifcore ifport) + else() + target_link_libraries (CorrTest ${IntelLibPath}/libifcore.a) + target_link_libraries (CorrTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (CorrTest gfortran stdc++) + else() + target_link_libraries (CorrTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS CorrTest DESTINATION bin/tests/) + +add_test(CorrTest CorrTest) diff --git a/cpp/tests/CorrTest/main.cpp b/cpp/tests/CorrTest/main.cpp new file mode 100644 index 00000000..86441b0f --- /dev/null +++ b/cpp/tests/CorrTest/main.cpp @@ -0,0 +1,61 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "arrayio.h" +#include "arraytools.h" +#include "probability.h" +#include "assert.h" + + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv) { + + cout << "Testing implementation of distance correlation " << endl; + double cMin[6]={3.6e-01,1.3e-01,1.4e-01,4.8e-01,3.0e-01,0.0}; + double cMax[6]={3.8e-01,1.5e-01,1.6e-01,5.0e-01,3.2e-01,0.01}; + + Array2D spls, dCor; + + for ( int i = 0; i < 6; i++ ) { + char fname[20]; + sprintf(fname,"set_%d_w1.dat",i+1); + read_datafileVS(spls, (char *) fname); + distCorr( spls, dCor); + printf("Set #%d: %e\n",i+1, dCor(1,0)); + assert((dCor(1,0)>cMin[i])&&(dCor(1,0). + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /******************************************* + Get derivative of a Legendre + polynomial at x = 1.0 up to 4th order + ********************************************/ + + PCBasis polybasis("LU"); + Array1D derivevals(5,0); + + double x = 1.0; + polybasis.EvalDerivBasis(x,derivevals); + + printarray(derivevals); + + assert(derivevals(0) == 0.0); + assert(derivevals(1) == 1.0); + assert(derivevals(2) == 3.0); + assert(derivevals(3) == 6.0); + assert(derivevals(4) == 10.0); + + /******************************************* + Get derivative of a Legendre + polynomial at x = -1,-.5,0,.5,1.0 up to 4th order + ********************************************/ + Array2D dpsi; + int kord = 4; + Array1D custPoints(5,0); + for (int i = 0; i < 5; i++){ + custPoints(i) = 2*i/4.0 - 1.0; + } + polybasis.Eval1dDerivBasisAtCustPoints(dpsi,kord,custPoints); + assert(dpsi(4,0) == 0.0); + assert(dpsi(4,1) == 1.0); + assert(dpsi(4,2) == 3.0); + assert(dpsi(4,3) == 6.0); + assert(dpsi(4,4) == 10.0); + + + return 0; + +} diff --git a/cpp/tests/GradHessianTest/CMakeLists.txt b/cpp/tests/GradHessianTest/CMakeLists.txt new file mode 100644 index 00000000..96c71858 --- /dev/null +++ b/cpp/tests/GradHessianTest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +add_executable (GradHessianTest main.cpp) + +target_link_libraries (GradHessianTest uqtk ) + +target_link_libraries (GradHessianTest depdsfmt ) +target_link_libraries (GradHessianTest depcvode ) +target_link_libraries (GradHessianTest depnvec ) +target_link_libraries (GradHessianTest depslatec) +target_link_libraries (GradHessianTest deplapack) +target_link_libraries (GradHessianTest depblas ) +target_link_libraries (GradHessianTest deplbfgs ) +target_link_libraries (GradHessianTest depfigtree ) +target_link_libraries (GradHessianTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (GradHessianTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (GradHessianTest ifcore ifport) + else() + target_link_libraries (GradHessianTest ${IntelLibPath}/libifcore.a) + target_link_libraries (GradHessianTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (GradHessianTest gfortran stdc++) + else() + target_link_libraries (GradHessianTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS GradHessianTest DESTINATION bin/tests/) + +add_test(GradHessianTest GradHessianTest) diff --git a/cpp/tests/GradHessianTest/main.cpp b/cpp/tests/GradHessianTest/main.cpp new file mode 100644 index 00000000..e96b57f1 --- /dev/null +++ b/cpp/tests/GradHessianTest/main.cpp @@ -0,0 +1,160 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /******************************************** + Test gradient of Legendre PCE + ********************************************/ + + // get 1d legendre polynomials + int ndim = 3; + int norder = 4; + PCSet polymodel("NISPnoq",norder,ndim,"LU"); + // polymodel.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha(ndim); + alpha(0) = 1; + alpha(1) = 3; + alpha(2) = 2; + + // define evaluation point and gradient + Array1D x(ndim,1); + Array1D grad; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel.dPhi_alpha(x, alpha, grad); + // printarray(grad); + assert(grad(0) == 1.0); + assert(grad(1) == 6.0); + assert(grad(2) == 3.0); + + /******************************************** + Test Hessian of Legendre PCE + ********************************************/ + + // get 1d legendre polynomials + int ndim2 = 2; + int norder2 = 4; + PCSet polymodel2("NISPnoq",norder2,ndim2,"LU"); + // polymodel2.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha2(ndim2,0); + alpha2(0) = 1; + alpha2(1) = 2; + + // define evaluation point and gradient + Array1D x2(ndim2,0); + x2(0) = 1; + x2(1) = 2; + Array1D grad2; + Array2D hessian; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel2.dPhi_alpha(x2, alpha2, grad2); + printarray(grad2); + + polymodel2.ddPhi_alpha(x2, alpha2, hessian); + printarray(hessian); + assert(hessian(0,0) == 0.0); + assert(hessian(1,1) == 3.0); + assert(hessian(0,1) == 6.0); + assert(hessian(1,0) == 6.0); + + /******************************************** + Test 3D Hessian of Legendre PCE + ********************************************/ + int ndim3 = 3; + int norder3 = 4; + PCSet polymodel3("NISPnoq",norder3,ndim3,"LU"); + // polymodel3.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha3(ndim3,0); + alpha3(0) = 1; + alpha3(1) = 1; + alpha3(2) = 2; + + // define evaluation point and gradient + Array1D x3(ndim3,0); + x3(0) = 1; + x3(1) = 2; + x3(2) = 3; + Array1D grad3; + Array2D hessian2; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel3.dPhi_alpha(x3, alpha3, grad3); + printarray(grad3); + + polymodel3.ddPhi_alpha(x3, alpha3, hessian2); + printarray(hessian2); + assert(hessian2(0,0) == 0.0); + assert(hessian2(1,1) == 0.0); + assert(hessian2(2,2) == 6.0); + assert(hessian2(0,1) == 13.0); + assert(hessian2(0,2) == 18.0); + assert(hessian2(1,2) == 9.0); + + // check to make sure Hessian is symmetric + Array2D hessian2T; + hessian2T = Trans(hessian2); + for (int i = 0; i < ndim3; i++){ + for (int j = 0; j < ndim3; j++){ + assert(hessian2(i,j) == hessian2T(i,j)); + } + } + + + + + + return 0; + +} diff --git a/cpp/tests/GradientPCETest/CMakeLists.txt b/cpp/tests/GradientPCETest/CMakeLists.txt new file mode 100644 index 00000000..6d6500d5 --- /dev/null +++ b/cpp/tests/GradientPCETest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +add_executable (GradientPCETest main.cpp) + +target_link_libraries (GradientPCETest uqtk ) + +target_link_libraries (GradientPCETest depdsfmt ) +target_link_libraries (GradientPCETest depcvode ) +target_link_libraries (GradientPCETest depnvec ) +target_link_libraries (GradientPCETest depslatec) +target_link_libraries (GradientPCETest deplapack) +target_link_libraries (GradientPCETest depblas ) +target_link_libraries (GradientPCETest deplbfgs ) +target_link_libraries (GradientPCETest depfigtree ) +target_link_libraries (GradientPCETest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (GradientPCETest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (GradientPCETest ifcore ifport) + else() + target_link_libraries (GradientPCETest ${IntelLibPath}/libifcore.a) + target_link_libraries (GradientPCETest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (GradientPCETest gfortran stdc++) + else() + target_link_libraries (GradientPCETest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS GradientPCETest DESTINATION bin/tests/) + +add_test(GradientPCETest GradientPCETest) diff --git a/cpp/tests/GradientPCETest/main.cpp b/cpp/tests/GradientPCETest/main.cpp new file mode 100644 index 00000000..e96b57f1 --- /dev/null +++ b/cpp/tests/GradientPCETest/main.cpp @@ -0,0 +1,160 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /******************************************** + Test gradient of Legendre PCE + ********************************************/ + + // get 1d legendre polynomials + int ndim = 3; + int norder = 4; + PCSet polymodel("NISPnoq",norder,ndim,"LU"); + // polymodel.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha(ndim); + alpha(0) = 1; + alpha(1) = 3; + alpha(2) = 2; + + // define evaluation point and gradient + Array1D x(ndim,1); + Array1D grad; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel.dPhi_alpha(x, alpha, grad); + // printarray(grad); + assert(grad(0) == 1.0); + assert(grad(1) == 6.0); + assert(grad(2) == 3.0); + + /******************************************** + Test Hessian of Legendre PCE + ********************************************/ + + // get 1d legendre polynomials + int ndim2 = 2; + int norder2 = 4; + PCSet polymodel2("NISPnoq",norder2,ndim2,"LU"); + // polymodel2.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha2(ndim2,0); + alpha2(0) = 1; + alpha2(1) = 2; + + // define evaluation point and gradient + Array1D x2(ndim2,0); + x2(0) = 1; + x2(1) = 2; + Array1D grad2; + Array2D hessian; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel2.dPhi_alpha(x2, alpha2, grad2); + printarray(grad2); + + polymodel2.ddPhi_alpha(x2, alpha2, hessian); + printarray(hessian); + assert(hessian(0,0) == 0.0); + assert(hessian(1,1) == 3.0); + assert(hessian(0,1) == 6.0); + assert(hessian(1,0) == 6.0); + + /******************************************** + Test 3D Hessian of Legendre PCE + ********************************************/ + int ndim3 = 3; + int norder3 = 4; + PCSet polymodel3("NISPnoq",norder3,ndim3,"LU"); + // polymodel3.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha3(ndim3,0); + alpha3(0) = 1; + alpha3(1) = 1; + alpha3(2) = 2; + + // define evaluation point and gradient + Array1D x3(ndim3,0); + x3(0) = 1; + x3(1) = 2; + x3(2) = 3; + Array1D grad3; + Array2D hessian2; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel3.dPhi_alpha(x3, alpha3, grad3); + printarray(grad3); + + polymodel3.ddPhi_alpha(x3, alpha3, hessian2); + printarray(hessian2); + assert(hessian2(0,0) == 0.0); + assert(hessian2(1,1) == 0.0); + assert(hessian2(2,2) == 6.0); + assert(hessian2(0,1) == 13.0); + assert(hessian2(0,2) == 18.0); + assert(hessian2(1,2) == 9.0); + + // check to make sure Hessian is symmetric + Array2D hessian2T; + hessian2T = Trans(hessian2); + for (int i = 0; i < ndim3; i++){ + for (int j = 0; j < ndim3; j++){ + assert(hessian2(i,j) == hessian2T(i,j)); + } + } + + + + + + return 0; + +} diff --git a/cpp/tests/Hessian2dTest/CMakeLists.txt b/cpp/tests/Hessian2dTest/CMakeLists.txt new file mode 100644 index 00000000..a68bd990 --- /dev/null +++ b/cpp/tests/Hessian2dTest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +add_executable (Hessian2dTest main.cpp) + +target_link_libraries (Hessian2dTest uqtk ) + +target_link_libraries (Hessian2dTest depdsfmt ) +target_link_libraries (Hessian2dTest depcvode ) +target_link_libraries (Hessian2dTest depnvec ) +target_link_libraries (Hessian2dTest depslatec) +target_link_libraries (Hessian2dTest deplapack) +target_link_libraries (Hessian2dTest depblas ) +target_link_libraries (Hessian2dTest deplbfgs ) +target_link_libraries (Hessian2dTest depfigtree ) +target_link_libraries (Hessian2dTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (Hessian2dTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (Hessian2dTest ifcore ifport) + else() + target_link_libraries (Hessian2dTest ${IntelLibPath}/libifcore.a) + target_link_libraries (Hessian2dTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (Hessian2dTest gfortran stdc++) + else() + target_link_libraries (Hessian2dTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS Hessian2dTest DESTINATION bin/tests/) + +add_test(Hessian2dTest Hessian2dTest) diff --git a/cpp/tests/Hessian2dTest/main.cpp b/cpp/tests/Hessian2dTest/main.cpp new file mode 100644 index 00000000..38adbf15 --- /dev/null +++ b/cpp/tests/Hessian2dTest/main.cpp @@ -0,0 +1,110 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /******************************************** + Get Legendre PCE for 2d quadratic + ********************************************/ + // Set up quadrature rule + Array2D xq; + Array1D wq; + Array2D index; + + int ndim1 = 2; + int level1 = 5; + + Quad q("LU","sparse",ndim1,level1); + q.SetRule(); + q.GetRule(xq,wq,index); + + // define function to be evaluated + Array1D y0(xq.XSize(),0); + for (int i = 0; i < xq.XSize(); i++){ + y0(i) = ( -.5*( sqrt(2)*xq(i,0)*xq(i,0) + sqrt(3)*xq(i,1)*xq(i,1)) + xq(i,0)*xq(i,0)*xq(i,1) ); + } + + // Define PCSet object with quadrature rule above + int nord = 3; + PCSet pcmodel("NISPnoq",nord,ndim1,"LU"); + pcmodel.SetQuadRule(q); + + // get multiindex + Array2D mindex0; + pcmodel.GetMultiIndex(mindex0); + pcmodel.PrintMultiIndex(); + // write_datafile(mindex0, "mindex.dat"); + + // get coefficients + Array1D ck0; + pcmodel.GalerkProjection(y0,ck0); + // write_datafile_1d(ck0, "ck.dat"); + + /******************************************** + Test Hessian of Legendre PCE + ********************************************/ + + // get 1d legendre polynomials + int ndim = 2; + + // The first step, after reading in mindex, is to initialize the PCSet object. + PCSet polymodel("NISPnoq",mindex0,"LU"); + polymodel.PrintMultiIndex(); + + //compute the hessian at a single x point + Array1D xpnt(ndim,0.0); + Array2D hessian; + polymodel.ddPhi(xpnt,mindex0,hessian,ck0); + cout << fabs(hessian(0,0) - (-sqrt(2))) << endl; + cout << fabs(hessian(1,1) - (-sqrt(3))) << endl; + cout << fabs(hessian(0,1) - (2*xpnt(0))) << endl; + printarray(hessian); + assert(fabs(hessian(0,0) - (-sqrt(2))) <= 1e-12); + assert(fabs(hessian(1,1) - (-sqrt(3))) <= 1e-12); + assert(fabs(hessian(0,1) - (2*xpnt(0))) <= 1e-12); + + + return 0; + +} diff --git a/cpp/tests/MCMC2dTest/CMakeLists.txt b/cpp/tests/MCMC2dTest/CMakeLists.txt new file mode 100644 index 00000000..3c3fcda1 --- /dev/null +++ b/cpp/tests/MCMC2dTest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +INSTALL(FILES ${copy_FILES} DESTINATION cpp/tests/MCMC2dTest/) + +add_executable (MCMC2dTest main.cpp) + +target_link_libraries (MCMC2dTest uqtk ) + +target_link_libraries (MCMC2dTest depdsfmt ) +target_link_libraries (MCMC2dTest depcvode ) +target_link_libraries (MCMC2dTest depnvec ) +target_link_libraries (MCMC2dTest depslatec) +target_link_libraries (MCMC2dTest deplapack) +target_link_libraries (MCMC2dTest depblas ) +target_link_libraries (MCMC2dTest deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (MCMC2dTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (MCMC2dTest ifcore ifport) + else() + target_link_libraries (MCMC2dTest ${IntelLibPath}/libifcore.a) + target_link_libraries (MCMC2dTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (MCMC2dTest gfortran stdc++) + else() + target_link_libraries (MCMC2dTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS MCMC2dTest DESTINATION bin/tests/) + +add_test(MCMC2dTest MCMC2dTest) diff --git a/cpp/tests/MCMC2dTest/main.cpp b/cpp/tests/MCMC2dTest/main.cpp new file mode 100644 index 00000000..b467d532 --- /dev/null +++ b/cpp/tests/MCMC2dTest/main.cpp @@ -0,0 +1,128 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Define Likelihood function +*************************************************/ +class Likelihood: public LikelihoodBase{ +public: + Likelihood(){}; + ~Likelihood(){}; + double eval(Array1D&); +}; + +// // Rosnebrock function +// double Likelihood::eval(Array1D& x){ +// double lnpost = -(1-x(0))*(1-x(0)) - 100*(x(1) - x(0)*x(0))*(x(1) - x(0)*x(0)); +// return lnpost; +// } + +// Simple 2d Gaussian with zero mean and (.1,.8) variance +double Likelihood::eval(Array1D& x){ + double lnpost = -.5*(x(0)*x(0)/.01 + x(1)*x(1)/.64); + return lnpost; +} + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + +/************************************************* + Initial start for MCMC chain + and set Likelihood function + *************************************************/ + int dim = 2; + int nCalls = 500000; + Array1D x(dim,0); + + Likelihood L; + // cout << "L.eval(x) = " << L.eval(x) << endl; + + /************************************************* + Initiate and Run MCMC chain + *************************************************/ + Array1D g(dim,.1); + + MCMC mchain(L); + mchain.setChainDim(dim); + mchain.initMethod("am"); + mchain.initChainPropCovDiag(g); + mchain.setSeed(13); + // mchain.printChainSetup(); + // mchain.setOutputInfo("txt","chain.txt",nCalls,nCalls); + mchain.setWriteFlag(0); + mchain.runChain(nCalls,x); + + // Get chain states + Array1D chainstates; + mchain.getFullChain(chainstates); + + // get mean from chainstates + double mean_x1 = 0; + double mean_x2 = 0; + int nBurn = 3000; + for (int i = nBurn; i < nCalls; i++){ + mean_x1 += chainstates(i).state(0); + mean_x2 += chainstates(i).state(1); + } + mean_x1 *= 1./(nCalls-nBurn+1); + mean_x2 *= 1./(nCalls-nBurn+1); + cout << mean_x1 << endl; + cout << mean_x2 << endl; + + // get variance + double var_x1 = 0; + double var_x2 = 0; + for (int i = nBurn; i < nCalls; i=i+1){ + var_x1 += pow(chainstates(i).state(0) - mean_x1,2); + var_x2 += pow(chainstates(i).state(1) - mean_x2,2); + } + var_x1 *= 1./(nCalls-nBurn); + var_x2 *= 1./(nCalls-nBurn); + cout << var_x1 << endl; + cout << var_x2 << endl; + + // check variance + assert(fabs((sqrt(var_x1) - .1)) < .01); + assert(fabs((sqrt(var_x2) - .8)) < .01); + + return 0; + +} diff --git a/cpp/tests/MCMCNestedTest/CMakeLists.txt b/cpp/tests/MCMCNestedTest/CMakeLists.txt new file mode 100644 index 00000000..3b9d8f85 --- /dev/null +++ b/cpp/tests/MCMCNestedTest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +INSTALL(FILES ${copy_FILES} DESTINATION cpp/tests/MCMCNestedTest/) + +add_executable (MCMCNestedTest main.cpp) + +target_link_libraries (MCMCNestedTest uqtk ) + +target_link_libraries (MCMCNestedTest depdsfmt ) +target_link_libraries (MCMCNestedTest depcvode ) +target_link_libraries (MCMCNestedTest depnvec ) +target_link_libraries (MCMCNestedTest depslatec) +target_link_libraries (MCMCNestedTest deplapack) +target_link_libraries (MCMCNestedTest depblas ) +target_link_libraries (MCMCNestedTest deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (MCMCNestedTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (MCMCNestedTest ifcore ifport) + else() + target_link_libraries (MCMCNestedTest ${IntelLibPath}/libifcore.a) + target_link_libraries (MCMCNestedTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (MCMCNestedTest gfortran stdc++) + else() + target_link_libraries (MCMCNestedTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS MCMCNestedTest DESTINATION bin/tests/) + +add_test(MCMCNestedTest MCMCNestedTest) diff --git a/cpp/tests/MCMCNestedTest/main.cpp b/cpp/tests/MCMCNestedTest/main.cpp new file mode 100644 index 00000000..654b3cef --- /dev/null +++ b/cpp/tests/MCMCNestedTest/main.cpp @@ -0,0 +1,153 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Define Likelihood functions +*************************************************/ +class Likelihood: public LikelihoodBase{ +public: + Likelihood(){}; + ~Likelihood(){}; + double eval(Array1D&); +}; +class Likelihood_in: public LikelihoodBase{ +public: + Likelihood_in(){}; + ~Likelihood_in(){}; + double eval(Array1D&); +}; +class Likelihood2: public LikelihoodBase{ +public: + Likelihood2(){}; + ~Likelihood2(){}; + double eval(Array1D&); +}; + +// Rosnebrock function +double Likelihood::eval(Array1D& x){ + Likelihood_in L; + int dim = 2; + int nCalls = 100; + Array1D g(dim,.1); + MCMC mchaintemp(L); + mchaintemp.setChainDim(dim); + mchaintemp.initMethod("am"); + mchaintemp.initChainPropCovDiag(g); + mchaintemp.setWriteFlag(0); + mchaintemp.setSeed(10); + mchaintemp.runChain(nCalls,x); + Array2D samples; + mchaintemp.getSamples(samples); + samples = Trans(samples); + // printarray(samples); + + double lnpost = -(1-x(0))*(1-x(0)) - 100*(x(1) - x(0)*x(0))*(x(1) - x(0)*x(0)); + return lnpost; +} +// Rosnebrock function +double Likelihood_in::eval(Array1D& x){ + double lnpost = -.5*(x(0)*x(0)/.01 + x(1)*x(1)/.64); + return lnpost; +} +// Rosnebrock function +double Likelihood2::eval(Array1D& x){ + double lnpost = -(1-x(0))*(1-x(0)) - 100*(x(1) - x(0)*x(0))*(x(1) - x(0)*x(0)); + return lnpost; +} + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /************************************************* + Initial start for MCMC chain + and set Likelihood function + *************************************************/ + int dim = 2; + int nCalls = 100; + Array1D x(dim,0); + + /************************************************* + Initiate and Run MCMC chain + *************************************************/ + Likelihood L; + Array1D g(dim,.1); + MCMC mchain(L); + mchain.setChainDim(dim); + mchain.initMethod("am"); + mchain.initChainPropCovDiag(g); + mchain.setOutputInfo("txt","chain.txt",nCalls,nCalls); + mchain.setWriteFlag(0); + mchain.runChain(nCalls,x); + Array2D samples; + mchain.getSamples(samples); + samples = Trans(samples); + // printarray(samples); + + /************************************************* + Initiate and Run MCMC chain + *************************************************/ + Likelihood2 L2; + Array1D g2(dim,.1); + MCMC mchain2(L2); + mchain2.setChainDim(dim); + mchain2.initMethod("am"); + mchain2.initChainPropCovDiag(g2); + mchain2.setOutputInfo("txt","chain.txt",nCalls,nCalls); + mchain2.setWriteFlag(0); + mchain2.runChain(nCalls,x); + Array2D samples2; + mchain2.getSamples(samples2); + samples2 = Trans(samples2); + // printarray(samples2); + + // test to make sure two MCMC objects do not + // affect each others random number generation + for (int i = 0; i < nCalls; i++){ + for (int n = 0; n < dim; n++){ + assert(samples(i,n) - samples2(i,n) == 0) ; + } + } + + + + return 0; + +} diff --git a/cpp/tests/MCMCRandomTest/CMakeLists.txt b/cpp/tests/MCMCRandomTest/CMakeLists.txt new file mode 100644 index 00000000..95c27f45 --- /dev/null +++ b/cpp/tests/MCMCRandomTest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +INSTALL(FILES ${copy_FILES} DESTINATION cpp/tests/MCMCRandomTest/) + +add_executable (MCMCRandomTest main.cpp) + +target_link_libraries (MCMCRandomTest uqtk ) + +target_link_libraries (MCMCRandomTest depdsfmt ) +target_link_libraries (MCMCRandomTest depcvode ) +target_link_libraries (MCMCRandomTest depnvec ) +target_link_libraries (MCMCRandomTest depslatec) +target_link_libraries (MCMCRandomTest deplapack) +target_link_libraries (MCMCRandomTest depblas ) +target_link_libraries (MCMCRandomTest deplbfgs ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (MCMCRandomTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (MCMCRandomTest ifcore ifport) + else() + target_link_libraries (MCMCRandomTest ${IntelLibPath}/libifcore.a) + target_link_libraries (MCMCRandomTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (MCMCRandomTest gfortran stdc++) + else() + target_link_libraries (MCMCRandomTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS MCMCRandomTest DESTINATION bin/tests/) + +add_test(MCMCRandomTest MCMCRandomTest) diff --git a/cpp/tests/MCMCRandomTest/main.cpp b/cpp/tests/MCMCRandomTest/main.cpp new file mode 100644 index 00000000..2ec24356 --- /dev/null +++ b/cpp/tests/MCMCRandomTest/main.cpp @@ -0,0 +1,123 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Define Likelihood function +*************************************************/ +class Likelihood: public LikelihoodBase{ +public: + Likelihood(){}; + ~Likelihood(){}; + double eval(Array1D&); +}; + +// Rosnebrock function +double Likelihood::eval(Array1D& x){ + double lnpost = -(1-x(0))*(1-x(0)) - 100*(x(1) - x(0)*x(0))*(x(1) - x(0)*x(0)); + // double lnpost = -.5*(x(0)*x(0)/.01 + x(1)*x(1)/.64); + // // ''' + // // sample from exp(-.5*(x**2/.1**2 - y**2/.8**2)) + // // ''' + // // y1 = x[0] + // // y2 = x[1] + // // return -.5*(y1**2/.1**2 + y2**2/.8**2) + return lnpost; +} + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /************************************************* + Initial start for MCMC chain + and set Likelihood function + *************************************************/ + int dim = 2; + int nCalls = 100; + Array1D x(dim,0); + + Likelihood L; + cout << "L.eval(x) = " << L.eval(x) << endl; + + /************************************************* + Initiate and Run MCMC chain + *************************************************/ + Array1D g(dim,.1); + + MCMC mchain(L); + mchain.setChainDim(dim); + mchain.initMethod("am"); + mchain.initChainPropCovDiag(g); + mchain.setOutputInfo("txt","chain.txt",nCalls,nCalls); + mchain.setWriteFlag(0); + mchain.runChain(nCalls,x); + Array2D samples; + mchain.getSamples(samples); + samples = Trans(samples); + // printarray(samples); + + /************************************************* + Initiate and Run a second MCMC chain + *************************************************/ + MCMC mchain2(L); + mchain2.setChainDim(dim); + mchain2.initMethod("am"); + mchain2.initChainPropCovDiag(g); + // mchain2.setSeed(130); + mchain2.setWriteFlag(0); + mchain2.runChain(nCalls,x); + Array2D samples2; + mchain2.getSamples(samples2); + samples2 = Trans(samples2); + // printarray(samples2); + + // test to make sure two MCMC objects do not + // affect each others random number generation + for (int i = 0; i < nCalls; i++){ + for (int n = 0; n < dim; n++){ + assert(samples(i,n) - samples2(i,n) == 0) ; + } + } + + + + return 0; + +} diff --git a/cpp/tests/MultiIndexTest/CMakeLists.txt b/cpp/tests/MultiIndexTest/CMakeLists.txt new file mode 100644 index 00000000..b4fe40d3 --- /dev/null +++ b/cpp/tests/MultiIndexTest/CMakeLists.txt @@ -0,0 +1,63 @@ +project (UQTk) + +add_executable (MultiIndexTest main.cpp) + +target_link_libraries (MultiIndexTest uqtk) + +target_link_libraries (MultiIndexTest depdsfmt ) +target_link_libraries (MultiIndexTest depcvode ) +target_link_libraries (MultiIndexTest depnvec ) +target_link_libraries (MultiIndexTest depslatec ) +target_link_libraries (MultiIndexTest deplapack ) +target_link_libraries (MultiIndexTest depblas ) +target_link_libraries (MultiIndexTest deplbfgs ) +target_link_libraries (MultiIndexTest depfigtree ) +target_link_libraries (MultiIndexTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + if ("${GnuLibPath}" STREQUAL "") + target_link_libraries (MultiIndexTest gfortran stdc++) + else() + target_link_libraries (MultiIndexTest ${GnuLibPath}/libgfortran.a ${GnuLibPath}/libquadmath.a stdc++) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (MultiIndexTest ifcore) + else() + target_link_libraries (MultiIndexTest ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (MultiIndexTest gfortran stdc++) + else() + target_link_libraries (MultiIndexTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/figtree) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS MultiIndexTest DESTINATION bin/tests/) + +add_test(MultiIndexTest MultiIndexTest) diff --git a/cpp/tests/MultiIndexTest/main.cpp b/cpp/tests/MultiIndexTest/main.cpp new file mode 100644 index 00000000..d7954c34 --- /dev/null +++ b/cpp/tests/MultiIndexTest/main.cpp @@ -0,0 +1,96 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "probability.h" +#include "arrayio.h" +#include "arraytools.h" +#include "multiindex.h" +#include "assert.h" +#include "gen_defs.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + cout << "====> Testing multiindex generation:" << endl; + int ndim = 3; + int order = 4; + Array2D mindex; + + // Computes multiindex + int npc = computeMultiIndex(ndim,order, mindex); + // Basic sanity check + CHECKEQ(npc,mindex.XSize()); + + // Print multiindex set + for (int ip=0; ip mi; + getRow(mindex,ip,mi); + // Compute 'inverse' multiindex, i.e. given a multiindex, find its location + int ip_inv=get_invmindex(mi); + cout << " : " << ip_inv << endl; + // Make sure inverse works correctly + CHECKEQ(ip,ip_inv); + } + + + // Increase multiindex by an order + cout << "Growing an order" << endl; + + Array2D new_mindex; + upOrder(mindex,new_mindex); + + // Compute orders of each term + Array1D orders; + getOrders(new_mindex,orders); + + // Print the new multiindex + for (int ip=0; ip. + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + // Set up quadrature rule + Array2D x; + Array1D w; + Array2D index; + + int ndim = 1; + int level = 16; + + Quad q("LU","full",ndim,level); + q.SetRule(); + q.GetRule(x,w,index); + + // define function to be evaluated + Array1D y(x.XSize(),0); + for (int i = 0; i < x.XSize(); i++){ + y(i) = 1./(1 + x(i,0)*x(i,0)); + // cout << x(i,0) << ", " << y(i) << endl; + } + + // Define PCSet object with quadrature rule above + int nord = level; + PCSet pcmodel("NISPnoq",nord,ndim,"LU"); + pcmodel.SetQuadRule(q); + + // get multiindex + Array2D mindex; + pcmodel.GetMultiIndex(mindex); + + // get coefficients + Array1D ck; + pcmodel.GalerkProjection(y,ck); + + // evaluate PC at quadrature points + Array1D ytest(x.XSize(),0); + pcmodel.EvalPCAtCustPoints(ytest,x,ck); + double error = 0.0; + for (int i = 0; i < x.XSize(); i++){ + error += pow(y(i) - ytest(i),2); + } + cout << "error at the quadrature points: " << sqrt(error) << endl; + assert( sqrt(error) <= 1e-12); + + + + return 0; + +} diff --git a/cpp/tests/PCEImplTest/CMakeLists.txt b/cpp/tests/PCEImplTest/CMakeLists.txt new file mode 100644 index 00000000..e72905e2 --- /dev/null +++ b/cpp/tests/PCEImplTest/CMakeLists.txt @@ -0,0 +1,59 @@ +project (UQTk) + +add_executable (PCEImplTest main.cpp) + +target_link_libraries (PCEImplTest uqtk ) + +target_link_libraries (PCEImplTest depdsfmt ) +target_link_libraries (PCEImplTest depcvode ) +target_link_libraries (PCEImplTest depnvec ) +target_link_libraries (PCEImplTest depslatec) +target_link_libraries (PCEImplTest deplapack) +target_link_libraries (PCEImplTest depblas ) +target_link_libraries (PCEImplTest deplbfgs ) +target_link_libraries (PCEImplTest depfigtree ) +target_link_libraries (PCEImplTest depann ) + + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (PCEImplTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (PCEImplTest ifcore ifport) + else() + target_link_libraries (PCEImplTest ${IntelLibPath}/libifcore.a) + target_link_libraries (PCEImplTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (PCEImplTest gfortran stdc++) + else() + target_link_libraries (PCEImplTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS PCEImplTest DESTINATION bin/tests/) + +add_test(PCEImplTest PCEImplTest) diff --git a/cpp/tests/PCEImplTest/main.cpp b/cpp/tests/PCEImplTest/main.cpp new file mode 100644 index 00000000..ec8a075f --- /dev/null +++ b/cpp/tests/PCEImplTest/main.cpp @@ -0,0 +1,129 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + cout << "Testing PC implementations: " << endl; + + + // Set up PC parameters + int ndim = 3; + int nord = 3; + string pctype = "HG"; + string impl = "ISP"; + + + // Define PCSet object + PCSet pcmodel(impl,nord,ndim,pctype); + + + cout << "====> Testing norm computation: " << endl; + + Array1D normsq, normsq_exact; + // Get the norms computed by quadrature + pcmodel.GetNormSq(normsq); + // Evaluate the norms analytically + pcmodel.EvalNormSqExact(normsq_exact); + + for (int i=0; i 1e-7 ){ + cout << "PC type = " << pctype << ", Dim = " << ndim << ", Order = " << nord << endl; + throw Tantrum("====> Norm computation test failed."); + } + + } + + cout << "====> Norm computation test passed." << endl; + + if (impl == "NISP"){ + // Testing Galerkin projection + cout << "====> Testing Galerkin projection: " << endl; + + // Get the quadrature points + Array2D x; + pcmodel.GetQuadPoints(x); + + // Define test function to be evaluated + // Test function is a polynomial of order nord + Array1D y(x.XSize(),0); + for (int i = 0; i < x.XSize(); i++){ + double sum = 0.0; + for (int j = 0; j < ndim; j++) + sum += (x(i,j)/(j+1)); + y(i) = pow(sum,nord); + } + + + // Get coefficients via Galerkin projection + Array1D ck; + pcmodel.GalerkProjection(y,ck); + + // Evaluate PC at quadrature points + // PC should be exactly matching the polynomial test function + Array1D ytest(x.XSize(),0); + pcmodel.EvalPCAtCustPoints(ytest,x,ck); + double error = 0.0; + for (int i = 0; i < x.XSize(); i++){ + error += pow(y(i) - ytest(i),2); + } + double rms_error=sqrt(error/x.XSize()); + if ( rms_error > 1e-10 ){ + cout << "PC type = " << pctype << ", Dim = " << ndim << ", Order = " << nord << endl; + cout << "Error at quadrature points " << rms_error << endl; + throw Tantrum("====> Galerkin projection test failed."); + } + + cout << "====> Galerkin projection test passed." << endl; + } + + else if (impl == "ISP"){ + cout << "ISP tests not implemented yet. " << endl; + //cout << "====> Testing triple products: " << endl; + //cout << "====> Testing 4-tuple products: " << endl; + } + + return 0; + +} diff --git a/cpp/tests/QuadLUTest/CMakeLists.txt b/cpp/tests/QuadLUTest/CMakeLists.txt new file mode 100644 index 00000000..30470a34 --- /dev/null +++ b/cpp/tests/QuadLUTest/CMakeLists.txt @@ -0,0 +1,63 @@ +project (UQTk) + +SET(copy_FILES + quadpnts.txt + quadwghts.txt + ) +INSTALL(FILES ${copy_FILES} DESTINATION cpp/tests/QuadLUTest/) + +add_executable (QuadLUTest main.cpp) + +target_link_libraries (QuadLUTest uqtk ) + +target_link_libraries (QuadLUTest depdsfmt ) +target_link_libraries (QuadLUTest depcvode ) +target_link_libraries (QuadLUTest depnvec ) +target_link_libraries (QuadLUTest depslatec) +target_link_libraries (QuadLUTest deplapack) +target_link_libraries (QuadLUTest depblas ) +target_link_libraries (QuadLUTest deplbfgs ) +target_link_libraries (QuadLUTest depfigtree ) +target_link_libraries (QuadLUTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (QuadLUTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (QuadLUTest ifcore) + else() + target_link_libraries (QuadLUTest ${IntelLibPath}/libifcore.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (QuadLUTest gfortran stdc++) + else() + target_link_libraries (QuadLUTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS QuadLUTest DESTINATION bin/tests/) + +add_test(QuadLUTest QuadLUTest) diff --git a/cpp/tests/QuadLUTest/main.cpp b/cpp/tests/QuadLUTest/main.cpp new file mode 100644 index 00000000..e71b7324 --- /dev/null +++ b/cpp/tests/QuadLUTest/main.cpp @@ -0,0 +1,93 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "mcmc.h" +#include "quad.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /************************************************* + get 2d quadrature points + *************************************************/ + Array2D x; + Array1D w; + + int ndim = 2; + int level = 5; + Quad q("LU","sparse",ndim,level,0,1); + + q.SetRule(); + q.GetRule(x,w); + + // Array2D x_ref(x.XSize(),x.YSize(),0); + // Array1D w_ref(w.Length(),0); + + // read_datafile(x_ref,"quadpnts.txt"); + // read_datafile_1d(w_ref,"quadwghts.txt"); + + // // check to make sure weights are correct + // for (int i = 0; i < w.Length(); i++){ + // double error = fabs(w(i) - w_ref(i)); + // assert(error < 1e-16); + // } + + // // check to make sure points are correct + // for (int i = 0; i < w.Length(); i++){ + // double error_x1 = fabs(x(i,0) - x_ref(i,0)); + // double error_x2 = fabs(x(i,1) - x_ref(i,1)); + // assert(error_x1 < 1e-16); + // assert(error_x2 < 1e-16); + // } + + double sum = 0e0; + double sum2 = 0e0; + double sum3 = 0e0; + for (int i = 0; i < w.Length(); i++){ + sum += w(i); + sum2 += pow(x(i,0),2)*w(i); + sum3 += pow(x(i,1),2)*pow(x(i,0),2)*w(i); + } + assert(fabs(sum - 1) < 1e-12); // sum of weights is 1 + assert(fabs(sum2 - 1./3) < 1e-12); // int of x^2 is 1/3 + assert(fabs(sum3 - 1./9) < 1e-12); // int of x^2y^2 is 1/9 + + + return 0; + +} diff --git a/cpp/tests/QuadLUTest/quadpnts.txt b/cpp/tests/QuadLUTest/quadpnts.txt new file mode 100644 index 00000000..ceec88c8 --- /dev/null +++ b/cpp/tests/QuadLUTest/quadpnts.txt @@ -0,0 +1,321 @@ + -0.9974246942464551 0 + -0.9905754753144171 -0.7745966692414833 + -0.9905754753144171 0 + -0.9905754753144171 0.7745966692414834 + -0.9864557262306423 0 + -0.9681602395076263 -0.9061798459386639 + -0.9681602395076263 -0.7745966692414833 + -0.9681602395076263 -0.5384693101056832 + -0.9681602395076263 0 + -0.9681602395076263 0.538469310105683 + -0.9681602395076263 0.7745966692414834 + -0.9681602395076263 0.9061798459386639 + -0.9668229096899926 0 + -0.9506755217687676 -0.7745966692414833 + -0.9506755217687676 0 + -0.9506755217687676 0.7745966692414834 + -0.9386943726111682 0 + -0.9061798459386639 -0.9681602395076263 + -0.9061798459386639 -0.9061798459386639 + -0.9061798459386639 -0.8360311073266359 + -0.9061798459386639 -0.7745966692414833 + -0.9061798459386639 -0.6133714327005902 + -0.9061798459386639 -0.5384693101056832 + -0.9061798459386639 -0.324253423403809 + -0.9061798459386639 0 + -0.9061798459386639 0.3242534234038088 + -0.9061798459386639 0.538469310105683 + -0.9061798459386639 0.6133714327005906 + -0.9061798459386639 0.7745966692414834 + -0.9061798459386639 0.8360311073266353 + -0.9061798459386639 0.9061798459386639 + -0.9061798459386639 0.9681602395076263 + -0.9023167677434333 0 + -0.8802391537269858 -0.7745966692414833 + -0.8802391537269858 0 + -0.8802391537269858 0.7745966692414834 + -0.8580096526765038 0 + -0.8360311073266359 -0.9061798459386639 + -0.8360311073266359 -0.7745966692414833 + -0.8360311073266359 -0.5384693101056832 + -0.8360311073266359 0 + -0.8360311073266359 0.538469310105683 + -0.8360311073266359 0.7745966692414834 + -0.8360311073266359 0.9061798459386639 + -0.8061623562741663 0 + -0.7815140038968014 -0.7745966692414833 + -0.7815140038968014 0 + -0.7815140038968014 0.7745966692414834 + -0.7745966692414833 -0.9905754753144171 + -0.7745966692414833 -0.9681602395076263 + -0.7745966692414833 -0.9506755217687676 + -0.7745966692414833 -0.9061798459386639 + -0.7745966692414833 -0.8802391537269858 + -0.7745966692414833 -0.8360311073266359 + -0.7745966692414833 -0.7815140038968014 + -0.7745966692414833 -0.7745966692414833 + -0.7745966692414833 -0.6576711592166908 + -0.7745966692414833 -0.6133714327005902 + -0.7745966692414833 -0.5384693101056832 + -0.7745966692414833 -0.5126905370864772 + -0.7745966692414833 -0.3512317634538764 + -0.7745966692414833 -0.324253423403809 + -0.7745966692414833 -0.1784841814958477 + -0.7745966692414833 0 + -0.7745966692414833 0.1784841814958473 + -0.7745966692414833 0.3242534234038088 + -0.7745966692414833 0.3512317634538762 + -0.7745966692414833 0.5126905370864772 + -0.7745966692414833 0.538469310105683 + -0.7745966692414833 0.6133714327005906 + -0.7745966692414833 0.6576711592166908 + -0.7745966692414833 0.7745966692414834 + -0.7745966692414833 0.7815140038968016 + -0.7745966692414833 0.8360311073266353 + -0.7745966692414833 0.880239153726986 + -0.7745966692414833 0.9061798459386639 + -0.7745966692414833 0.9506755217687677 + -0.7745966692414833 0.9681602395076263 + -0.7745966692414833 0.9905754753144174 + -0.747230496449562 0 + -0.6817319599697427 0 + -0.6576711592166908 -0.7745966692414833 + -0.6576711592166908 0 + -0.6576711592166908 0.7745966692414834 + -0.6133714327005902 -0.9061798459386639 + -0.6133714327005902 -0.7745966692414833 + -0.6133714327005902 -0.5384693101056832 + -0.6133714327005902 0 + -0.6133714327005902 0.538469310105683 + -0.6133714327005902 0.7745966692414834 + -0.6133714327005902 0.9061798459386639 + -0.6102423458363788 0 + -0.5384693101056832 -0.9681602395076263 + -0.5384693101056832 -0.9061798459386639 + -0.5384693101056832 -0.8360311073266359 + -0.5384693101056832 -0.7745966692414833 + -0.5384693101056832 -0.6133714327005902 + -0.5384693101056832 -0.5384693101056832 + -0.5384693101056832 -0.324253423403809 + -0.5384693101056832 0 + -0.5384693101056832 0.3242534234038088 + -0.5384693101056832 0.538469310105683 + -0.5384693101056832 0.6133714327005906 + -0.5384693101056832 0.7745966692414834 + -0.5384693101056832 0.8360311073266353 + -0.5384693101056832 0.9061798459386639 + -0.5384693101056832 0.9681602395076263 + -0.5333899047863476 0 + -0.5126905370864772 -0.7745966692414833 + -0.5126905370864772 0 + -0.5126905370864772 0.7745966692414834 + -0.4518500172724508 0 + -0.3663392577480732 0 + -0.3512317634538764 -0.7745966692414833 + -0.3512317634538764 0 + -0.3512317634538764 0.7745966692414834 + -0.324253423403809 -0.9061798459386639 + -0.324253423403809 -0.7745966692414833 + -0.324253423403809 -0.5384693101056832 + -0.324253423403809 0 + -0.324253423403809 0.538469310105683 + -0.324253423403809 0.7745966692414834 + -0.324253423403809 0.9061798459386639 + -0.2776090971524972 0 + -0.1864392988279915 0 + -0.1784841814958477 -0.7745966692414833 + -0.1784841814958477 0 + -0.1784841814958477 0.7745966692414834 + -0.09363106585473335 0 + 0 -0.9974246942464551 + 0 -0.9905754753144171 + 0 -0.9864557262306423 + 0 -0.9681602395076263 + 0 -0.9668229096899926 + 0 -0.9506755217687676 + 0 -0.9386943726111682 + 0 -0.9061798459386639 + 0 -0.9023167677434333 + 0 -0.8802391537269858 + 0 -0.8580096526765038 + 0 -0.8360311073266359 + 0 -0.8061623562741663 + 0 -0.7815140038968014 + 0 -0.7745966692414833 + 0 -0.747230496449562 + 0 -0.6817319599697427 + 0 -0.6576711592166908 + 0 -0.6133714327005902 + 0 -0.6102423458363788 + 0 -0.5384693101056832 + 0 -0.5333899047863476 + 0 -0.5126905370864772 + 0 -0.4518500172724508 + 0 -0.3663392577480732 + 0 -0.3512317634538764 + 0 -0.324253423403809 + 0 -0.2776090971524972 + 0 -0.1864392988279915 + 0 -0.1784841814958477 + 0 -0.09363106585473335 + 0 0 + 0 0.09363106585473302 + 0 0.1784841814958473 + 0 0.1864392988279913 + 0 0.2776090971524967 + 0 0.3242534234038088 + 0 0.3512317634538762 + 0 0.3663392577480735 + 0 0.4518500172724509 + 0 0.5126905370864772 + 0 0.5333899047863477 + 0 0.538469310105683 + 0 0.610242345836379 + 0 0.6133714327005906 + 0 0.6576711592166908 + 0 0.6817319599697425 + 0 0.7472304964495624 + 0 0.7745966692414834 + 0 0.7815140038968016 + 0 0.8061623562741662 + 0 0.8360311073266353 + 0 0.858009652676504 + 0 0.880239153726986 + 0 0.9023167677434336 + 0 0.9061798459386639 + 0 0.9386943726111685 + 0 0.9506755217687677 + 0 0.9668229096899932 + 0 0.9681602395076263 + 0 0.9864557262306426 + 0 0.9905754753144174 + 0 0.9974246942464551 + 0.09363106585473302 0 + 0.1784841814958473 -0.7745966692414833 + 0.1784841814958473 0 + 0.1784841814958473 0.7745966692414834 + 0.1864392988279913 0 + 0.2776090971524967 0 + 0.3242534234038088 -0.9061798459386639 + 0.3242534234038088 -0.7745966692414833 + 0.3242534234038088 -0.5384693101056832 + 0.3242534234038088 0 + 0.3242534234038088 0.538469310105683 + 0.3242534234038088 0.7745966692414834 + 0.3242534234038088 0.9061798459386639 + 0.3512317634538762 -0.7745966692414833 + 0.3512317634538762 0 + 0.3512317634538762 0.7745966692414834 + 0.3663392577480735 0 + 0.4518500172724509 0 + 0.5126905370864772 -0.7745966692414833 + 0.5126905370864772 0 + 0.5126905370864772 0.7745966692414834 + 0.5333899047863477 0 + 0.538469310105683 -0.9681602395076263 + 0.538469310105683 -0.9061798459386639 + 0.538469310105683 -0.8360311073266359 + 0.538469310105683 -0.7745966692414833 + 0.538469310105683 -0.6133714327005902 + 0.538469310105683 -0.5384693101056832 + 0.538469310105683 -0.324253423403809 + 0.538469310105683 0 + 0.538469310105683 0.3242534234038088 + 0.538469310105683 0.538469310105683 + 0.538469310105683 0.6133714327005906 + 0.538469310105683 0.7745966692414834 + 0.538469310105683 0.8360311073266353 + 0.538469310105683 0.9061798459386639 + 0.538469310105683 0.9681602395076263 + 0.610242345836379 0 + 0.6133714327005906 -0.9061798459386639 + 0.6133714327005906 -0.7745966692414833 + 0.6133714327005906 -0.5384693101056832 + 0.6133714327005906 0 + 0.6133714327005906 0.538469310105683 + 0.6133714327005906 0.7745966692414834 + 0.6133714327005906 0.9061798459386639 + 0.6576711592166908 -0.7745966692414833 + 0.6576711592166908 0 + 0.6576711592166908 0.7745966692414834 + 0.6817319599697425 0 + 0.7472304964495624 0 + 0.7745966692414834 -0.9905754753144171 + 0.7745966692414834 -0.9681602395076263 + 0.7745966692414834 -0.9506755217687676 + 0.7745966692414834 -0.9061798459386639 + 0.7745966692414834 -0.8802391537269858 + 0.7745966692414834 -0.8360311073266359 + 0.7745966692414834 -0.7815140038968014 + 0.7745966692414834 -0.7745966692414833 + 0.7745966692414834 -0.6576711592166908 + 0.7745966692414834 -0.6133714327005902 + 0.7745966692414834 -0.5384693101056832 + 0.7745966692414834 -0.5126905370864772 + 0.7745966692414834 -0.3512317634538764 + 0.7745966692414834 -0.324253423403809 + 0.7745966692414834 -0.1784841814958477 + 0.7745966692414834 0 + 0.7745966692414834 0.1784841814958473 + 0.7745966692414834 0.3242534234038088 + 0.7745966692414834 0.3512317634538762 + 0.7745966692414834 0.5126905370864772 + 0.7745966692414834 0.538469310105683 + 0.7745966692414834 0.6133714327005906 + 0.7745966692414834 0.6576711592166908 + 0.7745966692414834 0.7745966692414834 + 0.7745966692414834 0.7815140038968016 + 0.7745966692414834 0.8360311073266353 + 0.7745966692414834 0.880239153726986 + 0.7745966692414834 0.9061798459386639 + 0.7745966692414834 0.9506755217687677 + 0.7745966692414834 0.9681602395076263 + 0.7745966692414834 0.9905754753144174 + 0.7815140038968016 -0.7745966692414833 + 0.7815140038968016 0 + 0.7815140038968016 0.7745966692414834 + 0.8061623562741662 0 + 0.8360311073266353 -0.9061798459386639 + 0.8360311073266353 -0.7745966692414833 + 0.8360311073266353 -0.5384693101056832 + 0.8360311073266353 0 + 0.8360311073266353 0.538469310105683 + 0.8360311073266353 0.7745966692414834 + 0.8360311073266353 0.9061798459386639 + 0.858009652676504 0 + 0.880239153726986 -0.7745966692414833 + 0.880239153726986 0 + 0.880239153726986 0.7745966692414834 + 0.9023167677434336 0 + 0.9061798459386639 -0.9681602395076263 + 0.9061798459386639 -0.9061798459386639 + 0.9061798459386639 -0.8360311073266359 + 0.9061798459386639 -0.7745966692414833 + 0.9061798459386639 -0.6133714327005902 + 0.9061798459386639 -0.5384693101056832 + 0.9061798459386639 -0.324253423403809 + 0.9061798459386639 0 + 0.9061798459386639 0.3242534234038088 + 0.9061798459386639 0.538469310105683 + 0.9061798459386639 0.6133714327005906 + 0.9061798459386639 0.7745966692414834 + 0.9061798459386639 0.8360311073266353 + 0.9061798459386639 0.9061798459386639 + 0.9061798459386639 0.9681602395076263 + 0.9386943726111685 0 + 0.9506755217687677 -0.7745966692414833 + 0.9506755217687677 0 + 0.9506755217687677 0.7745966692414834 + 0.9668229096899932 0 + 0.9681602395076263 -0.9061798459386639 + 0.9681602395076263 -0.7745966692414833 + 0.9681602395076263 -0.5384693101056832 + 0.9681602395076263 0 + 0.9681602395076263 0.538469310105683 + 0.9681602395076263 0.7745966692414834 + 0.9681602395076263 0.9061798459386639 + 0.9864557262306426 0 + 0.9905754753144174 -0.7745966692414833 + 0.9905754753144174 0 + 0.9905754753144174 0.7745966692414834 + 0.9974246942464551 0 diff --git a/cpp/tests/QuadLUTest/quadwghts.txt b/cpp/tests/QuadLUTest/quadwghts.txt new file mode 100644 index 00000000..f89f895c --- /dev/null +++ b/cpp/tests/QuadLUTest/quadwghts.txt @@ -0,0 +1,321 @@ + 0.003303113923788093 + 0.003353930953963978 + -0.006707861907927958 + 0.003353930953963977 + 0.007660850756463352 + 0.004814021917338943 + -0.01128810949466376 + 0.009725063111787956 + -0.006501951068926327 + 0.009725063111787946 + -0.01128810949466376 + 0.004814021917338943 + 0.01195777405087297 + 0.007702712413053281 + -0.01540542482610657 + 0.00770271241305328 + 0.01615017931616286 + 0.004814021917338943 + -0.01403358721560694 + 0.01070010150114059 + 0 + 0.01543642012776774 + -0.02834999999999981 + 0.01850085500487321 + -0.01413562267102675 + 0.01850085500487321 + -0.02834999999999979 + 0.01543642012776786 + 0 + 0.01070010150114035 + -0.01403358721560694 + 0.004814021917338824 + 0.02020077066583277 + 0.01181057615516362 + -0.02362115231032726 + 0.01181057615516362 + 0.02407387140935418 + 0.01070010150114059 + -0.02509002231873033 + 0.02161584724538402 + -0.01445185285558867 + 0.021615847245384 + -0.02509002231873032 + 0.01070010150114059 + 0.02773542331583067 + 0.01553942322130604 + -0.0310788464426121 + 0.01553942322130604 + 0.003353930953963978 + -0.01128810949466376 + 0.007702712413053281 + 0 + 0.01181057615516362 + -0.02509002231873033 + 0.01553942322130604 + 0 + 0.01876894006507305 + -0.0361959300559631 + 0 + 0.02139524459400154 + 0.02333390307728475 + -0.04338153847777817 + 0.02452259796763781 + -0.02094345620070185 + 0.0245225979676378 + -0.04338153847777816 + 0.02333390307728467 + 0.02139524459400154 + 0 + -0.03619593005596339 + 0.01876894006507305 + 0 + 0.01553942322130619 + -0.02509002231872977 + 0.01181057615516393 + 0 + 0.007702712413053542 + -0.01128810949466348 + 0.003353930953964847 + 0.0311532412651581 + 0.03429728640932805 + 0.01876894006507305 + -0.03753788013014613 + 0.01876894006507305 + 0.01543642012776774 + -0.0361959300559631 + 0.03118393778431267 + -0.02084885571223477 + 0.03118393778431264 + -0.0361959300559631 + 0.01543642012776774 + 0.03713992742197654 + 0.009725063111787956 + -0.02834999999999981 + 0.02161584724538402 + 0 + 0.03118393778431267 + -0.05727135105599791 + 0.03737456655450499 + -0.02855612727998237 + 0.03737456655450498 + -0.05727135105599785 + 0.03118393778431292 + 0 + 0.02161584724538354 + -0.02834999999999981 + 0.009725063111787717 + 0.03965618239744336 + 0.02139524459400154 + -0.04279048918800309 + 0.02139524459400153 + 0.04182393803351951 + 0.04362414380942199 + 0.02333390307728475 + -0.04666780615456952 + 0.02333390307728474 + 0.01850085500487321 + -0.04338153847777817 + 0.03737456655450499 + -0.02498776616320023 + 0.03737456655450495 + -0.04338153847777816 + 0.01850085500487321 + 0.0450409793303194 + 0.04606199332165845 + 0.02452259796763781 + -0.04904519593527564 + 0.02452259796763781 + 0.04667821303279804 + 0.003303113923788093 + -0.006707861907927958 + 0.007660850756463352 + -0.006501951068926329 + 0.01195777405087297 + -0.01540542482610657 + 0.01615017931616286 + -0.01413562267102673 + 0.02020077066583277 + -0.02362115231032726 + 0.02407387140935418 + -0.01445185285558867 + 0.02773542331583067 + -0.03107884644261211 + -0.02094345620070184 + 0.0311532412651581 + 0.03429728640932805 + -0.03753788013014613 + -0.02084885571223474 + 0.03713992742197654 + -0.02855612727998241 + 0.03965618239744336 + -0.04279048918800309 + 0.04182393803351951 + 0.04362414380942199 + -0.04666780615456952 + -0.02498776616320023 + 0.0450409793303194 + 0.04606199332165845 + -0.04904519593527564 + 0.04667821303279804 + -0.1396709761465258 + 0.04667821303279792 + -0.04904519593527563 + 0.04606199332165826 + 0.04504097933031906 + -0.02498776616320023 + -0.04666780615456937 + 0.0436241438094225 + 0.04182393803351974 + -0.04279048918800309 + 0.03965618239744336 + -0.02855612727998233 + 0.03713992742197743 + -0.02084885571223491 + -0.03753788013014613 + 0.03429728640932712 + 0.03115324126515921 + -0.0209434562007018 + -0.03107884644261239 + 0.02773542331583067 + -0.01445185285558836 + 0.0240738714093547 + -0.02362115231032787 + 0.02020077066583501 + -0.01413562267102674 + 0.01615017931616475 + -0.01540542482610709 + 0.01195777405087973 + -0.006501951068926162 + 0.007660850756469105 + -0.006707861907929697 + 0.003303113923793619 + 0.04667821303279792 + 0.0245225979676378 + -0.04904519593527562 + 0.0245225979676378 + 0.04606199332165826 + 0.04504097933031906 + 0.01850085500487321 + -0.04338153847777816 + 0.03737456655450498 + -0.02498776616320023 + 0.03737456655450495 + -0.04338153847777815 + 0.01850085500487321 + 0.02333390307728467 + -0.04666780615456936 + 0.02333390307728467 + 0.0436241438094225 + 0.04182393803351974 + 0.02139524459400154 + -0.04279048918800309 + 0.02139524459400153 + 0.03965618239744336 + 0.009725063111787946 + -0.02834999999999979 + 0.021615847245384 + 0 + 0.03118393778431264 + -0.05727135105599785 + 0.03737456655450495 + -0.02855612727998236 + 0.03737456655450495 + -0.05727135105599779 + 0.03118393778431288 + 0 + 0.02161584724538352 + -0.02834999999999979 + 0.009725063111787707 + 0.03713992742197743 + 0.01543642012776786 + -0.03619593005596339 + 0.03118393778431292 + -0.02084885571223492 + 0.03118393778431288 + -0.03619593005596338 + 0.01543642012776786 + 0.01876894006507305 + -0.03753788013014613 + 0.01876894006507305 + 0.03429728640932712 + 0.03115324126515921 + 0.003353930953963977 + -0.01128810949466376 + 0.00770271241305328 + 0 + 0.01181057615516362 + -0.02509002231873032 + 0.01553942322130604 + 0 + 0.01876894006507305 + -0.0361959300559631 + 0 + 0.02139524459400153 + 0.02333390307728474 + -0.04338153847777816 + 0.02452259796763781 + -0.02094345620070182 + 0.0245225979676378 + -0.04338153847777815 + 0.02333390307728467 + 0.02139524459400153 + 0 + -0.03619593005596338 + 0.01876894006507305 + 0 + 0.01553942322130619 + -0.02509002231872976 + 0.01181057615516393 + 0 + 0.007702712413053541 + -0.01128810949466348 + 0.003353930953964847 + 0.01553942322130619 + -0.03107884644261239 + 0.01553942322130619 + 0.02773542331583067 + 0.01070010150114035 + -0.02509002231872977 + 0.02161584724538354 + -0.01445185285558834 + 0.02161584724538352 + -0.02509002231872976 + 0.01070010150114035 + 0.0240738714093547 + 0.01181057615516393 + -0.02362115231032787 + 0.01181057615516393 + 0.02020077066583501 + 0.004814021917338943 + -0.01403358721560694 + 0.01070010150114059 + 0 + 0.01543642012776774 + -0.02834999999999981 + 0.01850085500487321 + -0.01413562267102673 + 0.01850085500487321 + -0.02834999999999979 + 0.01543642012776786 + 0 + 0.01070010150114035 + -0.01403358721560694 + 0.004814021917338824 + 0.01615017931616475 + 0.007702712413053542 + -0.01540542482610709 + 0.007702712413053541 + 0.01195777405087973 + 0.004814021917338824 + -0.01128810949466348 + 0.009725063111787717 + -0.006501951068926162 + 0.009725063111787707 + -0.01128810949466348 + 0.004814021917338824 + 0.007660850756469105 + 0.003353930953964847 + -0.006707861907929697 + 0.003353930953964847 + 0.003303113923793619 diff --git a/cpp/tests/SecondDeriv1dTest/CMakeLists.txt b/cpp/tests/SecondDeriv1dTest/CMakeLists.txt new file mode 100644 index 00000000..504b0500 --- /dev/null +++ b/cpp/tests/SecondDeriv1dTest/CMakeLists.txt @@ -0,0 +1,58 @@ +project (UQTk) + +add_executable (SecondDeriv1dTest main.cpp) + +target_link_libraries (SecondDeriv1dTest uqtk ) + +target_link_libraries (SecondDeriv1dTest depdsfmt ) +target_link_libraries (SecondDeriv1dTest depcvode ) +target_link_libraries (SecondDeriv1dTest depnvec ) +target_link_libraries (SecondDeriv1dTest depslatec) +target_link_libraries (SecondDeriv1dTest deplapack) +target_link_libraries (SecondDeriv1dTest depblas ) +target_link_libraries (SecondDeriv1dTest deplbfgs ) +target_link_libraries (SecondDeriv1dTest depfigtree ) +target_link_libraries (SecondDeriv1dTest depann ) + +# Link fortran libraries +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # using GCC + target_link_libraries (SecondDeriv1dTest gfortran expat stdc++) +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + # using Intel + if ("${IntelLibPath}" STREQUAL "") + target_link_libraries (SecondDeriv1dTest ifcore ifport) + else() + target_link_libraries (SecondDeriv1dTest ${IntelLibPath}/libifcore.a) + target_link_libraries (SecondDeriv1dTest ${IntelLibPath}/libifport.a) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # using Clang + if ("${ClangLibPath}" STREQUAL "") + target_link_libraries (SecondDeriv1dTest gfortran stdc++) + else() + target_link_libraries (SecondDeriv1dTest ${ClangLibPath}/libgfortran.dylib ${ClangLibPath}/libstdc++.dylib) + endif() +endif() + +link_directories(${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/src/cvode) + +include_directories(../../lib/pce ) +include_directories(../../lib/array ) +include_directories(../../lib/include) +include_directories(../../lib/quad ) +include_directories(../../lib/tools ) +include_directories(../../lib/mcmc ) + +include_directories(../../../dep/dsfmt) +include_directories(../../../dep/lapack) +include_directories(../../../dep/blas) +include_directories(../../../dep/slatec) +include_directories(../../../dep/lbfgs) +include_directories(../../../dep/cvode-2.7.0/include) + +include_directories("${PROJECT_BINARY_DIR}/../../../dep/cvode-2.7.0/include") + +INSTALL(TARGETS SecondDeriv1dTest DESTINATION bin/tests/) + +add_test(SecondDeriv1dTest SecondDeriv1dTest) diff --git a/cpp/tests/SecondDeriv1dTest/main.cpp b/cpp/tests/SecondDeriv1dTest/main.cpp new file mode 100644 index 00000000..575e50f3 --- /dev/null +++ b/cpp/tests/SecondDeriv1dTest/main.cpp @@ -0,0 +1,78 @@ +/* ===================================================================================== + The UQ Toolkit (UQTk) version 3.0.4 + Copyright (2017) Sandia Corporation + http://www.sandia.gov/UQToolkit/ + + Copyright (2017) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 + with Sandia Corporation, the U.S. Government retains certain rights in this software. + + This file is part of The UQ Toolkit (UQTk) + + UQTk 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 3 of the License, or + (at your option) any later version. + + UQTk 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 UQTk. If not, see . + + Questions? Contact Bert Debusschere + Sandia National Laboratories, Livermore, CA, USA +===================================================================================== */ +#include +#include "math.h" +#include "Array1D.h" +#include "Array2D.h" +#include "dsfmt_add.h" +#include "arrayio.h" +#include "arraytools.h" +#include "PCBasis.h" +#include "PCSet.h" +#include "quad.h" +#include "assert.h" + +using namespace std; + +/************************************************* +Begin main code +*************************************************/ +int main(int argc, char ** argv){ + + /******************************************** + ********************************************/ + + // get 1d legendre polynomials + int ndim = 3; + int norder = 4; + PCSet polymodel("NISPnoq",norder,ndim,"LU"); + polymodel.PrintMultiIndex(); + + // define alpha, which is a specific multiindex + Array1D alpha(ndim); + alpha(0) = 1; + alpha(1) = 3; + alpha(2) = 2; + + // define evaluation point and gradient + Array1D x(3,1); + Array1D grad; + + // get derivative of 3d legendre polynomial + // defined by the multiindex above + polymodel.dPhi_alpha(x, alpha, grad); + printarray(grad); + assert(grad(0) == 1.0); + assert(grad(1) == 6.0); + assert(grad(2) == 3.0); + + + + + return 0; + +} diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt new file mode 100644 index 00000000..ba339517 --- /dev/null +++ b/dep/CMakeLists.txt @@ -0,0 +1,33 @@ +project (UQTk) + +enable_language(Fortran) +enable_language(CXX) + +add_subdirectory (slatec) +add_subdirectory (blas) +add_subdirectory (lapack) +add_subdirectory (dsfmt) +add_subdirectory (lbfgs) +add_subdirectory (cvode-2.7.0) +add_subdirectory (ann) +add_subdirectory (figtree) + +FILE(GLOB slatecsrc "slatec/*.f") +FILE(GLOB blassrc "blas/*.f") +FILE(GLOB lapacksrc "lapack/*.f") +FILE(GLOB dsfmtsrc "dsfmt/*.c") +FILE(GLOB lbfgsCsrc "lbfgs/lbfgsDR.c") +FILE(GLOB lbfgsFsrc "lbfgs/lbfgs_routines.f") +FILE(GLOB annsrc "ann/*.cpp") +FILE(GLOB figtreesrc "figtree/*.cpp") + + +include_directories (dsfmt) +include_directories (lbfgs) +include_directories (ann) +include_directories (figtree) +include_directories("../cpp/lib/include") + +add_library(depuqtk ${slatecsrc} ${blassrc} ${lapacksrc} ${dsfmtsrc} ${lbfgsCsrc} ${lbfgsFsrc} ${annsrc} ${figtreesrc}) + +INSTALL(TARGETS depuqtk DESTINATION lib) diff --git a/dep/ann/ANN.cpp b/dep/ann/ANN.cpp new file mode 100644 index 00000000..634e8718 --- /dev/null +++ b/dep/ann/ANN.cpp @@ -0,0 +1,201 @@ +//---------------------------------------------------------------------- +// File: ANN.cpp +// Programmer: Sunil Arya and David Mount +// Description: Methods for ANN.h and ANNx.h +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added performance counting to annDist() +// Revision 2010/05/12 by Vlad Morariu +// Added stdlib.h and string.h includes to for exit(). +//---------------------------------------------------------------------- + +#include "ANNx.h" // all ANN includes +#include "ANNperf.h" // ANN performance +#include // added by Vlad 2010/05/12 for exit() + +using namespace std; // make std:: accessible + +//---------------------------------------------------------------------- +// Point methods +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Distance utility. +// (Note: In the nearest neighbor search, most distances are +// computed using partial distance calculations, not this +// procedure.) +//---------------------------------------------------------------------- + +ANNdist annDist( // interpoint squared distance + int dim, + ANNpoint p, + ANNpoint q) +{ + register int d; + register ANNcoord diff; + register ANNcoord dist; + + dist = 0; + for (d = 0; d < dim; d++) { + diff = p[d] - q[d]; + dist = ANN_SUM(dist, ANN_POW(diff)); + } + ANN_FLOP(3*dim) // performance counts + ANN_PTS(1) + ANN_COORD(dim) + return dist; +} + +//---------------------------------------------------------------------- +// annPrintPoint() prints a point to a given output stream. +//---------------------------------------------------------------------- + +void annPrintPt( // print a point + ANNpoint pt, // the point + int dim, // the dimension + std::ostream &out) // output stream +{ + for (int j = 0; j < dim; j++) { + out << pt[j]; + if (j < dim-1) out << " "; + } +} + +//---------------------------------------------------------------------- +// Point allocation/deallocation: +// +// Because points (somewhat like strings in C) are stored +// as pointers. Consequently, creating and destroying +// copies of points may require storage allocation. These +// procedures do this. +// +// annAllocPt() and annDeallocPt() allocate a deallocate +// storage for a single point, and return a pointer to it. +// +// annAllocPts() allocates an array of points as well a place +// to store their coordinates, and initializes the points to +// point to their respective coordinates. It allocates point +// storage in a contiguous block large enough to store all the +// points. It performs no initialization. +// +// annDeallocPts() should only be used on point arrays allocated +// by annAllocPts since it assumes that points are allocated in +// a block. +// +// annCopyPt() copies a point taking care to allocate storage +// for the new point. +// +// annAssignRect() assigns the coordinates of one rectangle to +// another. The two rectangles must have the same dimension +// (and it is not possible to test this here). +//---------------------------------------------------------------------- + +ANNpoint annAllocPt(int dim, ANNcoord c) // allocate 1 point +{ + ANNpoint p = new ANNcoord[dim]; + for (int i = 0; i < dim; i++) p[i] = c; + return p; +} + +ANNpointArray annAllocPts(int n, int dim) // allocate n pts in dim +{ + ANNpointArray pa = new ANNpoint[n]; // allocate points + ANNpoint p = new ANNcoord[n*dim]; // allocate space for coords + for (int i = 0; i < n; i++) { + pa[i] = &(p[i*dim]); + } + return pa; +} + +void annDeallocPt(ANNpoint &p) // deallocate 1 point +{ + delete [] p; + p = NULL; +} + +void annDeallocPts(ANNpointArray &pa) // deallocate points +{ + delete [] pa[0]; // dealloc coordinate storage + delete [] pa; // dealloc points + pa = NULL; +} + +ANNpoint annCopyPt(int dim, ANNpoint source) // copy point +{ + ANNpoint p = new ANNcoord[dim]; + for (int i = 0; i < dim; i++) p[i] = source[i]; + return p; +} + + // assign one rect to another +void annAssignRect(int dim, ANNorthRect &dest, const ANNorthRect &source) +{ + for (int i = 0; i < dim; i++) { + dest.lo[i] = source.lo[i]; + dest.hi[i] = source.hi[i]; + } +} + + // is point inside rectangle? +ANNbool ANNorthRect::inside(int dim, ANNpoint p) +{ + for (int i = 0; i < dim; i++) { + if (p[i] < lo[i] || p[i] > hi[i]) return ANNfalse; + } + return ANNtrue; +} + +//---------------------------------------------------------------------- +// Error handler +//---------------------------------------------------------------------- + +void annError(char *msg, ANNerr level) +{ + if (level == ANNabort) { + cerr << "ANN: ERROR------->" << msg << "<-------------ERROR\n"; + exit(1); + } + else { + cerr << "ANN: WARNING----->" << msg << "<-------------WARNING\n"; + } +} + +//---------------------------------------------------------------------- +// Limit on number of points visited +// We have an option for terminating the search early if the +// number of points visited exceeds some threshold. If the +// threshold is 0 (its default) this means there is no limit +// and the algorithm applies its normal termination condition. +// This is for applications where there are real time constraints +// on the running time of the algorithm. +//---------------------------------------------------------------------- + +int ANNmaxPtsVisited = 0; // maximum number of pts visited +int ANNptsVisited; // number of pts visited in search + +//---------------------------------------------------------------------- +// Global function declarations +//---------------------------------------------------------------------- + +void annMaxPtsVisit( // set limit on max. pts to visit in search + int maxPts) // the limit +{ + ANNmaxPtsVisited = maxPts; +} diff --git a/dep/ann/ANN.h b/dep/ann/ANN.h new file mode 100644 index 00000000..152c2975 --- /dev/null +++ b/dep/ann/ANN.h @@ -0,0 +1,855 @@ +//---------------------------------------------------------------------- +// File: ANN.h +// Programmer: Sunil Arya and David Mount +// Last modified: 05/03/05 (Release 1.1) +// Description: Basic include file for approximate nearest +// neighbor searching. +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added copyright and revision information +// Added ANNcoordPrec for coordinate precision. +// Added methods theDim, nPoints, maxPoints, thePoints to ANNpointSet. +// Cleaned up C++ structure for modern compilers +// Revision 1.1 05/03/05 +// Added fixed-radius k-NN searching +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// ANN - approximate nearest neighbor searching +// ANN is a library for approximate nearest neighbor searching, +// based on the use of standard and priority search in kd-trees +// and balanced box-decomposition (bbd) trees. Here are some +// references to the main algorithmic techniques used here: +// +// kd-trees: +// Friedman, Bentley, and Finkel, ``An algorithm for finding +// best matches in logarithmic expected time,'' ACM +// Transactions on Mathematical Software, 3(3):209-226, 1977. +// +// Priority search in kd-trees: +// Arya and Mount, ``Algorithms for fast vector quantization,'' +// Proc. of DCC '93: Data Compression Conference, eds. J. A. +// Storer and M. Cohn, IEEE Press, 1993, 381-390. +// +// Approximate nearest neighbor search and bbd-trees: +// Arya, Mount, Netanyahu, Silverman, and Wu, ``An optimal +// algorithm for approximate nearest neighbor searching,'' +// 5th Ann. ACM-SIAM Symposium on Discrete Algorithms, +// 1994, 573-582. +//---------------------------------------------------------------------- + +#ifndef ANN_H +#define ANN_H + +#ifdef WIN32 + //---------------------------------------------------------------------- + // For Microsoft Visual C++, externally accessible symbols must be + // explicitly indicated with DLL_API, which is somewhat like "extern." + // + // The following ifdef block is the standard way of creating macros + // which make exporting from a DLL simpler. All files within this DLL + // are compiled with the DLL_EXPORTS preprocessor symbol defined on the + // command line. In contrast, projects that use (or import) the DLL + // objects do not define the DLL_EXPORTS symbol. This way any other + // project whose source files include this file see DLL_API functions as + // being imported from a DLL, wheras this DLL sees symbols defined with + // this macro as being exported. + //---------------------------------------------------------------------- + #ifdef DLL_EXPORTS + #define DLL_API __declspec(dllexport) + #else + #define DLL_API __declspec(dllimport) + #endif + //---------------------------------------------------------------------- + // DLL_API is ignored for all other systems + //---------------------------------------------------------------------- +#else + #define DLL_API +#endif + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- + +#include // math includes +#include // I/O streams + +//---------------------------------------------------------------------- +// Limits +// There are a number of places where we use the maximum double value as +// default initializers (and others may be used, depending on the +// data/distance representation). These can usually be found in limits.h +// (as LONG_MAX, INT_MAX) or in float.h (as DBL_MAX, FLT_MAX). +// +// Not all systems have these files. If you are using such a system, +// you should set the preprocessor symbol ANN_NO_LIMITS_H when +// compiling, and modify the statements below to generate the +// appropriate value. For practical purposes, this does not need to be +// the maximum double value. It is sufficient that it be at least as +// large than the maximum squared distance between between any two +// points. +//---------------------------------------------------------------------- +#ifdef ANN_NO_LIMITS_H // limits.h unavailable + #include // replacement for limits.h + const double ANN_DBL_MAX = MAXDOUBLE; // insert maximum double +#else + #include + #include + const double ANN_DBL_MAX = DBL_MAX; +#endif + +#define ANNversion "1.1.1" // ANN version and information +#define ANNversionCmt "" +#define ANNcopyright "David M. Mount and Sunil Arya" +#define ANNlatestRev "Aug 4, 2006" + +//---------------------------------------------------------------------- +// ANNbool +// This is a simple boolean type. Although ANSI C++ is supposed +// to support the type bool, some compilers do not have it. +//---------------------------------------------------------------------- + +enum ANNbool {ANNfalse = 0, ANNtrue = 1}; // ANN boolean type (non ANSI C++) + +//---------------------------------------------------------------------- +// ANNcoord, ANNdist +// ANNcoord and ANNdist are the types used for representing +// point coordinates and distances. They can be modified by the +// user, with some care. It is assumed that they are both numeric +// types, and that ANNdist is generally of an equal or higher type +// from ANNcoord. A variable of type ANNdist should be large +// enough to store the sum of squared components of a variable +// of type ANNcoord for the number of dimensions needed in the +// application. For example, the following combinations are +// legal: +// +// ANNcoord ANNdist +// --------- ------------------------------- +// short short, int, long, float, double +// int int, long, float, double +// long long, float, double +// float float, double +// double double +// +// It is the user's responsibility to make sure that overflow does +// not occur in distance calculation. +//---------------------------------------------------------------------- + +typedef double ANNcoord; // coordinate data type +typedef double ANNdist; // distance data type + +//---------------------------------------------------------------------- +// ANNidx +// ANNidx is a point index. When the data structure is built, the +// points are given as an array. Nearest neighbor results are +// returned as an integer index into this array. To make it +// clearer when this is happening, we define the integer type +// ANNidx. Indexing starts from 0. +// +// For fixed-radius near neighbor searching, it is possible that +// there are not k nearest neighbors within the search radius. To +// indicate this, the algorithm returns ANN_NULL_IDX as its result. +// It should be distinguishable from any valid array index. +//---------------------------------------------------------------------- + +typedef int ANNidx; // point index +const ANNidx ANN_NULL_IDX = -1; // a NULL point index + +//---------------------------------------------------------------------- +// Infinite distance: +// The code assumes that there is an "infinite distance" which it +// uses to initialize distances before performing nearest neighbor +// searches. It should be as larger or larger than any legitimate +// nearest neighbor distance. +// +// On most systems, these should be found in the standard include +// file or possibly . If you do not have these +// file, some suggested values are listed below, assuming 64-bit +// long, 32-bit int and 16-bit short. +// +// ANNdist ANN_DIST_INF Values (see or ) +// ------- ------------ ------------------------------------ +// double DBL_MAX 1.79769313486231570e+308 +// float FLT_MAX 3.40282346638528860e+38 +// long LONG_MAX 0x7fffffffffffffff +// int INT_MAX 0x7fffffff +// short SHRT_MAX 0x7fff +//---------------------------------------------------------------------- + +const ANNdist ANN_DIST_INF = ANN_DBL_MAX; + +//---------------------------------------------------------------------- +// Significant digits for tree dumps: +// When floating point coordinates are used, the routine that dumps +// a tree needs to know roughly how many significant digits there +// are in a ANNcoord, so it can output points to full precision. +// This is defined to be ANNcoordPrec. On most systems these +// values can be found in the standard include files or +// . For integer types, the value is essentially ignored. +// +// ANNcoord ANNcoordPrec Values (see or ) +// -------- ------------ ------------------------------------ +// double DBL_DIG 15 +// float FLT_DIG 6 +// long doesn't matter 19 +// int doesn't matter 10 +// short doesn't matter 5 +//---------------------------------------------------------------------- + +#ifdef DBL_DIG // number of sig. bits in ANNcoord + const int ANNcoordPrec = DBL_DIG; +#else + const int ANNcoordPrec = 15; // default precision +#endif + +//---------------------------------------------------------------------- +// Self match? +// In some applications, the nearest neighbor of a point is not +// allowed to be the point itself. This occurs, for example, when +// computing all nearest neighbors in a set. By setting the +// parameter ANN_ALLOW_SELF_MATCH to ANNfalse, the nearest neighbor +// is the closest point whose distance from the query point is +// strictly positive. +//---------------------------------------------------------------------- + +const ANNbool ANN_ALLOW_SELF_MATCH = ANNtrue; + +//---------------------------------------------------------------------- +// Norms and metrics: +// ANN supports any Minkowski norm for defining distance. In +// particular, for any p >= 1, the L_p Minkowski norm defines the +// length of a d-vector (v0, v1, ..., v(d-1)) to be +// +// (|v0|^p + |v1|^p + ... + |v(d-1)|^p)^(1/p), +// +// (where ^ denotes exponentiation, and |.| denotes absolute +// value). The distance between two points is defined to be the +// norm of the vector joining them. Some common distance metrics +// include +// +// Euclidean metric p = 2 +// Manhattan metric p = 1 +// Max metric p = infinity +// +// In the case of the max metric, the norm is computed by taking +// the maxima of the absolute values of the components. ANN is +// highly "coordinate-based" and does not support general distances +// functions (e.g. those obeying just the triangle inequality). It +// also does not support distance functions based on +// inner-products. +// +// For the purpose of computing nearest neighbors, it is not +// necessary to compute the final power (1/p). Thus the only +// component that is used by the program is |v(i)|^p. +// +// ANN parameterizes the distance computation through the following +// macros. (Macros are used rather than procedures for +// efficiency.) Recall that the distance between two points is +// given by the length of the vector joining them, and the length +// or norm of a vector v is given by formula: +// +// |v| = ROOT(POW(v0) # POW(v1) # ... # POW(v(d-1))) +// +// where ROOT, POW are unary functions and # is an associative and +// commutative binary operator mapping the following types: +// +// ** POW: ANNcoord --> ANNdist +// ** #: ANNdist x ANNdist --> ANNdist +// ** ROOT: ANNdist (>0) --> double +// +// For early termination in distance calculation (partial distance +// calculation) we assume that POW and # together are monotonically +// increasing on sequences of arguments, meaning that for all +// v0..vk and y: +// +// POW(v0) #...# POW(vk) <= (POW(v0) #...# POW(vk)) # POW(y). +// +// Incremental Distance Calculation: +// The program uses an optimized method of computing distances for +// kd-trees and bd-trees, called incremental distance calculation. +// It is used when distances are to be updated when only a single +// coordinate of a point has been changed. In order to use this, +// we assume that there is an incremental update function DIFF(x,y) +// for #, such that if: +// +// s = x0 # ... # xi # ... # xk +// +// then if s' is equal to s but with xi replaced by y, that is, +// +// s' = x0 # ... # y # ... # xk +// +// then the length of s' can be computed by: +// +// |s'| = |s| # DIFF(xi,y). +// +// Thus, if # is + then DIFF(xi,y) is (yi-x). For the L_infinity +// norm we make use of the fact that in the program this function +// is only invoked when y > xi, and hence DIFF(xi,y)=y. +// +// Finally, for approximate nearest neighbor queries we assume +// that POW and ROOT are related such that +// +// v*ROOT(x) = ROOT(POW(v)*x) +// +// Here are the values for the various Minkowski norms: +// +// L_p: p even: p odd: +// ------------------------- ------------------------ +// POW(v) = v^p POW(v) = |v|^p +// ROOT(x) = x^(1/p) ROOT(x) = x^(1/p) +// # = + # = + +// DIFF(x,y) = y - x DIFF(x,y) = y - x +// +// L_inf: +// POW(v) = |v| +// ROOT(x) = x +// # = max +// DIFF(x,y) = y +// +// By default the Euclidean norm is assumed. To change the norm, +// uncomment the appropriate set of macros below. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Use the following for the Euclidean norm +//---------------------------------------------------------------------- +#define ANN_POW(v) ((v)*(v)) +#define ANN_ROOT(x) sqrt(x) +#define ANN_SUM(x,y) ((x) + (y)) +#define ANN_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Use the following for the L_1 (Manhattan) norm +//---------------------------------------------------------------------- +// #define ANN_POW(v) fabs(v) +// #define ANN_ROOT(x) (x) +// #define ANN_SUM(x,y) ((x) + (y)) +// #define ANN_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Use the following for a general L_p norm +//---------------------------------------------------------------------- +// #define ANN_POW(v) pow(fabs(v),p) +// #define ANN_ROOT(x) pow(fabs(x),1/p) +// #define ANN_SUM(x,y) ((x) + (y)) +// #define ANN_DIFF(x,y) ((y) - (x)) + +//---------------------------------------------------------------------- +// Use the following for the L_infinity (Max) norm +//---------------------------------------------------------------------- +// #define ANN_POW(v) fabs(v) +// #define ANN_ROOT(x) (x) +// #define ANN_SUM(x,y) ((x) > (y) ? (x) : (y)) +// #define ANN_DIFF(x,y) (y) + +//---------------------------------------------------------------------- +// Array types +// The following array types are of basic interest. A point is +// just a dimensionless array of coordinates, a point array is a +// dimensionless array of points. A distance array is a +// dimensionless array of distances and an index array is a +// dimensionless array of point indices. The latter two are used +// when returning the results of k-nearest neighbor queries. +//---------------------------------------------------------------------- + +typedef ANNcoord* ANNpoint; // a point +typedef ANNpoint* ANNpointArray; // an array of points +typedef ANNdist* ANNdistArray; // an array of distances +typedef ANNidx* ANNidxArray; // an array of point indices + +//---------------------------------------------------------------------- +// Basic point and array utilities: +// The following procedures are useful supplements to ANN's nearest +// neighbor capabilities. +// +// annDist(): +// Computes the (squared) distance between a pair of points. +// Note that this routine is not used internally by ANN for +// computing distance calculations. For reasons of efficiency +// this is done using incremental distance calculation. Thus, +// this routine cannot be modified as a method of changing the +// metric. +// +// Because points (somewhat like strings in C) are stored as +// pointers. Consequently, creating and destroying copies of +// points may require storage allocation. These procedures do +// this. +// +// annAllocPt() and annDeallocPt(): +// Allocate a deallocate storage for a single point, and +// return a pointer to it. The argument to AllocPt() is +// used to initialize all components. +// +// annAllocPts() and annDeallocPts(): +// Allocate and deallocate an array of points as well a +// place to store their coordinates, and initializes the +// points to point to their respective coordinates. It +// allocates point storage in a contiguous block large +// enough to store all the points. It performs no +// initialization. +// +// annCopyPt(): +// Creates a copy of a given point, allocating space for +// the new point. It returns a pointer to the newly +// allocated copy. +//---------------------------------------------------------------------- + +DLL_API ANNdist annDist( + int dim, // dimension of space + ANNpoint p, // points + ANNpoint q); + +DLL_API ANNpoint annAllocPt( + int dim, // dimension + ANNcoord c = 0); // coordinate value (all equal) + +DLL_API ANNpointArray annAllocPts( + int n, // number of points + int dim); // dimension + +DLL_API void annDeallocPt( + ANNpoint &p); // deallocate 1 point + +DLL_API void annDeallocPts( + ANNpointArray &pa); // point array + +DLL_API ANNpoint annCopyPt( + int dim, // dimension + ANNpoint source); // point to copy + +//---------------------------------------------------------------------- +//Overall structure: ANN supports a number of different data structures +//for approximate and exact nearest neighbor searching. These are: +// +// ANNbruteForce A simple brute-force search structure. +// ANNkd_tree A kd-tree tree search structure. ANNbd_tree +// A bd-tree tree search structure (a kd-tree with shrink +// capabilities). +// +// At a minimum, each of these data structures support k-nearest +// neighbor queries. The nearest neighbor query, annkSearch, +// returns an integer identifier and the distance to the nearest +// neighbor(s) and annRangeSearch returns the nearest points that +// lie within a given query ball. +// +// Each structure is built by invoking the appropriate constructor +// and passing it (at a minimum) the array of points, the total +// number of points and the dimension of the space. Each structure +// is also assumed to support a destructor and member functions +// that return basic information about the point set. +// +// Note that the array of points is not copied by the data +// structure (for reasons of space efficiency), and it is assumed +// to be constant throughout the lifetime of the search structure. +// +// The search algorithm, annkSearch, is given the query point (q), +// and the desired number of nearest neighbors to report (k), and +// the error bound (eps) (whose default value is 0, implying exact +// nearest neighbors). It returns two arrays which are assumed to +// contain at least k elements: one (nn_idx) contains the indices +// (within the point array) of the nearest neighbors and the other +// (dd) contains the squared distances to these nearest neighbors. +// +// The search algorithm, annkFRSearch, is a fixed-radius kNN +// search. In addition to a query point, it is given a (squared) +// radius bound. (This is done for consistency, because the search +// returns distances as squared quantities.) It does two things. +// First, it computes the k nearest neighbors within the radius +// bound, and second, it returns the total number of points lying +// within the radius bound. It is permitted to set k = 0, in which +// case it effectively answers a range counting query. If the +// error bound epsilon is positive, then the search is approximate +// in the sense that it is free to ignore any point that lies +// outside a ball of radius r/(1+epsilon), where r is the given +// (unsquared) radius bound. +// +// The generic object from which all the search structures are +// dervied is given below. It is a virtual object, and is useless +// by itself. +//---------------------------------------------------------------------- + +class DLL_API ANNpointSet { +public: + virtual ~ANNpointSet() {} // virtual distructor + + virtual void annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0 // error bound + ) = 0; // pure virtual (defined elsewhere) + + virtual int annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // query point + ANNdist sqRad, // squared radius + int k = 0, // number of near neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0 // error bound + ) = 0; // pure virtual (defined elsewhere) + + virtual int theDim() = 0; // return dimension of space + virtual int nPoints() = 0; // return number of points + // return pointer to points + virtual ANNpointArray thePoints() = 0; +}; + +//---------------------------------------------------------------------- +// Brute-force nearest neighbor search: +// The brute-force search structure is very simple but inefficient. +// It has been provided primarily for the sake of comparison with +// and validation of the more complex search structures. +// +// Query processing is the same as described above, but the value +// of epsilon is ignored, since all distance calculations are +// performed exactly. +// +// WARNING: This data structure is very slow, and should not be +// used unless the number of points is very small. +// +// Internal information: +// --------------------- +// This data structure bascially consists of the array of points +// (each a pointer to an array of coordinates). The search is +// performed by a simple linear scan of all the points. +//---------------------------------------------------------------------- + +class DLL_API ANNbruteForce: public ANNpointSet { + int dim; // dimension + int n_pts; // number of points + ANNpointArray pts; // point array +public: + ANNbruteForce( // constructor from point array + ANNpointArray pa, // point array + int n, // number of points + int dd); // dimension + + ~ANNbruteForce(); // destructor + + void annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // query point + ANNdist sqRad, // squared radius + int k = 0, // number of near neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int theDim() // return dimension of space + { return dim; } + + int nPoints() // return number of points + { return n_pts; } + + ANNpointArray thePoints() // return pointer to points + { return pts; } +}; + +//---------------------------------------------------------------------- +// kd- and bd-tree splitting and shrinking rules +// kd-trees supports a collection of different splitting rules. +// In addition to the standard kd-tree splitting rule proposed +// by Friedman, Bentley, and Finkel, we have introduced a +// number of other splitting rules, which seem to perform +// as well or better (for the distributions we have tested). +// +// The splitting methods given below allow the user to tailor +// the data structure to the particular data set. They are +// are described in greater details in the kd_split.cc source +// file. The method ANN_KD_SUGGEST is the method chosen (rather +// subjectively) by the implementors as the one giving the +// fastest performance, and is the default splitting method. +// +// As with splitting rules, there are a number of different +// shrinking rules. The shrinking rule ANN_BD_NONE does no +// shrinking (and hence produces a kd-tree tree). The rule +// ANN_BD_SUGGEST uses the implementors favorite rule. +//---------------------------------------------------------------------- + +enum ANNsplitRule { + ANN_KD_STD = 0, // the optimized kd-splitting rule + ANN_KD_MIDPT = 1, // midpoint split + ANN_KD_FAIR = 2, // fair split + ANN_KD_SL_MIDPT = 3, // sliding midpoint splitting method + ANN_KD_SL_FAIR = 4, // sliding fair split method + ANN_KD_SUGGEST = 5}; // the authors' suggestion for best +const int ANN_N_SPLIT_RULES = 6; // number of split rules + +enum ANNshrinkRule { + ANN_BD_NONE = 0, // no shrinking at all (just kd-tree) + ANN_BD_SIMPLE = 1, // simple splitting + ANN_BD_CENTROID = 2, // centroid splitting + ANN_BD_SUGGEST = 3}; // the authors' suggested choice +const int ANN_N_SHRINK_RULES = 4; // number of shrink rules + +//---------------------------------------------------------------------- +// kd-tree: +// The main search data structure supported by ANN is a kd-tree. +// The main constructor is given a set of points and a choice of +// splitting method to use in building the tree. +// +// Construction: +// ------------- +// The constructor is given the point array, number of points, +// dimension, bucket size (default = 1), and the splitting rule +// (default = ANN_KD_SUGGEST). The point array is not copied, and +// is assumed to be kept constant throughout the lifetime of the +// search structure. There is also a "load" constructor that +// builds a tree from a file description that was created by the +// Dump operation. +// +// Search: +// ------- +// There are two search methods: +// +// Standard search (annkSearch()): +// Searches nodes in tree-traversal order, always visiting +// the closer child first. +// Priority search (annkPriSearch()): +// Searches nodes in order of increasing distance of the +// associated cell from the query point. For many +// distributions the standard search seems to work just +// fine, but priority search is safer for worst-case +// performance. +// +// Printing: +// --------- +// There are two methods provided for printing the tree. Print() +// is used to produce a "human-readable" display of the tree, with +// indenation, which is handy for debugging. Dump() produces a +// format that is suitable reading by another program. There is a +// "load" constructor, which constructs a tree which is assumed to +// have been saved by the Dump() procedure. +// +// Performance and Structure Statistics: +// ------------------------------------- +// The procedure getStats() collects statistics information on the +// tree (its size, height, etc.) See ANNperf.h for information on +// the stats structure it returns. +// +// Internal information: +// --------------------- +// The data structure consists of three major chunks of storage. +// The first (implicit) storage are the points themselves (pts), +// which have been provided by the users as an argument to the +// constructor, or are allocated dynamically if the tree is built +// using the load constructor). These should not be changed during +// the lifetime of the search structure. It is the user's +// responsibility to delete these after the tree is destroyed. +// +// The second is the tree itself (which is dynamically allocated in +// the constructor) and is given as a pointer to its root node +// (root). These nodes are automatically deallocated when the tree +// is deleted. See the file src/kd_tree.h for further information +// on the structure of the tree nodes. +// +// Each leaf of the tree does not contain a pointer directly to a +// point, but rather contains a pointer to a "bucket", which is an +// array consisting of point indices. The third major chunk of +// storage is an array (pidx), which is a large array in which all +// these bucket subarrays reside. (The reason for storing them +// separately is the buckets are typically small, but of varying +// sizes. This was done to avoid fragmentation.) This array is +// also deallocated when the tree is deleted. +// +// In addition to this, the tree consists of a number of other +// pieces of information which are used in searching and for +// subsequent tree operations. These consist of the following: +// +// dim Dimension of space +// n_pts Number of points currently in the tree +// n_max Maximum number of points that are allowed +// in the tree +// bkt_size Maximum bucket size (no. of points per leaf) +// bnd_box_lo Bounding box low point +// bnd_box_hi Bounding box high point +// splitRule Splitting method used +// +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Some types and objects used by kd-tree functions +// See src/kd_tree.h and src/kd_tree.cpp for definitions +//---------------------------------------------------------------------- +class ANNkdStats; // stats on kd-tree +class ANNkd_node; // generic node in a kd-tree +typedef ANNkd_node* ANNkd_ptr; // pointer to a kd-tree node + +class DLL_API ANNkd_tree: public ANNpointSet { +protected: + int dim; // dimension of space + int n_pts; // number of points in tree + int bkt_size; // bucket size + ANNpointArray pts; // the points + ANNidxArray pidx; // point indices (to pts array) + ANNkd_ptr root; // root of kd-tree + ANNpoint bnd_box_lo; // bounding box low point + ANNpoint bnd_box_hi; // bounding box high point + + void SkeletonTree( // construct skeleton tree + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNpointArray pa = NULL, // point array (optional) + ANNidxArray pi = NULL); // point indices (optional) + +public: + ANNkd_tree( // build skeleton tree + int n = 0, // number of points + int dd = 0, // dimension + int bs = 1); // bucket size + + ANNkd_tree( // build from point array + ANNpointArray pa, // point array + int n, // number of points + int dd, // dimension + int bs = 1, // bucket size + ANNsplitRule split = ANN_KD_SUGGEST); // splitting method + + ANNkd_tree( // build from dump file + std::istream& in); // input stream for dump file + + ~ANNkd_tree(); // tree destructor + + void annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0); // error bound + + void annkPriSearch( // priority k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (modified) + ANNdistArray dd, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0); // error bound + + // added by vlad to allow user to update flops by calling this function + // even if ANN_PERF is not defined + int annkFRSearchFlops( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0, // error bound + int * flops=NULL); // returns the number of floating ops performed by this query + + int annkFRSearchUnordered( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0); // error bound + + int annkFRSearchUnorderedFlops( // approx fixed-radius kNN search + ANNpoint q, // the query point + ANNdist sqRad, // squared radius of query ball + int k, // number of neighbors to return + ANNidxArray nn_idx = NULL, // nearest neighbor array (modified) + ANNdistArray dd = NULL, // dist to near neighbors (modified) + double eps=0.0, // error bound + int * flops=NULL); // returns the number of floating ops performed by this query + + + int theDim() // return dimension of space + { return dim; } + + int nPoints() // return number of points + { return n_pts; } + + ANNpointArray thePoints() // return pointer to points + { return pts; } + + virtual void Print( // print the tree (for debugging) + ANNbool with_pts, // print points as well? + std::ostream& out); // output stream + + virtual void Dump( // dump entire tree + ANNbool with_pts, // print points as well? + std::ostream& out); // output stream + + virtual void getStats( // compute tree statistics + ANNkdStats& st); // the statistics (modified) +}; + +//---------------------------------------------------------------------- +// Box decomposition tree (bd-tree) +// The bd-tree is inherited from a kd-tree. The main difference +// in the bd-tree and the kd-tree is a new type of internal node +// called a shrinking node (in the kd-tree there is only one type +// of internal node, a splitting node). The shrinking node +// makes it possible to generate balanced trees in which the +// cells have bounded aspect ratio, by allowing the decomposition +// to zoom in on regions of dense point concentration. Although +// this is a nice idea in theory, few point distributions are so +// densely clustered that this is really needed. +//---------------------------------------------------------------------- + +class DLL_API ANNbd_tree: public ANNkd_tree { +public: + ANNbd_tree( // build skeleton tree + int n, // number of points + int dd, // dimension + int bs = 1) // bucket size + : ANNkd_tree(n, dd, bs) {} // build base kd-tree + + ANNbd_tree( // build from point array + ANNpointArray pa, // point array + int n, // number of points + int dd, // dimension + int bs = 1, // bucket size + ANNsplitRule split = ANN_KD_SUGGEST, // splitting rule + ANNshrinkRule shrink = ANN_BD_SUGGEST); // shrinking rule + + ANNbd_tree( // build from dump file + std::istream& in); // input stream for dump file +}; + +//---------------------------------------------------------------------- +// Other functions +// annMaxPtsVisit Sets a limit on the maximum number of points +// to visit in the search. +// annClose Can be called when all use of ANN is finished. +// It clears up a minor memory leak. +//---------------------------------------------------------------------- + +DLL_API void annMaxPtsVisit( // max. pts to visit in search + int maxPts); // the limit + +DLL_API void annClose(); // called to end use of ANN + +#endif diff --git a/dep/ann/ANNperf.h b/dep/ann/ANNperf.h new file mode 100644 index 00000000..6741d473 --- /dev/null +++ b/dep/ann/ANNperf.h @@ -0,0 +1,228 @@ +//---------------------------------------------------------------------- +// File: ANNperf.h +// Programmer: Sunil Arya and David Mount +// Last modified: 03/04/98 (Release 0.1) +// Description: Include file for ANN performance stats +// +// Some of the code for statistics gathering has been adapted +// from the SmplStat.h package in the g++ library. +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Added ANN_ prefix to avoid name conflicts. +//---------------------------------------------------------------------- + +#ifndef ANNperf_H +#define ANNperf_H + +//---------------------------------------------------------------------- +// basic includes +//---------------------------------------------------------------------- + +#include "ANN.h" // basic ANN includes + +//---------------------------------------------------------------------- +// kd-tree stats object +// This object is used for collecting information about a kd-tree +// or bd-tree. +//---------------------------------------------------------------------- + +class ANNkdStats { // stats on kd-tree +public: + int dim; // dimension of space + int n_pts; // no. of points + int bkt_size; // bucket size + int n_lf; // no. of leaves (including trivial) + int n_tl; // no. of trivial leaves (no points) + int n_spl; // no. of splitting nodes + int n_shr; // no. of shrinking nodes (for bd-trees) + int depth; // depth of tree + float sum_ar; // sum of leaf aspect ratios + float avg_ar; // average leaf aspect ratio + // + // reset stats + void reset(int d=0, int n=0, int bs=0) + { + dim = d; n_pts = n; bkt_size = bs; + n_lf = n_tl = n_spl = n_shr = depth = 0; + sum_ar = avg_ar = 0.0; + } + + ANNkdStats() // basic constructor + { reset(); } + + void merge(const ANNkdStats &st); // merge stats from child +}; + +//---------------------------------------------------------------------- +// ANNsampStat +// A sample stat collects numeric (double) samples and returns some +// simple statistics. Its main functions are: +// +// reset() Reset to no samples. +// += x Include sample x. +// samples() Return number of samples. +// mean() Return mean of samples. +// stdDev() Return standard deviation +// min() Return minimum of samples. +// max() Return maximum of samples. +//---------------------------------------------------------------------- +class DLL_API ANNsampStat { + int n; // number of samples + double sum; // sum + double sum2; // sum of squares + double minVal, maxVal; // min and max +public : + void reset() // reset everything + { + n = 0; + sum = sum2 = 0; + minVal = ANN_DBL_MAX; + maxVal = -ANN_DBL_MAX; + } + + ANNsampStat() { reset(); } // constructor + + void operator+=(double x) // add sample + { + n++; sum += x; sum2 += x*x; + if (x < minVal) minVal = x; + if (x > maxVal) maxVal = x; + } + + int samples() { return n; } // number of samples + + double mean() { return sum/n; } // mean + + // standard deviation + double stdDev() { return sqrt((sum2 - (sum*sum)/n)/(n-1));} + + double min() { return minVal; } // minimum + double max() { return maxVal; } // maximum +}; + +//---------------------------------------------------------------------- +// Operation count updates +//---------------------------------------------------------------------- + +// defined by Vlad (05-01-2008) to get flop count even in Release version for some functions, +// while keeping the main functions fast +#define ANN_FLOP_ALWAYS(n) {ann_Nfloat_ops += (n);} +// end Vlad's modification + +#ifdef ANN_PERF + #define ANN_FLOP(n) {ann_Nfloat_ops += (n);} + #define ANN_LEAF(n) {ann_Nvisit_lfs += (n);} + #define ANN_SPL(n) {ann_Nvisit_spl += (n);} + #define ANN_SHR(n) {ann_Nvisit_shr += (n);} + #define ANN_PTS(n) {ann_Nvisit_pts += (n);} + #define ANN_COORD(n) {ann_Ncoord_hts += (n);} +#else + #define ANN_FLOP(n) + #define ANN_LEAF(n) + #define ANN_SPL(n) + #define ANN_SHR(n) + #define ANN_PTS(n) + #define ANN_COORD(n) +#endif + +//---------------------------------------------------------------------- +// Performance statistics +// The following data and routines are used for computing performance +// statistics for nearest neighbor searching. Because these routines +// can slow the code down, they can be activated and deactiviated by +// defining the ANN_PERF variable, by compiling with the option: +// -DANN_PERF +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Global counters for performance measurement +// +// visit_lfs The number of leaf nodes visited in the +// tree. +// +// visit_spl The number of splitting nodes visited in the +// tree. +// +// visit_shr The number of shrinking nodes visited in the +// tree. +// +// visit_pts The number of points visited in all the +// leaf nodes visited. Equivalently, this +// is the number of points for which distance +// calculations are performed. +// +// coord_hts The number of times a coordinate of a +// data point is accessed. This is generally +// less than visit_pts*d if partial distance +// calculation is used. This count is low +// in the sense that if a coordinate is hit +// many times in the same routine we may +// count it only once. +// +// float_ops The number of floating point operations. +// This includes all operations in the heap +// as well as distance calculations to boxes. +// +// average_err The average error of each query (the +// error of the reported point to the true +// nearest neighbor). For k nearest neighbors +// the error is computed k times. +// +// rank_err The rank error of each query (the difference +// in the rank of the reported point and its +// true rank). +// +// data_pts The number of data points. This is not +// a counter, but used in stats computation. +//---------------------------------------------------------------------- + +extern int ann_Ndata_pts; // number of data points +extern int ann_Nvisit_lfs; // number of leaf nodes visited +extern int ann_Nvisit_spl; // number of splitting nodes visited +extern int ann_Nvisit_shr; // number of shrinking nodes visited +extern int ann_Nvisit_pts; // visited points for one query +extern int ann_Ncoord_hts; // coordinate hits for one query +DLL_API extern int ann_Nfloat_ops; // floating ops for one query // DLL_API added by vlad 4/30/08 +extern ANNsampStat ann_visit_lfs; // stats on leaf nodes visits +extern ANNsampStat ann_visit_spl; // stats on splitting nodes visits +extern ANNsampStat ann_visit_shr; // stats on shrinking nodes visits +extern ANNsampStat ann_visit_nds; // stats on total nodes visits +extern ANNsampStat ann_visit_pts; // stats on points visited +extern ANNsampStat ann_coord_hts; // stats on coordinate hits +DLL_API extern ANNsampStat ann_float_ops; // stats on floating ops // DLL_API added by vlad 4/30/08 +//---------------------------------------------------------------------- +// The following need to be part of the public interface, because +// they are accessed outside the DLL in ann_test.cpp. +//---------------------------------------------------------------------- +DLL_API extern ANNsampStat ann_average_err; // average error +DLL_API extern ANNsampStat ann_rank_err; // rank error + +//---------------------------------------------------------------------- +// Declaration of externally accessible routines for statistics +//---------------------------------------------------------------------- + +DLL_API void annResetStats(int data_size); // reset stats for a set of queries + +DLL_API void annResetCounts(); // reset counts for one queries + +DLL_API void annUpdateStats(); // update stats with current counts + +DLL_API void annPrintStats(ANNbool validate); // print statistics for a run + +#endif diff --git a/dep/ann/ANNx.h b/dep/ann/ANNx.h new file mode 100644 index 00000000..0689118e --- /dev/null +++ b/dep/ann/ANNx.h @@ -0,0 +1,167 @@ +//---------------------------------------------------------------------- +// File: ANNx.h +// Programmer: Sunil Arya and David Mount +// Last modified: 03/04/98 (Release 0.1) +// Description: Internal include file for ANN +// +// These declarations are of use in manipulating some of +// the internal data objects appearing in ANN, but are not +// needed for applications just using the nearest neighbor +// search. +// +// Typical users of ANN should not need to access this file. +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed LO, HI, IN, OUT to ANN_LO, ANN_HI, etc. +//---------------------------------------------------------------------- + +#ifndef ANNx_H +#define ANNx_H + +#include // I/O manipulators +#include "ANN.h" // ANN includes + +//---------------------------------------------------------------------- +// Global constants and types +//---------------------------------------------------------------------- +enum {ANN_LO=0, ANN_HI=1}; // splitting indices +enum {ANN_IN=0, ANN_OUT=1}; // shrinking indices + // what to do in case of error +enum ANNerr {ANNwarn = 0, ANNabort = 1}; + +//---------------------------------------------------------------------- +// Maximum number of points to visit +// We have an option for terminating the search early if the +// number of points visited exceeds some threshold. If the +// threshold is 0 (its default) this means there is no limit +// and the algorithm applies its normal termination condition. +//---------------------------------------------------------------------- + +extern int ANNmaxPtsVisited; // maximum number of pts visited +extern int ANNptsVisited; // number of pts visited in search + +//---------------------------------------------------------------------- +// Global function declarations +//---------------------------------------------------------------------- + +void annError( // ANN error routine + char *msg, // error message + ANNerr level); // level of error + +void annPrintPt( // print a point + ANNpoint pt, // the point + int dim, // the dimension + std::ostream &out); // output stream + +//---------------------------------------------------------------------- +// Orthogonal (axis aligned) rectangle +// Orthogonal rectangles are represented by two points, one +// for the lower left corner (min coordinates) and the other +// for the upper right corner (max coordinates). +// +// The constructor initializes from either a pair of coordinates, +// pair of points, or another rectangle. Note that all constructors +// allocate new point storage. The destructor deallocates this +// storage. +// +// BEWARE: Orthogonal rectangles should be passed ONLY BY REFERENCE. +// (C++'s default copy constructor will not allocate new point +// storage, then on return the destructor free's storage, and then +// you get into big trouble in the calling procedure.) +//---------------------------------------------------------------------- + +class ANNorthRect { +public: + ANNpoint lo; // rectangle lower bounds + ANNpoint hi; // rectangle upper bounds +// + ANNorthRect( // basic constructor + int dd, // dimension of space + ANNcoord l=0, // default is empty + ANNcoord h=0) + { lo = annAllocPt(dd, l); hi = annAllocPt(dd, h); } + + ANNorthRect( // (almost a) copy constructor + int dd, // dimension + const ANNorthRect &r) // rectangle to copy + { lo = annCopyPt(dd, r.lo); hi = annCopyPt(dd, r.hi); } + + ANNorthRect( // construct from points + int dd, // dimension + ANNpoint l, // low point + ANNpoint h) // hight point + { lo = annCopyPt(dd, l); hi = annCopyPt(dd, h); } + + ~ANNorthRect() // destructor + { annDeallocPt(lo); annDeallocPt(hi); } + + ANNbool inside(int dim, ANNpoint p);// is point p inside rectangle? +}; + +void annAssignRect( // assign one rect to another + int dim, // dimension (both must be same) + ANNorthRect &dest, // destination (modified) + const ANNorthRect &source); // source + +//---------------------------------------------------------------------- +// Orthogonal (axis aligned) halfspace +// An orthogonal halfspace is represented by an integer cutting +// dimension cd, coordinate cutting value, cv, and side, sd, which is +// either +1 or -1. Our convention is that point q lies in the (closed) +// halfspace if (q[cd] - cv)*sd >= 0. +//---------------------------------------------------------------------- + +class ANNorthHalfSpace { +public: + int cd; // cutting dimension + ANNcoord cv; // cutting value + int sd; // which side +// + ANNorthHalfSpace() // default constructor + { cd = 0; cv = 0; sd = 0; } + + ANNorthHalfSpace( // basic constructor + int cdd, // dimension of space + ANNcoord cvv, // cutting value + int sdd) // side + { cd = cdd; cv = cvv; sd = sdd; } + + ANNbool in(ANNpoint q) const // is q inside halfspace? + { return (ANNbool) ((q[cd] - cv)*sd >= 0); } + + ANNbool out(ANNpoint q) const // is q outside halfspace? + { return (ANNbool) ((q[cd] - cv)*sd < 0); } + + ANNdist dist(ANNpoint q) const // (squared) distance from q + { return (ANNdist) ANN_POW(q[cd] - cv); } + + void setLowerBound(int d, ANNpoint p)// set to lower bound at p[i] + { cd = d; cv = p[d]; sd = +1; } + + void setUpperBound(int d, ANNpoint p)// set to upper bound at p[i] + { cd = d; cv = p[d]; sd = -1; } + + void project(ANNpoint &q) // project q (modified) onto halfspace + { if (out(q)) q[cd] = cv; } +}; + + // array of halfspaces +typedef ANNorthHalfSpace *ANNorthHSArray; + +#endif diff --git a/dep/ann/CMakeLists.txt b/dep/ann/CMakeLists.txt new file mode 100644 index 00000000..3f6bfa97 --- /dev/null +++ b/dep/ann/CMakeLists.txt @@ -0,0 +1,26 @@ + + +FILE(GLOB ansrcs "*.cpp") +add_library(depann ${ansrcs}) + + +INSTALL(TARGETS depann DESTINATION lib) + +# Install the header files +SET(ann_HEADERS + ANN.h + ANNx.h + ANNperf.h + bd_tree.h + kd_fix_rad_search.h + kd_pr_search.h + kd_search.h + kd_split.h + kd_tree.h + kd_util.h + pr_queue_k.h + pr_queue.h + ) + +INSTALL(FILES ${ann_HEADERS} DESTINATION include/dep) + diff --git a/dep/ann/LICENSE b/dep/ann/LICENSE new file mode 100644 index 00000000..cb4b386f --- /dev/null +++ b/dep/ann/LICENSE @@ -0,0 +1,48 @@ +ANN: Approximate Nearest Neighbors +Version: 1.1.2 +Release Date: Jan 27, 2010 +---------------------------------------------------------------------------- +Copyright (c) 1997-2010 University of Maryland and Sunil Arya and David +Mount All Rights Reserved. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser Public License as published by the +Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser Public License for more details. + +A copy of the terms and conditions of the license can be found in +License.txt or online at + + http://www.gnu.org/copyleft/lesser.html + +To obtain a copy, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Disclaimer +---------- +The University of Maryland and the authors make no representations about +the suitability or fitness of this software for any purpose. It is +provided "as is" without express or implied warranty. +--------------------------------------------------------------------- + +Authors +------- +David Mount +Dept of Computer Science +University of Maryland, +College Park, MD 20742 USA +mount@cs.umd.edu +http://www.cs.umd.edu/~mount/ + +Sunil Arya +Dept of Computer Science +Hong University of Science and Technology +Clearwater Bay, HONG KONG +arya@cs.ust.hk +http://www.cs.ust.hk/faculty/arya/ + diff --git a/dep/ann/bd_fix_rad_search.cpp b/dep/ann/bd_fix_rad_search.cpp new file mode 100644 index 00000000..4b2b432d --- /dev/null +++ b/dep/ann/bd_fix_rad_search.cpp @@ -0,0 +1,90 @@ +//---------------------------------------------------------------------- +// File: bd_fix_rad_search.cpp +// Programmer: David Mount +// Description: Standard bd-tree search +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 1.1 05/03/05 +// Initial release +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_fix_rad_search.h" // kd-tree FR search declarations + +//---------------------------------------------------------------------- +// Approximate searching for bd-trees. +// See the file kd_FR_search.cpp for general information on the +// approximate nearest neighbor search algorithm. Here we +// include the extensions for shrinking nodes. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// bd_shrink::ann_FR_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_FR_search(ANNdist box_dist) +{ + // check dist calc term cond. + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNkdFRQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdFRQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + child[ANN_IN]->ann_FR_search(inner_dist);// search inner child first + child[ANN_OUT]->ann_FR_search(box_dist);// ...then outer child + } + else { // if outer box is closer + child[ANN_OUT]->ann_FR_search(box_dist);// search outer child first + child[ANN_IN]->ann_FR_search(inner_dist);// ...then outer child + } + ANN_FLOP(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} + + +//---------------------------------------------------------------------- +// bd_shrink::ann_FR_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_FR_searchFlops(ANNdist box_dist) +{ + // check dist calc term cond. + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNkdFRQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdFRQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + child[ANN_IN]->ann_FR_searchFlops(inner_dist);// search inner child first + child[ANN_OUT]->ann_FR_searchFlops(box_dist);// ...then outer child + } + else { // if outer box is closer + child[ANN_OUT]->ann_FR_searchFlops(box_dist);// search outer child first + child[ANN_IN]->ann_FR_searchFlops(inner_dist);// ...then outer child + } + ANN_FLOP_ALWAYS(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} diff --git a/dep/ann/bd_pr_search.cpp b/dep/ann/bd_pr_search.cpp new file mode 100644 index 00000000..ad980fba --- /dev/null +++ b/dep/ann/bd_pr_search.cpp @@ -0,0 +1,62 @@ +//---------------------------------------------------------------------- +// File: bd_pr_search.cpp +// Programmer: David Mount +// Description: Priority search for bd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +//History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_pr_search.h" // kd priority search declarations + +//---------------------------------------------------------------------- +// Approximate priority searching for bd-trees. +// See the file kd_pr_search.cc for general information on the +// approximate nearest neighbor priority search algorithm. Here +// we include the extensions for shrinking nodes. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// bd_shrink::ann_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_pri_search(ANNdist box_dist) +{ + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNprQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNprQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + if (child[ANN_OUT] != KD_TRIVIAL) // enqueue outer if not trivial + ANNprBoxPQ->insert(box_dist,child[ANN_OUT]); + // continue with inner child + child[ANN_IN]->ann_pri_search(inner_dist); + } + else { // if outer box is closer + if (child[ANN_IN] != KD_TRIVIAL) // enqueue inner if not trivial + ANNprBoxPQ->insert(inner_dist,child[ANN_IN]); + // continue with outer child + child[ANN_OUT]->ann_pri_search(box_dist); + } + ANN_FLOP(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} diff --git a/dep/ann/bd_search.cpp b/dep/ann/bd_search.cpp new file mode 100644 index 00000000..1e492614 --- /dev/null +++ b/dep/ann/bd_search.cpp @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------- +// File: bd_search.cpp +// Programmer: David Mount +// Description: Standard bd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_search.h" // kd-tree search declarations + +//---------------------------------------------------------------------- +// Approximate searching for bd-trees. +// See the file kd_search.cpp for general information on the +// approximate nearest neighbor search algorithm. Here we +// include the extensions for shrinking nodes. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// bd_shrink::ann_search - search a shrinking node +//---------------------------------------------------------------------- + +void ANNbd_shrink::ann_search(ANNdist box_dist) +{ + // check dist calc term cond. + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + ANNdist inner_dist = 0; // distance to inner box + for (int i = 0; i < n_bnds; i++) { // is query point in the box? + if (bnds[i].out(ANNkdQ)) { // outside this bounding side? + // add to inner distance + inner_dist = (ANNdist) ANN_SUM(inner_dist, bnds[i].dist(ANNkdQ)); + } + } + if (inner_dist <= box_dist) { // if inner box is closer + child[ANN_IN]->ann_search(inner_dist); // search inner child first + child[ANN_OUT]->ann_search(box_dist); // ...then outer child + } + else { // if outer box is closer + child[ANN_OUT]->ann_search(box_dist); // search outer child first + child[ANN_IN]->ann_search(inner_dist); // ...then outer child + } + ANN_FLOP(3*n_bnds) // increment floating ops + ANN_SHR(1) // one more shrinking node +} diff --git a/dep/ann/bd_tree.cpp b/dep/ann/bd_tree.cpp new file mode 100644 index 00000000..7fa3725f --- /dev/null +++ b/dep/ann/bd_tree.cpp @@ -0,0 +1,417 @@ +//---------------------------------------------------------------------- +// File: bd_tree.cpp +// Programmer: David Mount +// Description: Basic methods for bd-trees. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision l.0 04/01/05 +// Fixed centroid shrink threshold condition to depend on the +// dimension. +// Moved dump routine to kd_dump.cpp. +//---------------------------------------------------------------------- + +#include "bd_tree.h" // bd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "kd_split.h" // kd-tree splitting rules + +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// Printing a bd-tree +// These routines print a bd-tree. See the analogous procedure +// in kd_tree.cpp for more information. +//---------------------------------------------------------------------- + +void ANNbd_shrink::print( // print shrinking node + int level, // depth of node in tree + ostream &out) // output stream +{ + child[ANN_OUT]->print(level+1, out); // print out-child + + out << " "; + for (int i = 0; i < level; i++) // print indentation + out << ".."; + out << "Shrink"; + for (int j = 0; j < n_bnds; j++) { // print sides, 2 per line + if (j % 2 == 0) { + out << "\n"; // newline and indentation + for (int i = 0; i < level+2; i++) out << " "; + } + out << " ([" << bnds[j].cd << "]" + << (bnds[j].sd > 0 ? ">=" : "< ") + << bnds[j].cv << ")"; + } + out << "\n"; + + child[ANN_IN]->print(level+1, out); // print in-child +} + +//---------------------------------------------------------------------- +// kd_tree statistics utility (for performance evaluation) +// This routine computes various statistics information for +// shrinking nodes. See file kd_tree.cpp for more information. +//---------------------------------------------------------------------- + +void ANNbd_shrink::getStats( // get subtree statistics + int dim, // dimension of space + ANNkdStats &st, // stats (modified) + ANNorthRect &bnd_box) // bounding box +{ + ANNkdStats ch_stats; // stats for children + ANNorthRect inner_box(dim); // inner box of shrink + + annBnds2Box(bnd_box, // enclosing box + dim, // dimension + n_bnds, // number of bounds + bnds, // bounds array + inner_box); // inner box (modified) + // get stats for inner child + ch_stats.reset(); // reset + child[ANN_IN]->getStats(dim, ch_stats, inner_box); + st.merge(ch_stats); // merge them + // get stats for outer child + ch_stats.reset(); // reset + child[ANN_OUT]->getStats(dim, ch_stats, bnd_box); + st.merge(ch_stats); // merge them + + st.depth++; // increment depth + st.n_shr++; // increment number of shrinks +} + +//---------------------------------------------------------------------- +// bd-tree constructor +// This is the main constructor for bd-trees given a set of points. +// It first builds a skeleton kd-tree as a basis, then computes the +// bounding box of the data points, and then invokes rbd_tree() to +// actually build the tree, passing it the appropriate splitting +// and shrinking information. +//---------------------------------------------------------------------- + +ANNkd_ptr rbd_tree( // recursive construction of bd-tree + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter, // splitting routine + ANNshrinkRule shrink); // shrinking rule + +ANNbd_tree::ANNbd_tree( // construct from point array + ANNpointArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNsplitRule split, // splitting rule + ANNshrinkRule shrink) // shrinking rule + : ANNkd_tree(n, dd, bs) // build skeleton base tree +{ + pts = pa; // where the points are + if (n == 0) return; // no points--no sweat + + ANNorthRect bnd_box(dd); // bounding box for points + // construct bounding rectangle + annEnclRect(pa, pidx, n, dd, bnd_box); + // copy to tree structure + bnd_box_lo = annCopyPt(dd, bnd_box.lo); + bnd_box_hi = annCopyPt(dd, bnd_box.hi); + + switch (split) { // build by rule + case ANN_KD_STD: // standard kd-splitting rule + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split, shrink); + break; + case ANN_KD_MIDPT: // midpoint split + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split, shrink); + break; + case ANN_KD_SUGGEST: // best (in our opinion) + case ANN_KD_SL_MIDPT: // sliding midpoint split + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split, shrink); + break; + case ANN_KD_FAIR: // fair split + root = rbd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split, shrink); + break; + case ANN_KD_SL_FAIR: // sliding fair split + root = rbd_tree(pa, pidx, n, dd, bs, + bnd_box, sl_fair_split, shrink); + break; + default: + annError("Illegal splitting method", ANNabort); + } +} + +//---------------------------------------------------------------------- +// Shrinking rules +//---------------------------------------------------------------------- + +enum ANNdecomp {SPLIT, SHRINK}; // decomposition methods + +//---------------------------------------------------------------------- +// trySimpleShrink - Attempt a simple shrink +// +// We compute the tight bounding box of the points, and compute +// the 2*dim ``gaps'' between the sides of the tight box and the +// bounding box. If any of the gaps is large enough relative to +// the longest side of the tight bounding box, then we shrink +// all sides whose gaps are large enough. (The reason for +// comparing against the tight bounding box, is that after +// shrinking the longest box size will decrease, and if we use +// the standard bounding box, we may decide to shrink twice in +// a row. Since the tight box is fixed, we cannot shrink twice +// consecutively.) +//---------------------------------------------------------------------- +const float BD_GAP_THRESH = 0.5; // gap threshold (must be < 1) +const int BD_CT_THRESH = 2; // min number of shrink sides + +ANNdecomp trySimpleShrink( // try a simple shrink + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + const ANNorthRect &bnd_box, // current bounding box + ANNorthRect &inner_box) // inner box if shrinking (returned) +{ + int i; + // compute tight bounding box + annEnclRect(pa, pidx, n, dim, inner_box); + + ANNcoord max_length = 0; // find longest box side + for (i = 0; i < dim; i++) { + ANNcoord length = inner_box.hi[i] - inner_box.lo[i]; + if (length > max_length) { + max_length = length; + } + } + + int shrink_ct = 0; // number of sides we shrunk + for (i = 0; i < dim; i++) { // select which sides to shrink + // gap between boxes + ANNcoord gap_hi = bnd_box.hi[i] - inner_box.hi[i]; + // big enough gap to shrink? + if (gap_hi < max_length*BD_GAP_THRESH) + inner_box.hi[i] = bnd_box.hi[i]; // no - expand + else shrink_ct++; // yes - shrink this side + + // repeat for high side + ANNcoord gap_lo = inner_box.lo[i] - bnd_box.lo[i]; + if (gap_lo < max_length*BD_GAP_THRESH) + inner_box.lo[i] = bnd_box.lo[i]; // no - expand + else shrink_ct++; // yes - shrink this side + } + + if (shrink_ct >= BD_CT_THRESH) // did we shrink enough sides? + return SHRINK; + else return SPLIT; +} + +//---------------------------------------------------------------------- +// tryCentroidShrink - Attempt a centroid shrink +// +// We repeatedly apply the splitting rule, always to the larger subset +// of points, until the number of points decreases by the constant +// fraction BD_FRACTION. If this takes more than dim*BD_MAX_SPLIT_FAC +// splits for this to happen, then we shrink to the final inner box +// Otherwise we split. +//---------------------------------------------------------------------- + +const float BD_MAX_SPLIT_FAC = 0.5; // maximum number of splits allowed +const float BD_FRACTION = 0.5; // ...to reduce points by this fraction + // ...This must be < 1. + +ANNdecomp tryCentroidShrink( // try a centroid shrink + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + const ANNorthRect &bnd_box, // current bounding box + ANNkd_splitter splitter, // splitting procedure + ANNorthRect &inner_box) // inner box if shrinking (returned) +{ + int n_sub = n; // number of points in subset + int n_goal = (int) (n*BD_FRACTION); // number of point in goal + int n_splits = 0; // number of splits needed + // initialize inner box to bounding box + annAssignRect(dim, inner_box, bnd_box); + + while (n_sub > n_goal) { // keep splitting until goal reached + int cd; // cut dim from splitter (ignored) + ANNcoord cv; // cut value from splitter (ignored) + int n_lo; // number of points on low side + // invoke splitting procedure + (*splitter)(pa, pidx, inner_box, n_sub, dim, cd, cv, n_lo); + n_splits++; // increment split count + + if (n_lo >= n_sub/2) { // most points on low side + inner_box.hi[cd] = cv; // collapse high side + n_sub = n_lo; // recurse on lower points + } + else { // most points on high side + inner_box.lo[cd] = cv; // collapse low side + pidx += n_lo; // recurse on higher points + n_sub -= n_lo; + } + } + if (n_splits > dim*BD_MAX_SPLIT_FAC)// took too many splits + return SHRINK; // shrink to final subset + else + return SPLIT; +} + +//---------------------------------------------------------------------- +// selectDecomp - select which decomposition to use +//---------------------------------------------------------------------- + +ANNdecomp selectDecomp( // select decomposition method + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + const ANNorthRect &bnd_box, // current bounding box + ANNkd_splitter splitter, // splitting procedure + ANNshrinkRule shrink, // shrinking rule + ANNorthRect &inner_box) // inner box if shrinking (returned) +{ + ANNdecomp decomp = SPLIT; // decomposition + + switch (shrink) { // check shrinking rule + case ANN_BD_NONE: // no shrinking allowed + decomp = SPLIT; + break; + case ANN_BD_SUGGEST: // author's suggestion + case ANN_BD_SIMPLE: // simple shrink + decomp = trySimpleShrink( + pa, pidx, // points and indices + n, dim, // number of points and dimension + bnd_box, // current bounding box + inner_box); // inner box if shrinking (returned) + break; + case ANN_BD_CENTROID: // centroid shrink + decomp = tryCentroidShrink( + pa, pidx, // points and indices + n, dim, // number of points and dimension + bnd_box, // current bounding box + splitter, // splitting procedure + inner_box); // inner box if shrinking (returned) + break; + default: + annError("Illegal shrinking rule", ANNabort); + } + return decomp; +} + +//---------------------------------------------------------------------- +// rbd_tree - recursive procedure to build a bd-tree +// +// This is analogous to rkd_tree, but for bd-trees. See the +// procedure rkd_tree() in kd_split.cpp for more information. +// +// If the number of points falls below the bucket size, then a +// leaf node is created for the points. Otherwise we invoke the +// procedure selectDecomp() which determines whether we are to +// split or shrink. If splitting is chosen, then we essentially +// do exactly as rkd_tree() would, and invoke the specified +// splitting procedure to the points. Otherwise, the selection +// procedure returns a bounding box, from which we extract the +// appropriate shrinking bounds, and create a shrinking node. +// Finally the points are subdivided, and the procedure is +// invoked recursively on the two subsets to form the children. +//---------------------------------------------------------------------- + +ANNkd_ptr rbd_tree( // recursive construction of bd-tree + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter, // splitting routine + ANNshrinkRule shrink) // shrinking rule +{ + ANNdecomp decomp; // decomposition method + + ANNorthRect inner_box(dim); // inner box (if shrinking) + + if (n <= bsp) { // n small, make a leaf node + if (n == 0) // empty leaf node + return KD_TRIVIAL; // return (canonical) empty leaf + else // construct the node and return + return new ANNkd_leaf(n, pidx); + } + + decomp = selectDecomp( // select decomposition method + pa, pidx, // points and indices + n, dim, // number of points and dimension + bnd_box, // current bounding box + splitter, shrink, // splitting/shrinking methods + inner_box); // inner box if shrinking (returned) + + if (decomp == SPLIT) { // split selected + int cd; // cutting dimension + ANNcoord cv; // cutting value + int n_lo; // number on low side of cut + // invoke splitting procedure + (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); + + ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension + ANNcoord hv = bnd_box.hi[cd]; + + bnd_box.hi[cd] = cv; // modify bounds for left subtree + ANNkd_ptr lo = rbd_tree( // build left subtree + pa, pidx, n_lo, // ...from pidx[0..n_lo-1] + dim, bsp, bnd_box, splitter, shrink); + bnd_box.hi[cd] = hv; // restore bounds + + bnd_box.lo[cd] = cv; // modify bounds for right subtree + ANNkd_ptr hi = rbd_tree( // build right subtree + pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] + dim, bsp, bnd_box, splitter, shrink); + bnd_box.lo[cd] = lv; // restore bounds + // create the splitting node + return new ANNkd_split(cd, cv, lv, hv, lo, hi); + } + else { // shrink selected + int n_in; // number of points in box + int n_bnds; // number of bounding sides + + annBoxSplit( // split points around inner box + pa, // points to split + pidx, // point indices + n, // number of points + dim, // dimension + inner_box, // inner box + n_in); // number of points inside (returned) + + ANNkd_ptr in = rbd_tree( // build inner subtree pidx[0..n_in-1] + pa, pidx, n_in, dim, bsp, inner_box, splitter, shrink); + ANNkd_ptr out = rbd_tree( // build outer subtree pidx[n_in..n] + pa, pidx+n_in, n - n_in, dim, bsp, bnd_box, splitter, shrink); + + ANNorthHSArray bnds = NULL; // bounds (alloc in Box2Bnds and + // ...freed in bd_shrink destroyer) + + annBox2Bnds( // convert inner box to bounds + inner_box, // inner box + bnd_box, // enclosing box + dim, // dimension + n_bnds, // number of bounds (returned) + bnds); // bounds array (modified) + + // return shrinking node + return new ANNbd_shrink(n_bnds, bnds, in, out); + } +} diff --git a/dep/ann/bd_tree.h b/dep/ann/bd_tree.h new file mode 100644 index 00000000..52209dbd --- /dev/null +++ b/dep/ann/bd_tree.h @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------- +// File: bd_tree.h +// Programmer: David Mount +// Description: Declarations for standard bd-tree routines +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed IN, OUT to ANN_IN, ANN_OUT +//---------------------------------------------------------------------- + +#ifndef ANN_bd_tree_H +#define ANN_bd_tree_H + +#include "ANNx.h" // all ANN includes +#include "kd_tree.h" // kd-tree includes + +//---------------------------------------------------------------------- +// bd-tree shrinking node. +// The main addition in the bd-tree is the shrinking node, which +// is declared here. +// +// Shrinking nodes are defined by list of orthogonal halfspaces. +// These halfspaces define a (possibly unbounded) orthogonal +// rectangle. There are two children, in and out. Points that +// lie within this rectangle are stored in the in-child, and the +// other points are stored in the out-child. +// +// We use a list of orthogonal halfspaces rather than an +// orthogonal rectangle object because typically the number of +// sides of the shrinking box will be much smaller than the +// worst case bound of 2*dim. +// +// BEWARE: Note that constructor just copies the pointer to the +// bounding array, but the destructor deallocates it. This is +// rather poor practice, but happens to be convenient. The list +// is allocated in the bd-tree building procedure rbd_tree() just +// prior to construction, and is used for no other purposes. +// +// WARNING: In the near neighbor searching code it is assumed that +// the list of bounding halfspaces is irredundant, meaning that there +// are no two distinct halfspaces in the list with the same outward +// pointing normals. +//---------------------------------------------------------------------- + +class ANNbd_shrink : public ANNkd_node // splitting node of a kd-tree +{ + int n_bnds; // number of bounding halfspaces + ANNorthHSArray bnds; // list of bounding halfspaces + ANNkd_ptr child[2]; // in and out children +public: + ANNbd_shrink( // constructor + int nb, // number of bounding halfspaces + ANNorthHSArray bds, // list of bounding halfspaces + ANNkd_ptr ic=NULL, ANNkd_ptr oc=NULL) // children + { + n_bnds = nb; // cutting dimension + bnds = bds; // assign bounds + child[ANN_IN] = ic; // set children + child[ANN_OUT] = oc; + } + + ~ANNbd_shrink() // destructor + { + if (child[ANN_IN]!= NULL && child[ANN_IN]!= KD_TRIVIAL) + delete child[ANN_IN]; + if (child[ANN_OUT]!= NULL&& child[ANN_OUT]!= KD_TRIVIAL) + delete child[ANN_OUT]; + if (bnds != NULL) + delete [] bnds; // delete bounds + } + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box); // bounding box + virtual void print(int level, ostream &out);// print node + virtual void dump(ostream &out); // dump node + + virtual void ann_search(ANNdist); // standard search + virtual void ann_pri_search(ANNdist); // priority search + virtual void ann_FR_search(ANNdist); // fixed-radius search + + // added by Vlad 5-1-08 to update flops even when ANN_PERF is not defined + virtual void ann_FR_searchFlops(ANNdist); // fixed-radius search +}; + +#endif diff --git a/dep/ann/brute.cpp b/dep/ann/brute.cpp new file mode 100644 index 00000000..a667da4c --- /dev/null +++ b/dep/ann/brute.cpp @@ -0,0 +1,109 @@ +//---------------------------------------------------------------------- +// File: brute.cpp +// Programmer: Sunil Arya and David Mount +// Description: Brute-force nearest neighbors +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.1 05/03/05 +// Added fixed-radius kNN search +//---------------------------------------------------------------------- + +#include "ANNx.h" // all ANN includes +#include "pr_queue_k.h" // k element priority queue + +//---------------------------------------------------------------------- +// Brute-force search simply stores a pointer to the list of +// data points and searches linearly for the nearest neighbor. +// The k nearest neighbors are stored in a k-element priority +// queue (which is implemented in a pretty dumb way as well). +// +// If ANN_ALLOW_SELF_MATCH is ANNfalse then data points at distance +// zero are not considered. +// +// Note that the error bound eps is passed in, but it is ignored. +// These routines compute exact nearest neighbors (which is needed +// for validation purposes in ann_test.cpp). +//---------------------------------------------------------------------- + +ANNbruteForce::ANNbruteForce( // constructor from point array + ANNpointArray pa, // point array + int n, // number of points + int dd) // dimension +{ + dim = dd; n_pts = n; pts = pa; +} + +ANNbruteForce::~ANNbruteForce() { } // destructor (empty) + +void ANNbruteForce::annkSearch( // approx k near neighbor search + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // dist to near neighbors (returned) + double eps) // error bound (ignored) +{ + ANNmin_k mk(k); // construct a k-limited priority queue + int i; + + if (k > n_pts) { // too many near neighbors? + annError("Requesting more near neighbors than data points", ANNabort); + } + // run every point through queue + for (i = 0; i < n_pts; i++) { + // compute distance to point + ANNdist sqDist = annDist(dim, pts[i], q); + if (ANN_ALLOW_SELF_MATCH || sqDist != 0) + mk.insert(sqDist, i); + } + for (i = 0; i < k; i++) { // extract the k closest points + dd[i] = mk.ith_smallest_key(i); + nn_idx[i] = mk.ith_smallest_info(i); + } +} + +int ANNbruteForce::annkFRSearch( // approx fixed-radius kNN search + ANNpoint q, // query point + ANNdist sqRad, // squared radius + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor array (returned) + ANNdistArray dd, // dist to near neighbors (returned) + double eps) // error bound +{ + ANNmin_k mk(k); // construct a k-limited priority queue + int i; + int pts_in_range = 0; // number of points in query range + // run every point through queue + for (i = 0; i < n_pts; i++) { + // compute distance to point + ANNdist sqDist = annDist(dim, pts[i], q); + if (sqDist <= sqRad && // within radius bound + (ANN_ALLOW_SELF_MATCH || sqDist != 0)) { // ...and no self match + mk.insert(sqDist, i); + pts_in_range++; + } + } + for (i = 0; i < k; i++) { // extract the k closest points + if (dd != NULL) + dd[i] = mk.ith_smallest_key(i); + if (nn_idx != NULL) + nn_idx[i] = mk.ith_smallest_info(i); + } + + return pts_in_range; +} diff --git a/dep/ann/kd_dump.cpp b/dep/ann/kd_dump.cpp new file mode 100644 index 00000000..13f9f0e2 --- /dev/null +++ b/dep/ann/kd_dump.cpp @@ -0,0 +1,450 @@ +//---------------------------------------------------------------------- +// File: kd_dump.cc +// Programmer: David Mount +// Description: Dump and Load for kd- and bd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Moved dump out of kd_tree.cc into this file. +// Added kd-tree load constructor. +// Revision 2010/05/12 by Vlad Morariu +// Added stdlib.h and string.h includes to for exit() and +// strcmp() (they used to be implicitly included by +// gcc headers, but they are not anymore). +//---------------------------------------------------------------------- +// This file contains routines for dumping kd-trees and bd-trees and +// reloading them. (It is an abuse of policy to include both kd- and +// bd-tree routines in the same file, sorry. There should be no problem +// in deleting the bd- versions of the routines if they are not +// desired.) +//---------------------------------------------------------------------- + +#include "kd_tree.h" // kd-tree declarations +#include "bd_tree.h" // bd-tree declarations +#include // Added by Vlad 2010/05/12 for exit() +#include // Added by Vlad 2010/05/12 for strcmp() + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------- + +const int STRING_LEN = 500; // maximum string length +const double EPSILON = 1E-5; // small number for float comparison + +enum ANNtreeType {KD_TREE, BD_TREE}; // tree types (used in loading) + +//---------------------------------------------------------------------- +// Procedure declarations +//---------------------------------------------------------------------- + +static ANNkd_ptr annReadDump( // read dump file + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNpointArray &the_pts, // new points (if applic) + ANNidxArray &the_pidx, // point indices (returned) + int &the_dim, // dimension (returned) + int &the_n_pts, // number of points (returned) + int &the_bkt_size, // bucket size (returned) + ANNpoint &the_bnd_box_lo, // low bounding point + ANNpoint &the_bnd_box_hi); // high bounding point + +static ANNkd_ptr annReadTree( // read tree-part of dump file + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNidxArray the_pidx, // point indices (modified) + int &next_idx); // next index (modified) + +//---------------------------------------------------------------------- +// ANN kd- and bd-tree Dump Format +// The dump file begins with a header containing the version of +// ANN, an optional section containing the points, followed by +// a description of the tree. The tree is printed in preorder. +// +// Format: +// #ANN [END_OF_LINE] +// points (point coordinates: this is optional) +// 0 ... (point indices and coordinates) +// 1 ... +// ... +// tree +// ... (lower end of bounding box) +// ... (upper end of bounding box) +// If the tree is null, then a single line "null" is +// output. Otherwise the nodes of the tree are printed +// one per line in preorder. Leaves and splitting nodes +// have the following formats: +// Leaf node: +// leaf ... +// Splitting nodes: +// split +// +// For bd-trees: +// +// Shrinking nodes: +// shrink +// +// +// ... (repeated n_bnds times) +//---------------------------------------------------------------------- + +void ANNkd_tree::Dump( // dump entire tree + ANNbool with_pts, // print points as well? + ostream &out) // output stream +{ + out << "#ANN " << ANNversion << "\n"; + out.precision(ANNcoordPrec); // use full precision in dumping + if (with_pts) { // print point coordinates + out << "points " << dim << " " << n_pts << "\n"; + for (int i = 0; i < n_pts; i++) { + out << i << " "; + annPrintPt(pts[i], dim, out); + out << "\n"; + } + } + out << "tree " // print tree elements + << dim << " " + << n_pts << " " + << bkt_size << "\n"; + + annPrintPt(bnd_box_lo, dim, out); // print lower bound + out << "\n"; + annPrintPt(bnd_box_hi, dim, out); // print upper bound + out << "\n"; + + if (root == NULL) // empty tree? + out << "null\n"; + else { + root->dump(out); // invoke printing at root + } + out.precision(0); // restore default precision +} + +void ANNkd_split::dump( // dump a splitting node + ostream &out) // output stream +{ + out << "split " << cut_dim << " " << cut_val << " "; + out << cd_bnds[ANN_LO] << " " << cd_bnds[ANN_HI] << "\n"; + + child[ANN_LO]->dump(out); // print low child + child[ANN_HI]->dump(out); // print high child +} + +void ANNkd_leaf::dump( // dump a leaf node + ostream &out) // output stream +{ + if (this == KD_TRIVIAL) { // canonical trivial leaf node + out << "leaf 0\n"; // leaf no points + } + else{ + out << "leaf " << n_pts; + for (int j = 0; j < n_pts; j++) { + out << " " << bkt[j]; + } + out << "\n"; + } +} + +void ANNbd_shrink::dump( // dump a shrinking node + ostream &out) // output stream +{ + out << "shrink " << n_bnds << "\n"; + for (int j = 0; j < n_bnds; j++) { + out << bnds[j].cd << " " << bnds[j].cv << " " << bnds[j].sd << "\n"; + } + child[ANN_IN]->dump(out); // print in-child + child[ANN_OUT]->dump(out); // print out-child +} + +//---------------------------------------------------------------------- +// Load kd-tree from dump file +// This rebuilds a kd-tree which was dumped to a file. The dump +// file contains all the basic tree information according to a +// preorder traversal. We assume that the dump file also contains +// point data. (This is to guarantee the consistency of the tree.) +// If not, then an error is generated. +// +// Indirectly, this procedure allocates space for points, point +// indices, all nodes in the tree, and the bounding box for the +// tree. When the tree is destroyed, all but the points are +// deallocated. +// +// This routine calls annReadDump to do all the work. +//---------------------------------------------------------------------- + +ANNkd_tree::ANNkd_tree( // build from dump file + istream &in) // input stream for dump file +{ + int the_dim; // local dimension + int the_n_pts; // local number of points + int the_bkt_size; // local number of points + ANNpoint the_bnd_box_lo; // low bounding point + ANNpoint the_bnd_box_hi; // high bounding point + ANNpointArray the_pts; // point storage + ANNidxArray the_pidx; // point index storage + ANNkd_ptr the_root; // root of the tree + + the_root = annReadDump( // read the dump file + in, // input stream + KD_TREE, // expecting a kd-tree + the_pts, // point array (returned) + the_pidx, // point indices (returned) + the_dim, the_n_pts, the_bkt_size, // basic tree info (returned) + the_bnd_box_lo, the_bnd_box_hi); // bounding box info (returned) + + // create a skeletal tree + SkeletonTree(the_n_pts, the_dim, the_bkt_size, the_pts, the_pidx); + + bnd_box_lo = the_bnd_box_lo; + bnd_box_hi = the_bnd_box_hi; + + root = the_root; // set the root +} + +ANNbd_tree::ANNbd_tree( // build bd-tree from dump file + istream &in) : ANNkd_tree() // input stream for dump file +{ + int the_dim; // local dimension + int the_n_pts; // local number of points + int the_bkt_size; // local number of points + ANNpoint the_bnd_box_lo; // low bounding point + ANNpoint the_bnd_box_hi; // high bounding point + ANNpointArray the_pts; // point storage + ANNidxArray the_pidx; // point index storage + ANNkd_ptr the_root; // root of the tree + + the_root = annReadDump( // read the dump file + in, // input stream + BD_TREE, // expecting a bd-tree + the_pts, // point array (returned) + the_pidx, // point indices (returned) + the_dim, the_n_pts, the_bkt_size, // basic tree info (returned) + the_bnd_box_lo, the_bnd_box_hi); // bounding box info (returned) + + // create a skeletal tree + SkeletonTree(the_n_pts, the_dim, the_bkt_size, the_pts, the_pidx); + bnd_box_lo = the_bnd_box_lo; + bnd_box_hi = the_bnd_box_hi; + + root = the_root; // set the root +} + +//---------------------------------------------------------------------- +// annReadDump - read a dump file +// +// This procedure reads a dump file, constructs a kd-tree +// and returns all the essential information needed to actually +// construct the tree. Because this procedure is used for +// constructing both kd-trees and bd-trees, the second argument +// is used to indicate which type of tree we are expecting. +//---------------------------------------------------------------------- + +static ANNkd_ptr annReadDump( + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNpointArray &the_pts, // new points (returned) + ANNidxArray &the_pidx, // point indices (returned) + int &the_dim, // dimension (returned) + int &the_n_pts, // number of points (returned) + int &the_bkt_size, // bucket size (returned) + ANNpoint &the_bnd_box_lo, // low bounding point (ret'd) + ANNpoint &the_bnd_box_hi) // high bounding point (ret'd) +{ + int j; + char str[STRING_LEN]; // storage for string + char version[STRING_LEN]; // ANN version number + ANNkd_ptr the_root = NULL; + + //------------------------------------------------------------------ + // Input file header + //------------------------------------------------------------------ + in >> str; // input header + if (strcmp(str, "#ANN") != 0) { // incorrect header + annError("Incorrect header for dump file", ANNabort); + } + in.getline(version, STRING_LEN); // get version (ignore) + + //------------------------------------------------------------------ + // Input the points + // An array the_pts is allocated and points are read from + // the dump file. + //------------------------------------------------------------------ + in >> str; // get major heading + if (strcmp(str, "points") == 0) { // points section + in >> the_dim; // input dimension + in >> the_n_pts; // number of points + // allocate point storage + the_pts = annAllocPts(the_n_pts, the_dim); + for (int i = 0; i < the_n_pts; i++) { // input point coordinates + ANNidx idx; // point index + in >> idx; // input point index + if (idx < 0 || idx >= the_n_pts) { + annError("Point index is out of range", ANNabort); + } + for (j = 0; j < the_dim; j++) { + in >> the_pts[idx][j]; // read point coordinates + } + } + in >> str; // get next major heading + } + else { // no points were input + annError("Points must be supplied in the dump file", ANNabort); + } + + //------------------------------------------------------------------ + // Input the tree + // After the basic header information, we invoke annReadTree + // to do all the heavy work. We create our own array of + // point indices (so we can pass them to annReadTree()) + // but we do not deallocate them. They will be deallocated + // when the tree is destroyed. + //------------------------------------------------------------------ + if (strcmp(str, "tree") == 0) { // tree section + in >> the_dim; // read dimension + in >> the_n_pts; // number of points + in >> the_bkt_size; // bucket size + the_bnd_box_lo = annAllocPt(the_dim); // allocate bounding box pts + the_bnd_box_hi = annAllocPt(the_dim); + + for (j = 0; j < the_dim; j++) { // read bounding box low + in >> the_bnd_box_lo[j]; + } + for (j = 0; j < the_dim; j++) { // read bounding box low + in >> the_bnd_box_hi[j]; + } + the_pidx = new ANNidx[the_n_pts]; // allocate point index array + int next_idx = 0; // number of indices filled + // read the tree and indices + the_root = annReadTree(in, tree_type, the_pidx, next_idx); + if (next_idx != the_n_pts) { // didn't see all the points? + annError("Didn't see as many points as expected", ANNwarn); + } + } + else { + annError("Illegal dump format. Expecting section heading", ANNabort); + } + return the_root; +} + +//---------------------------------------------------------------------- +// annReadTree - input tree and return pointer +// +// annReadTree reads in a node of the tree, makes any recursive +// calls as needed to input the children of this node (if internal). +// It returns a pointer to the node that was created. An array +// of point indices is given along with a pointer to the next +// available location in the array. As leaves are read, their +// point indices are stored here, and the point buckets point +// to the first entry in the array. +// +// Recall that these are the formats. The tree is given in +// preorder. +// +// Leaf node: +// leaf ... +// Splitting nodes: +// split +// +// For bd-trees: +// +// Shrinking nodes: +// shrink +// +// +// ... (repeated n_bnds times) +//---------------------------------------------------------------------- + +static ANNkd_ptr annReadTree( + istream &in, // input stream + ANNtreeType tree_type, // type of tree expected + ANNidxArray the_pidx, // point indices (modified) + int &next_idx) // next index (modified) +{ + char tag[STRING_LEN]; // tag (leaf, split, shrink) + int n_pts; // number of points in leaf + int cd; // cut dimension + ANNcoord cv; // cut value + ANNcoord lb; // low bound + ANNcoord hb; // high bound + int n_bnds; // number of bounding sides + int sd; // which side + + in >> tag; // input node tag + + if (strcmp(tag, "null") == 0) { // null tree + return NULL; + } + //------------------------------------------------------------------ + // Read a leaf + //------------------------------------------------------------------ + if (strcmp(tag, "leaf") == 0) { // leaf node + + in >> n_pts; // input number of points + int old_idx = next_idx; // save next_idx + if (n_pts == 0) { // trivial leaf + return KD_TRIVIAL; + } + else { + for (int i = 0; i < n_pts; i++) { // input point indices + in >> the_pidx[next_idx++]; // store in array of indices + } + } + return new ANNkd_leaf(n_pts, &the_pidx[old_idx]); + } + //------------------------------------------------------------------ + // Read a splitting node + //------------------------------------------------------------------ + else if (strcmp(tag, "split") == 0) { // splitting node + + in >> cd >> cv >> lb >> hb; + + // read low and high subtrees + ANNkd_ptr lc = annReadTree(in, tree_type, the_pidx, next_idx); + ANNkd_ptr hc = annReadTree(in, tree_type, the_pidx, next_idx); + // create new node and return + return new ANNkd_split(cd, cv, lb, hb, lc, hc); + } + //------------------------------------------------------------------ + // Read a shrinking node (bd-tree only) + //------------------------------------------------------------------ + else if (strcmp(tag, "shrink") == 0) { // shrinking node + if (tree_type != BD_TREE) { + annError("Shrinking node not allowed in kd-tree", ANNabort); + } + + in >> n_bnds; // number of bounding sides + // allocate bounds array + ANNorthHSArray bds = new ANNorthHalfSpace[n_bnds]; + for (int i = 0; i < n_bnds; i++) { + in >> cd >> cv >> sd; // input bounding halfspace + // copy to array + bds[i] = ANNorthHalfSpace(cd, cv, sd); + } + // read inner and outer subtrees + ANNkd_ptr ic = annReadTree(in, tree_type, the_pidx, next_idx); + ANNkd_ptr oc = annReadTree(in, tree_type, the_pidx, next_idx); + // create new node and return + return new ANNbd_shrink(n_bnds, bds, ic, oc); + } + else { + annError("Illegal node type in dump file", ANNabort); + exit(0); // to keep the compiler happy + } +} diff --git a/dep/ann/kd_fix_rad_search.cpp b/dep/ann/kd_fix_rad_search.cpp new file mode 100644 index 00000000..c41ed1b0 --- /dev/null +++ b/dep/ann/kd_fix_rad_search.cpp @@ -0,0 +1,465 @@ +//---------------------------------------------------------------------- +// File: kd_fix_rad_search.cpp +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree fixed-radius kNN search +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 1.1 05/03/05 +// Initial release +//---------------------------------------------------------------------- + +#include "kd_fix_rad_search.h" // kd fixed-radius search decls + +//---------------------------------------------------------------------- +// Approximate fixed-radius k nearest neighbor search +// The squared radius is provided, and this procedure finds the +// k nearest neighbors within the radius, and returns the total +// number of points lying within the radius. +// +// The method used for searching the kd-tree is a variation of the +// nearest neighbor search used in kd_search.cpp, except that the +// radius of the search ball is known. We refer the reader to that +// file for the explanation of the recursive search procedure. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + +int ANNkdFRDim; // dimension of space +ANNpoint ANNkdFRQ; // query point +ANNdist ANNkdFRSqRad; // squared radius search bound +double ANNkdFRMaxErr; // max tolerable squared error +ANNpointArray ANNkdFRPts; // the points +ANNmin_k* ANNkdFRPointMK; // set of k closest points +int ANNkdFRPtsVisited; // total points visited +int ANNkdFRPtsInRange; // number of points in the range + +// these are added by Vlad to report nn's found during range search +// with out spending any time sorting them +ANNidxArray fr_search_indexes; +ANNdistArray fr_search_dists; +int fr_search_unordered; +int fr_search_k; // this his here so we know the length of the arrays above + + +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearch( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps) // the error bound +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating op count + + fr_search_unordered = 0; // added by Vlad so that the leaf nodes know where + // to put pts (either in priority queue or in array; this case pq) + ANNkdFRPointMK = new ANNmin_k(k); // create set for closest k points + // search starting at the root + root->ann_FR_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + for (int i = 0; i < k; i++) { // extract the k-th closest points + if (dd != NULL) + dd[i] = ANNkdFRPointMK->ith_smallest_key(i); + if (nn_idx != NULL) + nn_idx[i] = ANNkdFRPointMK->ith_smallest_info(i); + } + + delete ANNkdFRPointMK; // deallocate closest point set + return ANNkdFRPtsInRange; // return final point count +} + +// Added by Vlad to update flops even when ANN_PERF is not defined +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearchFlops( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps, // the error bound + int * flops ) // the number of floating ops performed by this query +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + if( flops != NULL ) + *flops = ann_Nfloat_ops; + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP_ALWAYS(2) // increment floating op count + + fr_search_unordered = 0; // added by Vlad so that the leaf nodes know where + // to put pts (either in priority queue or in array; this case pq) + ANNkdFRPointMK = new ANNmin_k(k); // create set for closest k points + // search starting at the root + root->ann_FR_searchFlops(annBoxDistanceFlops(q, bnd_box_lo, bnd_box_hi, dim)); + + for (int i = 0; i < k; i++) { // extract the k-th closest points + if (dd != NULL) + dd[i] = ANNkdFRPointMK->ith_smallest_key(i); + if (nn_idx != NULL) + nn_idx[i] = ANNkdFRPointMK->ith_smallest_info(i); + } + + if( flops != NULL ) + *flops = ann_Nfloat_ops - *flops; + + delete ANNkdFRPointMK; // deallocate closest point set + return ANNkdFRPtsInRange; // return final point count +} + +//---------------------------------------------------------------------- +// kd_split::ann_FR_search - search a splitting node +// Note: This routine is similar in structure to the standard kNN +// search. It visits the subtree that is closer to the query point +// first. For fixed-radius search, there is no benefit in visiting +// one subtree before the other, but we maintain the same basic +// code structure for the sake of uniformity. +//---------------------------------------------------------------------- + +void ANNkd_split::ann_FR_search(ANNdist box_dist) +{ + // check dist calc term condition + if (ANNmaxPtsVisited != 0 && ANNkdFRPtsVisited > ANNmaxPtsVisited) return; + + // distance to cutting plane + ANNcoord cut_diff = ANNkdFRQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + child[ANN_LO]->ann_FR_search(box_dist);// visit closer child first + + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdFRQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if in range + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_HI]->ann_FR_search(box_dist); + + } + else { // right of cutting plane + child[ANN_HI]->ann_FR_search(box_dist);// visit closer child first + + ANNcoord box_diff = ANNkdFRQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_LO]->ann_FR_search(box_dist); + + } + ANN_FLOP(13) // increment floating ops + ANN_SPL(1) // one more splitting node visited +} + +// Added by Vlad 5-1-08 to update flops even when ANN_PERF is not defined +//---------------------------------------------------------------------- +// kd_split::ann_FR_search - search a splitting node +// Note: This routine is similar in structure to the standard kNN +// search. It visits the subtree that is closer to the query point +// first. For fixed-radius search, there is no benefit in visiting +// one subtree before the other, but we maintain the same basic +// code structure for the sake of uniformity. +//---------------------------------------------------------------------- + +void ANNkd_split::ann_FR_searchFlops(ANNdist box_dist) +{ + // check dist calc term condition + if (ANNmaxPtsVisited != 0 && ANNkdFRPtsVisited > ANNmaxPtsVisited) return; + + // distance to cutting plane + ANNcoord cut_diff = ANNkdFRQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + child[ANN_LO]->ann_FR_searchFlops(box_dist);// visit closer child first + + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdFRQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if in range + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_HI]->ann_FR_searchFlops(box_dist); + + } + else { // right of cutting plane + child[ANN_HI]->ann_FR_searchFlops(box_dist);// visit closer child first + + ANNcoord box_diff = ANNkdFRQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdFRMaxErr <= ANNkdFRSqRad) + child[ANN_LO]->ann_FR_searchFlops(box_dist); + + } + ANN_FLOP_ALWAYS(13) // increment floating ops + ANN_SPL(1) // one more splitting node visited +} + +//---------------------------------------------------------------------- +// kd_leaf::ann_FR_search - search points in a leaf node +// Note: The unreadability of this code is the result of +// some fine tuning to replace indexing by pointer operations. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_FR_search(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNcoord t; + register int d; + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNkdFRPts[bkt[i]]; // first coord of next data point + qq = ANNkdFRQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNkdFRDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP(5) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > ANNkdFRSqRad) { + break; + } + } + + if (d >= ANNkdFRDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + if( fr_search_unordered == 0 ) + { + // add new neighbor and its distance to priority queue + ANNkdFRPointMK->insert(dist, bkt[i]); + } + else + { + // add new neighbor index and its distance to the unordered arrays + if( fr_search_indexes != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_indexes[ANNkdFRPtsInRange] = bkt[i]; + if( fr_search_dists != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_dists[ANNkdFRPtsInRange] = dist; + } + ANNkdFRPtsInRange++; // increment point count + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNkdFRPtsVisited += n_pts; // increment number of points visited +} + +// Added by Vlad to allow update of flops even when ANN_PERF is not +// defined, at the same time keeping the fast version of the fcn above +//---------------------------------------------------------------------- +// kd_leaf::ann_FR_search - search points in a leaf node +// Note: The unreadability of this code is the result of +// some fine tuning to replace indexing by pointer operations. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_FR_searchFlops(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNcoord t; + register int d; + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNkdFRPts[bkt[i]]; // first coord of next data point + qq = ANNkdFRQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNkdFRDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP_ALWAYS(5) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > ANNkdFRSqRad) { + break; + } + } + + if (d >= ANNkdFRDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + if( fr_search_unordered == 0 ) + { + // add new neighbor and its distance to priority queue + ANNkdFRPointMK->insertFlops(dist, bkt[i]); + } + else + { + // add new neighbor index and its distance to the unordered arrays + if( fr_search_indexes != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_indexes[ANNkdFRPtsInRange] = bkt[i]; + if( fr_search_dists != NULL && ANNkdFRPtsInRange < fr_search_k ) + fr_search_dists[ANNkdFRPtsInRange] = dist; + } + ANNkdFRPtsInRange++; // increment point count + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNkdFRPtsVisited += n_pts; // increment number of points visited +} + + +/////////////////////////////////////////////////////////////////////////////////////// +// +// +// +// +// Functions, added by Vlad to allow for unordered fixed radius search where all neighbors within +// radius are reported. This reduces the cost since we do not need to keep neighbors sorted. +// +// 6/10/08 +// +// +// +// +// +// +// +// +// +////////////////////////////////////////////////////////////////////////////////////// + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + + +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearchUnordered( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps) // the error bound +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating op count + + // set the flag that we are doing unordered search + fr_search_unordered = 1; + fr_search_indexes = nn_idx; + fr_search_dists = dd; + fr_search_k = k; + + // search starting at the root + root->ann_FR_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + return ANNkdFRPtsInRange; // return final point count +} + +// Added by Vlad to update flops even when ANN_PERF is not defined +//---------------------------------------------------------------------- +// annkFRSearch - fixed radius search for k nearest neighbors +//---------------------------------------------------------------------- + +int ANNkd_tree::annkFRSearchUnorderedFlops( + ANNpoint q, // the query point + ANNdist sqRad, // squared radius search bound + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps, // the error bound + int * flops ) // the number of floating ops performed by this query +{ + ANNkdFRDim = dim; // copy arguments to static equivs + ANNkdFRQ = q; + ANNkdFRSqRad = sqRad; + ANNkdFRPts = pts; + ANNkdFRPtsVisited = 0; // initialize count of points visited + ANNkdFRPtsInRange = 0; // ...and points in the range + + if( flops != NULL ) + *flops = ann_Nfloat_ops; + + ANNkdFRMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP_ALWAYS(2) // increment floating op count + + // set the flag that we are doing unordered search + fr_search_unordered = 1; + fr_search_indexes = nn_idx; + fr_search_dists = dd; + fr_search_k = k; + + // search starting at the root + root->ann_FR_searchFlops(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + if( flops != NULL ) + *flops = ann_Nfloat_ops - *flops; + + return ANNkdFRPtsInRange; // return final point count +} diff --git a/dep/ann/kd_fix_rad_search.h b/dep/ann/kd_fix_rad_search.h new file mode 100644 index 00000000..a9bc7089 --- /dev/null +++ b/dep/ann/kd_fix_rad_search.h @@ -0,0 +1,44 @@ +//---------------------------------------------------------------------- +// File: kd_fix_rad_search.h +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree fixed-radius kNN search +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 1.1 05/03/05 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_fix_rad_search_H +#define ANN_kd_fix_rad_search_H + +#include "kd_tree.h" // kd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "pr_queue_k.h" // k-element priority queue + +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// Global variables +// These are active for the life of each call to +// annRangeSearch(). They are set to save the number of +// variables that need to be passed among the various search +// procedures. +//---------------------------------------------------------------------- + +extern ANNpoint ANNkdFRQ; // query point (static copy) + +#endif diff --git a/dep/ann/kd_pr_search.cpp b/dep/ann/kd_pr_search.cpp new file mode 100644 index 00000000..0d16060c --- /dev/null +++ b/dep/ann/kd_pr_search.cpp @@ -0,0 +1,219 @@ +//---------------------------------------------------------------------- +// File: kd_pr_search.cpp +// Programmer: Sunil Arya and David Mount +// Description: Priority search for kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "kd_pr_search.h" // kd priority search declarations + +//---------------------------------------------------------------------- +// Approximate nearest neighbor searching by priority search. +// The kd-tree is searched for an approximate nearest neighbor. +// The point is returned through one of the arguments, and the +// distance returned is the SQUARED distance to this point. +// +// The method used for searching the kd-tree is called priority +// search. (It is described in Arya and Mount, ``Algorithms for +// fast vector quantization,'' Proc. of DCC '93: Data Compression +// Conference}, eds. J. A. Storer and M. Cohn, IEEE Press, 1993, +// 381--390.) +// +// The cell of the kd-tree containing the query point is located, +// and cells are visited in increasing order of distance from the +// query point. This is done by placing each subtree which has +// NOT been visited in a priority queue, according to the closest +// distance of the corresponding enclosing rectangle from the +// query point. The search stops when the distance to the nearest +// remaining rectangle exceeds the distance to the nearest point +// seen by a factor of more than 1/(1+eps). (Implying that any +// point found subsequently in the search cannot be closer by more +// than this factor.) +// +// The main entry point is annkPriSearch() which sets things up and +// then call the recursive routine ann_pri_search(). This is a +// recursive routine which performs the processing for one node in +// the kd-tree. There are two versions of this virtual procedure, +// one for splitting nodes and one for leaves. When a splitting node +// is visited, we determine which child to continue the search on +// (the closer one), and insert the other child into the priority +// queue. When a leaf is visited, we compute the distances to the +// points in the buckets, and update information on the closest +// points. +// +// Some trickery is used to incrementally update the distance from +// a kd-tree rectangle to the query point. This comes about from +// the fact that which each successive split, only one component +// (along the dimension that is split) of the squared distance to +// the child rectangle is different from the squared distance to +// the parent rectangle. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + +double ANNprEps; // the error bound +int ANNprDim; // dimension of space +ANNpoint ANNprQ; // query point +double ANNprMaxErr; // max tolerable squared error +ANNpointArray ANNprPts; // the points +ANNpr_queue *ANNprBoxPQ; // priority queue for boxes +ANNmin_k *ANNprPointMK; // set of k closest points + +//---------------------------------------------------------------------- +// annkPriSearch - priority search for k nearest neighbors +//---------------------------------------------------------------------- + +void ANNkd_tree::annkPriSearch( + ANNpoint q, // query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // dist to near neighbors (returned) + double eps) // error bound (ignored) +{ + // max tolerable squared error + ANNprMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating ops + + ANNprDim = dim; // copy arguments to static equivs + ANNprQ = q; + ANNprPts = pts; + ANNptsVisited = 0; // initialize count of points visited + + ANNprPointMK = new ANNmin_k(k); // create set for closest k points + + // distance to root box + ANNdist box_dist = annBoxDistance(q, + bnd_box_lo, bnd_box_hi, dim); + + ANNprBoxPQ = new ANNpr_queue(n_pts);// create priority queue for boxes + ANNprBoxPQ->insert(box_dist, root); // insert root in priority queue + + while (ANNprBoxPQ->non_empty() && + (!(ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited))) { + ANNkd_ptr np; // next box from prior queue + + // extract closest box from queue + ANNprBoxPQ->extr_min(box_dist, (void *&) np); + + ANN_FLOP(2) // increment floating ops + if (box_dist*ANNprMaxErr >= ANNprPointMK->max_key()) + break; + + np->ann_pri_search(box_dist); // search this subtree. + } + + for (int i = 0; i < k; i++) { // extract the k-th closest points + dd[i] = ANNprPointMK->ith_smallest_key(i); + nn_idx[i] = ANNprPointMK->ith_smallest_info(i); + } + + delete ANNprPointMK; // deallocate closest point set + delete ANNprBoxPQ; // deallocate priority queue +} + +//---------------------------------------------------------------------- +// kd_split::ann_pri_search - search a splitting node +//---------------------------------------------------------------------- + +void ANNkd_split::ann_pri_search(ANNdist box_dist) +{ + ANNdist new_dist; // distance to child visited later + // distance to cutting plane + ANNcoord cut_diff = ANNprQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNprQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + new_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + if (child[ANN_HI] != KD_TRIVIAL)// enqueue if not trivial + ANNprBoxPQ->insert(new_dist, child[ANN_HI]); + // continue with closer child + child[ANN_LO]->ann_pri_search(box_dist); + } + else { // right of cutting plane + ANNcoord box_diff = ANNprQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + new_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + if (child[ANN_LO] != KD_TRIVIAL)// enqueue if not trivial + ANNprBoxPQ->insert(new_dist, child[ANN_LO]); + // continue with closer child + child[ANN_HI]->ann_pri_search(box_dist); + } + ANN_SPL(1) // one more splitting node visited + ANN_FLOP(8) // increment floating ops +} + +//---------------------------------------------------------------------- +// kd_leaf::ann_pri_search - search points in a leaf node +// +// This is virtually identical to the ann_search for standard search. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_pri_search(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNdist min_dist; // distance to k-th closest point + register ANNcoord t; + register int d; + + min_dist = ANNprPointMK->max_key(); // k-th smallest distance so far + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNprPts[bkt[i]]; // first coord of next data point + qq = ANNprQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNprDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP(4) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > min_dist) { + break; + } + } + + if (d >= ANNprDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + ANNprPointMK->insert(dist, bkt[i]); + min_dist = ANNprPointMK->max_key(); + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNptsVisited += n_pts; // increment number of points visited +} diff --git a/dep/ann/kd_pr_search.h b/dep/ann/kd_pr_search.h new file mode 100644 index 00000000..ad4886ae --- /dev/null +++ b/dep/ann/kd_pr_search.h @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------- +// File: kd_pr_search.h +// Programmer: Sunil Arya and David Mount +// Description: Priority kd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_pr_search_H +#define ANN_kd_pr_search_H + +#include "kd_tree.h" // kd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "pr_queue.h" // priority queue declarations +#include "pr_queue_k.h" // k-element priority queue + +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// Global variables +// Active for the life of each call to Appx_Near_Neigh() or +// Appx_k_Near_Neigh(). +//---------------------------------------------------------------------- + +extern double ANNprEps; // the error bound +extern int ANNprDim; // dimension of space +extern ANNpoint ANNprQ; // query point +extern double ANNprMaxErr; // max tolerable squared error +extern ANNpointArray ANNprPts; // the points +extern ANNpr_queue *ANNprBoxPQ; // priority queue for boxes +extern ANNmin_k *ANNprPointMK; // set of k closest points + +#endif diff --git a/dep/ann/kd_search.cpp b/dep/ann/kd_search.cpp new file mode 100644 index 00000000..745e0e3c --- /dev/null +++ b/dep/ann/kd_search.cpp @@ -0,0 +1,210 @@ +//---------------------------------------------------------------------- +// File: kd_search.cpp +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed names LO, HI to ANN_LO, ANN_HI +//---------------------------------------------------------------------- + +#include "kd_search.h" // kd-search declarations + +//---------------------------------------------------------------------- +// Approximate nearest neighbor searching by kd-tree search +// The kd-tree is searched for an approximate nearest neighbor. +// The point is returned through one of the arguments, and the +// distance returned is the squared distance to this point. +// +// The method used for searching the kd-tree is an approximate +// adaptation of the search algorithm described by Friedman, +// Bentley, and Finkel, ``An algorithm for finding best matches +// in logarithmic expected time,'' ACM Transactions on Mathematical +// Software, 3(3):209-226, 1977). +// +// The algorithm operates recursively. When first encountering a +// node of the kd-tree we first visit the child which is closest to +// the query point. On return, we decide whether we want to visit +// the other child. If the box containing the other child exceeds +// 1/(1+eps) times the current best distance, then we skip it (since +// any point found in this child cannot be closer to the query point +// by more than this factor.) Otherwise, we visit it recursively. +// The distance between a box and the query point is computed exactly +// (not approximated as is often done in kd-tree), using incremental +// distance updates, as described by Arya and Mount in ``Algorithms +// for fast vector quantization,'' Proc. of DCC '93: Data Compression +// Conference, eds. J. A. Storer and M. Cohn, IEEE Press, 1993, +// 381-390. +// +// The main entry points is annkSearch() which sets things up and +// then call the recursive routine ann_search(). This is a recursive +// routine which performs the processing for one node in the kd-tree. +// There are two versions of this virtual procedure, one for splitting +// nodes and one for leaves. When a splitting node is visited, we +// determine which child to visit first (the closer one), and visit +// the other child on return. When a leaf is visited, we compute +// the distances to the points in the buckets, and update information +// on the closest points. +// +// Some trickery is used to incrementally update the distance from +// a kd-tree rectangle to the query point. This comes about from +// the fact that which each successive split, only one component +// (along the dimension that is split) of the squared distance to +// the child rectangle is different from the squared distance to +// the parent rectangle. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// To keep argument lists short, a number of global variables +// are maintained which are common to all the recursive calls. +// These are given below. +//---------------------------------------------------------------------- + +int ANNkdDim; // dimension of space +ANNpoint ANNkdQ; // query point +double ANNkdMaxErr; // max tolerable squared error +ANNpointArray ANNkdPts; // the points +ANNmin_k *ANNkdPointMK; // set of k closest points + +//---------------------------------------------------------------------- +// annkSearch - search for the k nearest neighbors +//---------------------------------------------------------------------- + +void ANNkd_tree::annkSearch( + ANNpoint q, // the query point + int k, // number of near neighbors to return + ANNidxArray nn_idx, // nearest neighbor indices (returned) + ANNdistArray dd, // the approximate nearest neighbor + double eps) // the error bound +{ + + ANNkdDim = dim; // copy arguments to static equivs + ANNkdQ = q; + ANNkdPts = pts; + ANNptsVisited = 0; // initialize count of points visited + + if (k > n_pts) { // too many near neighbors? + annError("Requesting more near neighbors than data points", ANNabort); + } + + ANNkdMaxErr = ANN_POW(1.0 + eps); + ANN_FLOP(2) // increment floating op count + + ANNkdPointMK = new ANNmin_k(k); // create set for closest k points + // search starting at the root + root->ann_search(annBoxDistance(q, bnd_box_lo, bnd_box_hi, dim)); + + for (int i = 0; i < k; i++) { // extract the k-th closest points + dd[i] = ANNkdPointMK->ith_smallest_key(i); + nn_idx[i] = ANNkdPointMK->ith_smallest_info(i); + } + delete ANNkdPointMK; // deallocate closest point set +} + +//---------------------------------------------------------------------- +// kd_split::ann_search - search a splitting node +//---------------------------------------------------------------------- + +void ANNkd_split::ann_search(ANNdist box_dist) +{ + // check dist calc term condition + if (ANNmaxPtsVisited != 0 && ANNptsVisited > ANNmaxPtsVisited) return; + + // distance to cutting plane + ANNcoord cut_diff = ANNkdQ[cut_dim] - cut_val; + + if (cut_diff < 0) { // left of cutting plane + child[ANN_LO]->ann_search(box_dist);// visit closer child first + + ANNcoord box_diff = cd_bnds[ANN_LO] - ANNkdQ[cut_dim]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdMaxErr < ANNkdPointMK->max_key()) + child[ANN_HI]->ann_search(box_dist); + + } + else { // right of cutting plane + child[ANN_HI]->ann_search(box_dist);// visit closer child first + + ANNcoord box_diff = ANNkdQ[cut_dim] - cd_bnds[ANN_HI]; + if (box_diff < 0) // within bounds - ignore + box_diff = 0; + // distance to further box + box_dist = (ANNdist) ANN_SUM(box_dist, + ANN_DIFF(ANN_POW(box_diff), ANN_POW(cut_diff))); + + // visit further child if close enough + if (box_dist * ANNkdMaxErr < ANNkdPointMK->max_key()) + child[ANN_LO]->ann_search(box_dist); + + } + ANN_FLOP(10) // increment floating ops + ANN_SPL(1) // one more splitting node visited +} + +//---------------------------------------------------------------------- +// kd_leaf::ann_search - search points in a leaf node +// Note: The unreadability of this code is the result of +// some fine tuning to replace indexing by pointer operations. +//---------------------------------------------------------------------- + +void ANNkd_leaf::ann_search(ANNdist box_dist) +{ + register ANNdist dist; // distance to data point + register ANNcoord* pp; // data coordinate pointer + register ANNcoord* qq; // query coordinate pointer + register ANNdist min_dist; // distance to k-th closest point + register ANNcoord t; + register int d; + + min_dist = ANNkdPointMK->max_key(); // k-th smallest distance so far + + for (int i = 0; i < n_pts; i++) { // check points in bucket + + pp = ANNkdPts[bkt[i]]; // first coord of next data point + qq = ANNkdQ; // first coord of query point + dist = 0; + + for(d = 0; d < ANNkdDim; d++) { + ANN_COORD(1) // one more coordinate hit + ANN_FLOP(4) // increment floating ops + + t = *(qq++) - *(pp++); // compute length and adv coordinate + // exceeds dist to k-th smallest? + if( (dist = ANN_SUM(dist, ANN_POW(t))) > min_dist) { + break; + } + } + + if (d >= ANNkdDim && // among the k best? + (ANN_ALLOW_SELF_MATCH || dist!=0)) { // and no self-match problem + // add it to the list + ANNkdPointMK->insert(dist, bkt[i]); + min_dist = ANNkdPointMK->max_key(); + } + } + ANN_LEAF(1) // one more leaf node visited + ANN_PTS(n_pts) // increment points visited + ANNptsVisited += n_pts; // increment number of points visited +} diff --git a/dep/ann/kd_search.h b/dep/ann/kd_search.h new file mode 100644 index 00000000..e0bda310 --- /dev/null +++ b/dep/ann/kd_search.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------- +// File: kd_search.h +// Programmer: Sunil Arya and David Mount +// Description: Standard kd-tree search +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_search_H +#define ANN_kd_search_H + +#include "kd_tree.h" // kd-tree declarations +#include "kd_util.h" // kd-tree utilities +#include "pr_queue_k.h" // k-element priority queue + +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// More global variables +// These are active for the life of each call to annkSearch(). They +// are set to save the number of variables that need to be passed +// among the various search procedures. +//---------------------------------------------------------------------- + +extern int ANNkdDim; // dimension of space (static copy) +extern ANNpoint ANNkdQ; // query point (static copy) +extern double ANNkdMaxErr; // max tolerable squared error +extern ANNpointArray ANNkdPts; // the points (static copy) +extern ANNmin_k *ANNkdPointMK; // set of k closest points +extern int ANNptsVisited; // number of points visited + +#endif diff --git a/dep/ann/kd_split.cpp b/dep/ann/kd_split.cpp new file mode 100644 index 00000000..f5fb6201 --- /dev/null +++ b/dep/ann/kd_split.cpp @@ -0,0 +1,428 @@ +//---------------------------------------------------------------------- +// File: kd_split.cpp +// Programmer: Sunil Arya and David Mount +// Description: Methods for splitting kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +//---------------------------------------------------------------------- + +#include "kd_tree.h" // kd-tree definitions +#include "kd_util.h" // kd-tree utilities +#include "kd_split.h" // splitting functions + +//---------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------- + +const double ERR = 0.001; // a small value +const double FS_ASPECT_RATIO = 3.0; // maximum allowed aspect ratio + // in fair split. Must be >= 2. + +//---------------------------------------------------------------------- +// kd_split - Bentley's standard splitting routine for kd-trees +// Find the dimension of the greatest spread, and split +// just before the median point along this dimension. +//---------------------------------------------------------------------- + +void kd_split( + ANNpointArray pa, // point array (permuted on return) + ANNidxArray pidx, // point indices + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + // find dimension of maximum spread + cut_dim = annMaxSpread(pa, pidx, n, dim); + n_lo = n/2; // median rank + // split about median + annMedianSplit(pa, pidx, n, cut_dim, cut_val, n_lo); +} + +//---------------------------------------------------------------------- +// midpt_split - midpoint splitting rule for box-decomposition trees +// +// This is the simplest splitting rule that guarantees boxes +// of bounded aspect ratio. It simply cuts the box with the +// longest side through its midpoint. If there are ties, it +// selects the dimension with the maximum point spread. +// +// WARNING: This routine (while simple) doesn't seem to work +// well in practice in high dimensions, because it tends to +// generate a large number of trivial and/or unbalanced splits. +// Either kd_split(), sl_midpt_split(), or fair_split() are +// recommended, instead. +//---------------------------------------------------------------------- + +void midpt_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + } + } + ANNcoord max_spread = -1; // find long side with most spread + for (d = 0; d < dim; d++) { + // is it among longest? + if (double(bnds.hi[d] - bnds.lo[d]) >= (1-ERR)*max_length) { + // compute its spread + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // is it max so far? + max_spread = spr; + cut_dim = d; + } + } + } + // split along cut_dim at midpoint + cut_val = (bnds.lo[cut_dim] + bnds.hi[cut_dim]) / 2; + // permute points accordingly + int br1, br2; + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + //------------------------------------------------------------------ + // On return: pa[0..br1-1] < cut_val + // pa[br1..br2-1] == cut_val + // pa[br2..n-1] > cut_val + // + // We can set n_lo to any value in the range [br1..br2]. + // We choose split so that points are most evenly divided. + //------------------------------------------------------------------ + if (br1 > n/2) n_lo = br1; + else if (br2 < n/2) n_lo = br2; + else n_lo = n/2; +} + +//---------------------------------------------------------------------- +// sl_midpt_split - sliding midpoint splitting rule +// +// This is a modification of midpt_split, which has the nonsensical +// name "sliding midpoint". The idea is that we try to use the +// midpoint rule, by bisecting the longest side. If there are +// ties, the dimension with the maximum spread is selected. If, +// however, the midpoint split produces a trivial split (no points +// on one side of the splitting plane) then we slide the splitting +// (maintaining its orientation) until it produces a nontrivial +// split. For example, if the splitting plane is along the x-axis, +// and all the data points have x-coordinate less than the x-bisector, +// then the split is taken along the maximum x-coordinate of the +// data points. +// +// Intuitively, this rule cannot generate trivial splits, and +// hence avoids midpt_split's tendency to produce trees with +// a very large number of nodes. +// +//---------------------------------------------------------------------- + +void sl_midpt_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + } + } + ANNcoord max_spread = -1; // find long side with most spread + for (d = 0; d < dim; d++) { + // is it among longest? + if ((bnds.hi[d] - bnds.lo[d]) >= (1-ERR)*max_length) { + // compute its spread + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // is it max so far? + max_spread = spr; + cut_dim = d; + } + } + } + // ideal split at midpoint + ANNcoord ideal_cut_val = (bnds.lo[cut_dim] + bnds.hi[cut_dim])/2; + + ANNcoord min, max; + annMinMax(pa, pidx, n, cut_dim, min, max); // find min/max coordinates + + if (ideal_cut_val < min) // slide to min or max as needed + cut_val = min; + else if (ideal_cut_val > max) + cut_val = max; + else + cut_val = ideal_cut_val; + + // permute points accordingly + int br1, br2; + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + //------------------------------------------------------------------ + // On return: pa[0..br1-1] < cut_val + // pa[br1..br2-1] == cut_val + // pa[br2..n-1] > cut_val + // + // We can set n_lo to any value in the range [br1..br2] to satisfy + // the exit conditions of the procedure. + // + // if ideal_cut_val < min (implying br2 >= 1), + // then we select n_lo = 1 (so there is one point on left) and + // if ideal_cut_val > max (implying br1 <= n-1), + // then we select n_lo = n-1 (so there is one point on right). + // Otherwise, we select n_lo as close to n/2 as possible within + // [br1..br2]. + //------------------------------------------------------------------ + if (ideal_cut_val < min) n_lo = 1; + else if (ideal_cut_val > max) n_lo = n-1; + else if (br1 > n/2) n_lo = br1; + else if (br2 < n/2) n_lo = br2; + else n_lo = n/2; +} + +//---------------------------------------------------------------------- +// fair_split - fair-split splitting rule +// +// This is a compromise between the kd-tree splitting rule (which +// always splits data points at their median) and the midpoint +// splitting rule (which always splits a box through its center. +// The goal of this procedure is to achieve both nicely balanced +// splits, and boxes of bounded aspect ratio. +// +// A constant FS_ASPECT_RATIO is defined. Given a box, those sides +// which can be split so that the ratio of the longest to shortest +// side does not exceed ASPECT_RATIO are identified. Among these +// sides, we select the one in which the points have the largest +// spread. We then split the points in a manner which most evenly +// distributes the points on either side of the splitting plane, +// subject to maintaining the bound on the ratio of long to short +// sides. To determine that the aspect ratio will be preserved, +// we determine the longest side (other than this side), and +// determine how narrowly we can cut this side, without causing the +// aspect ratio bound to be exceeded (small_piece). +// +// This procedure is more robust than either kd_split or midpt_split, +// but is more complicated as well. When point distribution is +// extremely skewed, this degenerates to midpt_split (actually +// 1/3 point split), and when the points are most evenly distributed, +// this degenerates to kd-split. +//---------------------------------------------------------------------- + +void fair_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + cut_dim = 0; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + cut_dim = d; + } + } + + ANNcoord max_spread = 0; // find legal cut with max spread + cut_dim = 0; + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + // is this side midpoint splitable + // without violating aspect ratio? + if (((double) max_length)*2.0/((double) length) <= FS_ASPECT_RATIO) { + // compute spread along this dim + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // best spread so far + max_spread = spr; + cut_dim = d; // this is dimension to cut + } + } + } + + max_length = 0; // find longest side other than cut_dim + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (d != cut_dim && length > max_length) + max_length = length; + } + // consider most extreme splits + ANNcoord small_piece = max_length / FS_ASPECT_RATIO; + ANNcoord lo_cut = bnds.lo[cut_dim] + small_piece;// lowest legal cut + ANNcoord hi_cut = bnds.hi[cut_dim] - small_piece;// highest legal cut + + int br1, br2; + // is median below lo_cut ? + if (annSplitBalance(pa, pidx, n, cut_dim, lo_cut) >= 0) { + cut_val = lo_cut; // cut at lo_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br1; + } + // is median above hi_cut? + else if (annSplitBalance(pa, pidx, n, cut_dim, hi_cut) <= 0) { + cut_val = hi_cut; // cut at hi_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br2; + } + else { // median cut preserves asp ratio + n_lo = n/2; // split about median + annMedianSplit(pa, pidx, n, cut_dim, cut_val, n_lo); + } +} + +//---------------------------------------------------------------------- +// sl_fair_split - sliding fair split splitting rule +// +// Sliding fair split is a splitting rule that combines the +// strengths of both fair split with sliding midpoint split. +// Fair split tends to produce balanced splits when the points +// are roughly uniformly distributed, but it can produce many +// trivial splits when points are highly clustered. Sliding +// midpoint never produces trivial splits, and shrinks boxes +// nicely if points are highly clustered, but it may produce +// rather unbalanced splits when points are unclustered but not +// quite uniform. +// +// Sliding fair split is based on the theory that there are two +// types of splits that are "good": balanced splits that produce +// fat boxes, and unbalanced splits provided the cell with fewer +// points is fat. +// +// This splitting rule operates by first computing the longest +// side of the current bounding box. Then it asks which sides +// could be split (at the midpoint) and still satisfy the aspect +// ratio bound with respect to this side. Among these, it selects +// the side with the largest spread (as fair split would). It +// then considers the most extreme cuts that would be allowed by +// the aspect ratio bound. This is done by dividing the longest +// side of the box by the aspect ratio bound. If the median cut +// lies between these extreme cuts, then we use the median cut. +// If not, then consider the extreme cut that is closer to the +// median. If all the points lie to one side of this cut, then +// we slide the cut until it hits the first point. This may +// violate the aspect ratio bound, but will never generate empty +// cells. However the sibling of every such skinny cell is fat, +// and hence packing arguments still apply. +// +//---------------------------------------------------------------------- + +void sl_fair_split( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo) // num of points on low side (returned) +{ + int d; + ANNcoord min, max; // min/max coordinates + int br1, br2; // split break points + + ANNcoord max_length = bnds.hi[0] - bnds.lo[0]; + cut_dim = 0; + for (d = 1; d < dim; d++) { // find length of longest box side + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (length > max_length) { + max_length = length; + cut_dim = d; + } + } + + ANNcoord max_spread = 0; // find legal cut with max spread + cut_dim = 0; + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + // is this side midpoint splitable + // without violating aspect ratio? + if (((double) max_length)*2.0/((double) length) <= FS_ASPECT_RATIO) { + // compute spread along this dim + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spread) { // best spread so far + max_spread = spr; + cut_dim = d; // this is dimension to cut + } + } + } + + max_length = 0; // find longest side other than cut_dim + for (d = 0; d < dim; d++) { + ANNcoord length = bnds.hi[d] - bnds.lo[d]; + if (d != cut_dim && length > max_length) + max_length = length; + } + // consider most extreme splits + ANNcoord small_piece = max_length / FS_ASPECT_RATIO; + ANNcoord lo_cut = bnds.lo[cut_dim] + small_piece;// lowest legal cut + ANNcoord hi_cut = bnds.hi[cut_dim] - small_piece;// highest legal cut + // find min and max along cut_dim + annMinMax(pa, pidx, n, cut_dim, min, max); + // is median below lo_cut? + if (annSplitBalance(pa, pidx, n, cut_dim, lo_cut) >= 0) { + if (max > lo_cut) { // are any points above lo_cut? + cut_val = lo_cut; // cut at lo_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br1; // balance if there are ties + } + else { // all points below lo_cut + cut_val = max; // cut at max value + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = n-1; + } + } + // is median above hi_cut? + else if (annSplitBalance(pa, pidx, n, cut_dim, hi_cut) <= 0) { + if (min < hi_cut) { // are any points below hi_cut? + cut_val = hi_cut; // cut at hi_cut + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = br2; // balance if there are ties + } + else { // all points above hi_cut + cut_val = min; // cut at min value + annPlaneSplit(pa, pidx, n, cut_dim, cut_val, br1, br2); + n_lo = 1; + } + } + else { // median cut is good enough + n_lo = n/2; // split about median + annMedianSplit(pa, pidx, n, cut_dim, cut_val, n_lo); + } +} diff --git a/dep/ann/kd_split.h b/dep/ann/kd_split.h new file mode 100644 index 00000000..130e188f --- /dev/null +++ b/dep/ann/kd_split.h @@ -0,0 +1,85 @@ +//---------------------------------------------------------------------- +// File: kd_split.h +// Programmer: Sunil Arya and David Mount +// Description: Methods for splitting kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_KD_SPLIT_H +#define ANN_KD_SPLIT_H + +#include "kd_tree.h" // kd-tree definitions + +//---------------------------------------------------------------------- +// External entry points +// These are all splitting procedures for kd-trees. +//---------------------------------------------------------------------- + +void kd_split( // standard (optimized) kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void midpt_split( // midpoint kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void sl_midpt_split( // sliding midpoint kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void fair_split( // fair-split kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +void sl_fair_split( // sliding fair-split kd-splitter + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +#endif diff --git a/dep/ann/kd_tree.cpp b/dep/ann/kd_tree.cpp new file mode 100644 index 00000000..ecd40564 --- /dev/null +++ b/dep/ann/kd_tree.cpp @@ -0,0 +1,405 @@ +//---------------------------------------------------------------------- +// File: kd_tree.cpp +// Programmer: Sunil Arya and David Mount +// Description: Basic methods for kd-trees. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Increased aspect ratio bound (ANN_AR_TOOBIG) from 100 to 1000. +// Fixed leaf counts to count trivial leaves. +// Added optional pa, pi arguments to Skeleton kd_tree constructor +// for use in load constructor. +// Added annClose() to eliminate KD_TRIVIAL memory leak. +//---------------------------------------------------------------------- + +#include "kd_tree.h" // kd-tree declarations +#include "kd_split.h" // kd-tree splitting rules +#include "kd_util.h" // kd-tree utilities +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// Global data +// +// For some splitting rules, especially with small bucket sizes, +// it is possible to generate a large number of empty leaf nodes. +// To save storage we allocate a single trivial leaf node which +// contains no points. For messy coding reasons it is convenient +// to have it reference a trivial point index. +// +// KD_TRIVIAL is allocated when the first kd-tree is created. It +// must *never* deallocated (since it may be shared by more than +// one tree). +//---------------------------------------------------------------------- +static int IDX_TRIVIAL[] = {0}; // trivial point index +ANNkd_leaf *KD_TRIVIAL = NULL; // trivial leaf node + +//---------------------------------------------------------------------- +// Printing the kd-tree +// These routines print a kd-tree in reverse inorder (high then +// root then low). (This is so that if you look at the output +// from the right side it appear from left to right in standard +// inorder.) When outputting leaves we output only the point +// indices rather than the point coordinates. There is an option +// to print the point coordinates separately. +// +// The tree printing routine calls the printing routines on the +// individual nodes of the tree, passing in the level or depth +// in the tree. The level in the tree is used to print indentation +// for readability. +//---------------------------------------------------------------------- + +void ANNkd_split::print( // print splitting node + int level, // depth of node in tree + ostream &out) // output stream +{ + child[ANN_HI]->print(level+1, out); // print high child + out << " "; + for (int i = 0; i < level; i++) // print indentation + out << ".."; + out << "Split cd=" << cut_dim << " cv=" << cut_val; + out << " lbnd=" << cd_bnds[ANN_LO]; + out << " hbnd=" << cd_bnds[ANN_HI]; + out << "\n"; + child[ANN_LO]->print(level+1, out); // print low child +} + +void ANNkd_leaf::print( // print leaf node + int level, // depth of node in tree + ostream &out) // output stream +{ + + out << " "; + for (int i = 0; i < level; i++) // print indentation + out << ".."; + + if (this == KD_TRIVIAL) { // canonical trivial leaf node + out << "Leaf (trivial)\n"; + } + else{ + out << "Leaf n=" << n_pts << " <"; + for (int j = 0; j < n_pts; j++) { + out << bkt[j]; + if (j < n_pts-1) out << ","; + } + out << ">\n"; + } +} + +void ANNkd_tree::Print( // print entire tree + ANNbool with_pts, // print points as well? + ostream &out) // output stream +{ + out << "ANN Version " << ANNversion << "\n"; + if (with_pts) { // print point coordinates + out << " Points:\n"; + for (int i = 0; i < n_pts; i++) { + out << "\t" << i << ": "; + annPrintPt(pts[i], dim, out); + out << "\n"; + } + } + if (root == NULL) // empty tree? + out << " Null tree.\n"; + else { + root->print(0, out); // invoke printing at root + } +} + +//---------------------------------------------------------------------- +// kd_tree statistics (for performance evaluation) +// This routine compute various statistics information for +// a kd-tree. It is used by the implementors for performance +// evaluation of the data structure. +//---------------------------------------------------------------------- + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +void ANNkdStats::merge(const ANNkdStats &st) // merge stats from child +{ + n_lf += st.n_lf; n_tl += st.n_tl; + n_spl += st.n_spl; n_shr += st.n_shr; + depth = MAX(depth, st.depth); + sum_ar += st.sum_ar; +} + +//---------------------------------------------------------------------- +// Update statistics for nodes +//---------------------------------------------------------------------- + +const double ANN_AR_TOOBIG = 1000; // too big an aspect ratio + +void ANNkd_leaf::getStats( // get subtree statistics + int dim, // dimension of space + ANNkdStats &st, // stats (modified) + ANNorthRect &bnd_box) // bounding box +{ + st.reset(); + st.n_lf = 1; // count this leaf + if (this == KD_TRIVIAL) st.n_tl = 1; // count trivial leaf + double ar = annAspectRatio(dim, bnd_box); // aspect ratio of leaf + // incr sum (ignore outliers) + st.sum_ar += float(ar < ANN_AR_TOOBIG ? ar : ANN_AR_TOOBIG); +} + +void ANNkd_split::getStats( // get subtree statistics + int dim, // dimension of space + ANNkdStats &st, // stats (modified) + ANNorthRect &bnd_box) // bounding box +{ + ANNkdStats ch_stats; // stats for children + // get stats for low child + ANNcoord hv = bnd_box.hi[cut_dim]; // save box bounds + bnd_box.hi[cut_dim] = cut_val; // upper bound for low child + ch_stats.reset(); // reset + child[ANN_LO]->getStats(dim, ch_stats, bnd_box); + st.merge(ch_stats); // merge them + bnd_box.hi[cut_dim] = hv; // restore bound + // get stats for high child + ANNcoord lv = bnd_box.lo[cut_dim]; // save box bounds + bnd_box.lo[cut_dim] = cut_val; // lower bound for high child + ch_stats.reset(); // reset + child[ANN_HI]->getStats(dim, ch_stats, bnd_box); + st.merge(ch_stats); // merge them + bnd_box.lo[cut_dim] = lv; // restore bound + + st.depth++; // increment depth + st.n_spl++; // increment number of splits +} + +//---------------------------------------------------------------------- +// getStats +// Collects a number of statistics related to kd_tree or +// bd_tree. +//---------------------------------------------------------------------- + +void ANNkd_tree::getStats( // get tree statistics + ANNkdStats &st) // stats (modified) +{ + st.reset(dim, n_pts, bkt_size); // reset stats + // create bounding box + ANNorthRect bnd_box(dim, bnd_box_lo, bnd_box_hi); + if (root != NULL) { // if nonempty tree + root->getStats(dim, st, bnd_box); // get statistics + st.avg_ar = st.sum_ar / st.n_lf; // average leaf asp ratio + } +} + +//---------------------------------------------------------------------- +// kd_tree destructor +// The destructor just frees the various elements that were +// allocated in the construction process. +//---------------------------------------------------------------------- + +ANNkd_tree::~ANNkd_tree() // tree destructor +{ + if (root != NULL) delete root; + if (pidx != NULL) delete [] pidx; + if (bnd_box_lo != NULL) annDeallocPt(bnd_box_lo); + if (bnd_box_hi != NULL) annDeallocPt(bnd_box_hi); +} + +//---------------------------------------------------------------------- +// This is called with all use of ANN is finished. It eliminates the +// minor memory leak caused by the allocation of KD_TRIVIAL. +//---------------------------------------------------------------------- +void annClose() // close use of ANN +{ + if (KD_TRIVIAL != NULL) { + delete KD_TRIVIAL; + KD_TRIVIAL = NULL; + } +} + +//---------------------------------------------------------------------- +// kd_tree constructors +// There is a skeleton kd-tree constructor which sets up a +// trivial empty tree. The last optional argument allows +// the routine to be passed a point index array which is +// assumed to be of the proper size (n). Otherwise, one is +// allocated and initialized to the identity. Warning: In +// either case the destructor will deallocate this array. +// +// As a kludge, we need to allocate KD_TRIVIAL if one has not +// already been allocated. (This is because I'm too dumb to +// figure out how to cause a pointer to be allocated at load +// time.) +//---------------------------------------------------------------------- + +void ANNkd_tree::SkeletonTree( // construct skeleton tree + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNpointArray pa, // point array + ANNidxArray pi) // point indices +{ + dim = dd; // initialize basic elements + n_pts = n; + bkt_size = bs; + pts = pa; // initialize points array + + root = NULL; // no associated tree yet + + if (pi == NULL) { // point indices provided? + pidx = new ANNidx[n]; // no, allocate space for point indices + for (int i = 0; i < n; i++) { + pidx[i] = i; // initially identity + } + } + else { + pidx = pi; // yes, use them + } + + bnd_box_lo = bnd_box_hi = NULL; // bounding box is nonexistent + if (KD_TRIVIAL == NULL) // no trivial leaf node yet? + KD_TRIVIAL = new ANNkd_leaf(0, IDX_TRIVIAL); // allocate it +} + +ANNkd_tree::ANNkd_tree( // basic constructor + int n, // number of points + int dd, // dimension + int bs) // bucket size +{ SkeletonTree(n, dd, bs); } // construct skeleton tree + +//---------------------------------------------------------------------- +// rkd_tree - recursive procedure to build a kd-tree +// +// Builds a kd-tree for points in pa as indexed through the +// array pidx[0..n-1] (typically a subarray of the array used in +// the top-level call). This routine permutes the array pidx, +// but does not alter pa[]. +// +// The construction is based on a standard algorithm for constructing +// the kd-tree (see Friedman, Bentley, and Finkel, ``An algorithm for +// finding best matches in logarithmic expected time,'' ACM Transactions +// on Mathematical Software, 3(3):209-226, 1977). The procedure +// operates by a simple divide-and-conquer strategy, which determines +// an appropriate orthogonal cutting plane (see below), and splits +// the points. When the number of points falls below the bucket size, +// we simply store the points in a leaf node's bucket. +// +// One of the arguments is a pointer to a splitting routine, +// whose prototype is: +// +// void split( +// ANNpointArray pa, // complete point array +// ANNidxArray pidx, // point array (permuted on return) +// ANNorthRect &bnds, // bounds of current cell +// int n, // number of points +// int dim, // dimension of space +// int &cut_dim, // cutting dimension +// ANNcoord &cut_val, // cutting value +// int &n_lo) // no. of points on low side of cut +// +// This procedure selects a cutting dimension and cutting value, +// partitions pa about these values, and returns the number of +// points on the low side of the cut. +//---------------------------------------------------------------------- + +ANNkd_ptr rkd_tree( // recursive construction of kd-tree + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter) // splitting routine +{ + if (n <= bsp) { // n small, make a leaf node + if (n == 0) // empty leaf node + return KD_TRIVIAL; // return (canonical) empty leaf + else // construct the node and return + return new ANNkd_leaf(n, pidx); + } + else { // n large, make a splitting node + int cd; // cutting dimension + ANNcoord cv; // cutting value + int n_lo; // number on low side of cut + ANNkd_node *lo, *hi; // low and high children + + // invoke splitting procedure + (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); + + ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension + ANNcoord hv = bnd_box.hi[cd]; + + bnd_box.hi[cd] = cv; // modify bounds for left subtree + lo = rkd_tree( // build left subtree + pa, pidx, n_lo, // ...from pidx[0..n_lo-1] + dim, bsp, bnd_box, splitter); + bnd_box.hi[cd] = hv; // restore bounds + + bnd_box.lo[cd] = cv; // modify bounds for right subtree + hi = rkd_tree( // build right subtree + pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] + dim, bsp, bnd_box, splitter); + bnd_box.lo[cd] = lv; // restore bounds + + // create the splitting node + ANNkd_split *ptr = new ANNkd_split(cd, cv, lv, hv, lo, hi); + + return ptr; // return pointer to this node + } +} + +//---------------------------------------------------------------------- +// kd-tree constructor +// This is the main constructor for kd-trees given a set of points. +// It first builds a skeleton tree, then computes the bounding box +// of the data points, and then invokes rkd_tree() to actually +// build the tree, passing it the appropriate splitting routine. +//---------------------------------------------------------------------- + +ANNkd_tree::ANNkd_tree( // construct from point array + ANNpointArray pa, // point array (with at least n pts) + int n, // number of points + int dd, // dimension + int bs, // bucket size + ANNsplitRule split) // splitting method +{ + SkeletonTree(n, dd, bs); // set up the basic stuff + pts = pa; // where the points are + if (n == 0) return; // no points--no sweat + + ANNorthRect bnd_box(dd); // bounding box for points + annEnclRect(pa, pidx, n, dd, bnd_box);// construct bounding rectangle + // copy to tree structure + bnd_box_lo = annCopyPt(dd, bnd_box.lo); + bnd_box_hi = annCopyPt(dd, bnd_box.hi); + + switch (split) { // build by rule + case ANN_KD_STD: // standard kd-splitting rule + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split); + break; + case ANN_KD_MIDPT: // midpoint split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split); + break; + case ANN_KD_FAIR: // fair split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split); + break; + case ANN_KD_SUGGEST: // best (in our opinion) + case ANN_KD_SL_MIDPT: // sliding midpoint split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split); + break; + case ANN_KD_SL_FAIR: // sliding fair split + root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_fair_split); + break; + default: + annError("Illegal splitting method", ANNabort); + } +} diff --git a/dep/ann/kd_tree.h b/dep/ann/kd_tree.h new file mode 100644 index 00000000..842b2854 --- /dev/null +++ b/dep/ann/kd_tree.h @@ -0,0 +1,206 @@ +//---------------------------------------------------------------------- +// File: kd_tree.h +// Programmer: Sunil Arya and David Mount +// Description: Declarations for standard kd-tree routines +// Last modified: 05/03/05 (Version 1.1) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.1 05/03/05 +// Added fixed radius kNN search +//---------------------------------------------------------------------- + +#ifndef ANN_kd_tree_H +#define ANN_kd_tree_H + +#include "ANNx.h" // all ANN includes + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// Generic kd-tree node +// +// Nodes in kd-trees are of two types, splitting nodes which contain +// splitting information (a splitting hyperplane orthogonal to one +// of the coordinate axes) and leaf nodes which contain point +// information (an array of points stored in a bucket). This is +// handled by making a generic class kd_node, which is essentially an +// empty shell, and then deriving the leaf and splitting nodes from +// this. +//---------------------------------------------------------------------- + +class ANNkd_node{ // generic kd-tree node (empty shell) +public: + virtual ~ANNkd_node() {} // virtual distroyer + + virtual void ann_search(ANNdist) = 0; // tree search + virtual void ann_pri_search(ANNdist) = 0; // priority search + virtual void ann_FR_search(ANNdist) = 0; // fixed-radius search + + // added by vlad to allow update of flops even when ANN_PERF is not defined + // this gives user choice between speed and stats at runtime + virtual void ann_FR_searchFlops(ANNdist)=0; // fixed-radius search + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box) = 0; // bounding box + // print node + virtual void print(int level, ostream &out) = 0; + virtual void dump(ostream &out) = 0; // dump node + + friend class ANNkd_tree; // allow kd-tree to access us +}; + +//---------------------------------------------------------------------- +// kd-splitting function: +// kd_splitter is a pointer to a splitting routine for preprocessing. +// Different splitting procedures result in different strategies +// for building the tree. +//---------------------------------------------------------------------- + +typedef void (*ANNkd_splitter)( // splitting routine for kd-trees + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices (permuted on return) + const ANNorthRect &bnds, // bounding rectangle for cell + int n, // number of points + int dim, // dimension of space + int &cut_dim, // cutting dimension (returned) + ANNcoord &cut_val, // cutting value (returned) + int &n_lo); // num of points on low side (returned) + +//---------------------------------------------------------------------- +// Leaf kd-tree node +// Leaf nodes of the kd-tree store the set of points associated +// with this bucket, stored as an array of point indices. These +// are indices in the array points, which resides with the +// root of the kd-tree. We also store the number of points +// that reside in this bucket. +//---------------------------------------------------------------------- + +class ANNkd_leaf: public ANNkd_node // leaf node for kd-tree +{ + int n_pts; // no. points in bucket + ANNidxArray bkt; // bucket of points +public: + ANNkd_leaf( // constructor + int n, // number of points + ANNidxArray b) // bucket + { + n_pts = n; // number of points in bucket + bkt = b; // the bucket + } + + ~ANNkd_leaf() { } // destructor (none) + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box); // bounding box + virtual void print(int level, ostream &out);// print node + virtual void dump(ostream &out); // dump node + + virtual void ann_search(ANNdist); // standard search + virtual void ann_pri_search(ANNdist); // priority search + virtual void ann_FR_search(ANNdist); // fixed-radius search + // added by Vlad to always update flops, even if ANN_PERF is not defined + virtual void ann_FR_searchFlops(ANNdist); // fixed-radius search +}; + +//---------------------------------------------------------------------- +// KD_TRIVIAL is a special pointer to an empty leaf node. Since +// some splitting rules generate many (more than 50%) trivial +// leaves, we use this one shared node to save space. +// +// The pointer is initialized to NULL, but whenever a kd-tree is +// created, we allocate this node, if it has not already been +// allocated. This node is *never* deallocated, so it produces +// a small memory leak. +//---------------------------------------------------------------------- + +extern ANNkd_leaf *KD_TRIVIAL; // trivial (empty) leaf node + +//---------------------------------------------------------------------- +// kd-tree splitting node. +// Splitting nodes contain a cutting dimension and a cutting value. +// These indicate the axis-parellel plane which subdivide the +// box for this node. The extent of the bounding box along the +// cutting dimension is maintained (this is used to speed up point +// to box distance calculations) [we do not store the entire bounding +// box since this may be wasteful of space in high dimensions]. +// We also store pointers to the 2 children. +//---------------------------------------------------------------------- + +class ANNkd_split : public ANNkd_node // splitting node of a kd-tree +{ + int cut_dim; // dim orthogonal to cutting plane + ANNcoord cut_val; // location of cutting plane + ANNcoord cd_bnds[2]; // lower and upper bounds of + // rectangle along cut_dim + ANNkd_ptr child[2]; // left and right children +public: + ANNkd_split( // constructor + int cd, // cutting dimension + ANNcoord cv, // cutting value + ANNcoord lv, ANNcoord hv, // low and high values + ANNkd_ptr lc=NULL, ANNkd_ptr hc=NULL) // children + { + cut_dim = cd; // cutting dimension + cut_val = cv; // cutting value + cd_bnds[ANN_LO] = lv; // lower bound for rectangle + cd_bnds[ANN_HI] = hv; // upper bound for rectangle + child[ANN_LO] = lc; // left child + child[ANN_HI] = hc; // right child + } + + ~ANNkd_split() // destructor + { + if (child[ANN_LO]!= NULL && child[ANN_LO]!= KD_TRIVIAL) + delete child[ANN_LO]; + if (child[ANN_HI]!= NULL && child[ANN_HI]!= KD_TRIVIAL) + delete child[ANN_HI]; + } + + virtual void getStats( // get tree statistics + int dim, // dimension of space + ANNkdStats &st, // statistics + ANNorthRect &bnd_box); // bounding box + virtual void print(int level, ostream &out);// print node + virtual void dump(ostream &out); // dump node + + virtual void ann_search(ANNdist); // standard search + virtual void ann_pri_search(ANNdist); // priority search + virtual void ann_FR_search(ANNdist); // fixed-radius search + + // added by Vlad on 5-1-08 so that flops are updated even when ANN_PERF is not defined + virtual void ann_FR_searchFlops(ANNdist); // fixed-radius search +}; + +//---------------------------------------------------------------------- +// External entry points +//---------------------------------------------------------------------- + +ANNkd_ptr rkd_tree( // recursive construction of kd-tree + ANNpointArray pa, // point array (unaltered) + ANNidxArray pidx, // point indices to store in subtree + int n, // number of points + int dim, // dimension of space + int bsp, // bucket space + ANNorthRect &bnd_box, // bounding box for current node + ANNkd_splitter splitter); // splitting routine + +#endif diff --git a/dep/ann/kd_util.cpp b/dep/ann/kd_util.cpp new file mode 100644 index 00000000..91fac7ef --- /dev/null +++ b/dep/ann/kd_util.cpp @@ -0,0 +1,471 @@ +//---------------------------------------------------------------------- +// File: kd_util.cpp +// Programmer: Sunil Arya and David Mount +// Description: Common utilities for kd-trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#include "kd_util.h" // kd-utility declarations + +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// The following routines are utility functions for manipulating +// points sets, used in determining splitting planes for kd-tree +// construction. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// NOTE: Virtually all point indexing is done through an index (i.e. +// permutation) array pidx. Consequently, a reference to the d-th +// coordinate of the i-th point is pa[pidx[i]][d]. The macro PA(i,d) +// is a shorthand for this. +//---------------------------------------------------------------------- + // standard 2-d indirect indexing +#define PA(i,d) (pa[pidx[(i)]][(d)]) + // accessing a single point +#define PP(i) (pa[pidx[(i)]]) + +//---------------------------------------------------------------------- +// annAspectRatio +// Compute the aspect ratio (ratio of longest to shortest side) +// of a rectangle. +//---------------------------------------------------------------------- + +double annAspectRatio( + int dim, // dimension + const ANNorthRect &bnd_box) // bounding cube +{ + ANNcoord length = bnd_box.hi[0] - bnd_box.lo[0]; + ANNcoord min_length = length; // min side length + ANNcoord max_length = length; // max side length + for (int d = 0; d < dim; d++) { + length = bnd_box.hi[d] - bnd_box.lo[d]; + if (length < min_length) min_length = length; + if (length > max_length) max_length = length; + } + return max_length/min_length; +} + +//---------------------------------------------------------------------- +// annEnclRect, annEnclCube +// These utilities compute the smallest rectangle and cube enclosing +// a set of points, respectively. +//---------------------------------------------------------------------- + +void annEnclRect( + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds) // bounding cube (returned) +{ + for (int d = 0; d < dim; d++) { // find smallest enclosing rectangle + ANNcoord lo_bnd = PA(0,d); // lower bound on dimension d + ANNcoord hi_bnd = PA(0,d); // upper bound on dimension d + for (int i = 0; i < n; i++) { + if (PA(i,d) < lo_bnd) lo_bnd = PA(i,d); + else if (PA(i,d) > hi_bnd) hi_bnd = PA(i,d); + } + bnds.lo[d] = lo_bnd; + bnds.hi[d] = hi_bnd; + } +} + +void annEnclCube( // compute smallest enclosing cube + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds) // bounding cube (returned) +{ + int d; + // compute smallest enclosing rect + annEnclRect(pa, pidx, n, dim, bnds); + + ANNcoord max_len = 0; // max length of any side + for (d = 0; d < dim; d++) { // determine max side length + ANNcoord len = bnds.hi[d] - bnds.lo[d]; + if (len > max_len) { // update max_len if longest + max_len = len; + } + } + for (d = 0; d < dim; d++) { // grow sides to match max + ANNcoord len = bnds.hi[d] - bnds.lo[d]; + ANNcoord half_diff = (max_len - len) / 2; + bnds.lo[d] -= half_diff; + bnds.hi[d] += half_diff; + } +} + +//---------------------------------------------------------------------- +// annBoxDistance - utility routine which computes distance from point to +// box (Note: most distances to boxes are computed using incremental +// distance updates, not this function.) +//---------------------------------------------------------------------- + +ANNdist annBoxDistance( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim) // dimension of space +{ + register ANNdist dist = 0.0; // sum of squared distances + register ANNdist t; + + for (register int d = 0; d < dim; d++) { + if (q[d] < lo[d]) { // q is left of box + t = ANNdist(lo[d]) - ANNdist(q[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + else if (q[d] > hi[d]) { // q is right of box + t = ANNdist(q[d]) - ANNdist(hi[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + } + ANN_FLOP(4*dim) // increment floating op count + + return dist; +} + +//---------------------------------------------------------------------- +// annBoxDistanceFlops - utility routine which computes distance from point to +// box (Note: most distances to boxes are computed using incremental +// distance updates, not this function.) +// Added by Vlad 5-1-08 to allow computation of flops if user desires it +// at runtime (while still keeping the fast version that does not compute flops). +//---------------------------------------------------------------------- + +ANNdist annBoxDistanceFlops( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim) // dimension of space +{ + register ANNdist dist = 0.0; // sum of squared distances + register ANNdist t; + + for (register int d = 0; d < dim; d++) { + if (q[d] < lo[d]) { // q is left of box + t = ANNdist(lo[d]) - ANNdist(q[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + else if (q[d] > hi[d]) { // q is right of box + t = ANNdist(q[d]) - ANNdist(hi[d]); + dist = ANN_SUM(dist, ANN_POW(t)); + } + } + ANN_FLOP_ALWAYS(4*dim) // increment floating op count + + return dist; +} + +//---------------------------------------------------------------------- +// annSpread - find spread along given dimension +// annMinMax - find min and max coordinates along given dimension +// annMaxSpread - find dimension of max spread +//---------------------------------------------------------------------- + +ANNcoord annSpread( // compute point spread along dimension + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d) // dimension to check +{ + ANNcoord min = PA(0,d); // compute max and min coords + ANNcoord max = PA(0,d); + for (int i = 1; i < n; i++) { + ANNcoord c = PA(i,d); + if (c < min) min = c; + else if (c > max) max = c; + } + return (max - min); // total spread is difference +} + +void annMinMax( // compute min and max coordinates along dim + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension to check + ANNcoord &min, // minimum value (returned) + ANNcoord &max) // maximum value (returned) +{ + min = PA(0,d); // compute max and min coords + max = PA(0,d); + for (int i = 1; i < n; i++) { + ANNcoord c = PA(i,d); + if (c < min) min = c; + else if (c > max) max = c; + } +} + +int annMaxSpread( // compute dimension of max spread + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim) // dimension of space +{ + int max_dim = 0; // dimension of max spread + ANNcoord max_spr = 0; // amount of max spread + + if (n == 0) return max_dim; // no points, who cares? + + for (int d = 0; d < dim; d++) { // compute spread along each dim + ANNcoord spr = annSpread(pa, pidx, n, d); + if (spr > max_spr) { // bigger than current max + max_spr = spr; + max_dim = d; + } + } + return max_dim; +} + +//---------------------------------------------------------------------- +// annMedianSplit - split point array about its median +// Splits a subarray of points pa[0..n] about an element of given +// rank (median: n_lo = n/2) with respect to dimension d. It places +// the element of rank n_lo-1 correctly (because our splitting rule +// takes the mean of these two). On exit, the array is permuted so +// that: +// +// pa[0..n_lo-2][d] <= pa[n_lo-1][d] <= pa[n_lo][d] <= pa[n_lo+1..n-1][d]. +// +// The mean of pa[n_lo-1][d] and pa[n_lo][d] is returned as the +// splitting value. +// +// All indexing is done indirectly through the index array pidx. +// +// This function uses the well known selection algorithm due to +// C.A.R. Hoare. +//---------------------------------------------------------------------- + + // swap two points in pa array +#define PASWAP(a,b) { int tmp = pidx[a]; pidx[a] = pidx[b]; pidx[b] = tmp; } + +void annMedianSplit( + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord &cv, // cutting value + int n_lo) // split into n_lo and n-n_lo +{ + int l = 0; // left end of current subarray + int r = n-1; // right end of current subarray + while (l < r) { + register int i = (r+l)/2; // select middle as pivot + register int k; + + if (PA(i,d) > PA(r,d)) // make sure last > pivot + PASWAP(i,r) + PASWAP(l,i); // move pivot to first position + + ANNcoord c = PA(l,d); // pivot value + i = l; + k = r; + for(;;) { // pivot about c + while (PA(++i,d) < c) ; + while (PA(--k,d) > c) ; + if (i < k) PASWAP(i,k) else break; + } + PASWAP(l,k); // pivot winds up in location k + + if (k > n_lo) r = k-1; // recurse on proper subarray + else if (k < n_lo) l = k+1; + else break; // got the median exactly + } + if (n_lo > 0) { // search for next smaller item + ANNcoord c = PA(0,d); // candidate for max + int k = 0; // candidate's index + for (int i = 1; i < n_lo; i++) { + if (PA(i,d) > c) { + c = PA(i,d); + k = i; + } + } + PASWAP(n_lo-1, k); // max among pa[0..n_lo-1] to pa[n_lo-1] + } + // cut value is midpoint value + cv = (PA(n_lo-1,d) + PA(n_lo,d))/2.0; +} + +//---------------------------------------------------------------------- +// annPlaneSplit - split point array about a cutting plane +// Split the points in an array about a given plane along a +// given cutting dimension. On exit, br1 and br2 are set so +// that: +// +// pa[ 0 ..br1-1] < cv +// pa[br1..br2-1] == cv +// pa[br2.. n -1] > cv +// +// All indexing is done indirectly through the index array pidx. +// +//---------------------------------------------------------------------- + +void annPlaneSplit( // split points by a plane + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv, // cutting value + int &br1, // first break (values < cv) + int &br2) // second break (values == cv) +{ + int l = 0; + int r = n-1; + for(;;) { // partition pa[0..n-1] about cv + while (l < n && PA(l,d) < cv) l++; + while (r >= 0 && PA(r,d) >= cv) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + br1 = l; // now: pa[0..br1-1] < cv <= pa[br1..n-1] + r = n-1; + for(;;) { // partition pa[br1..n-1] about cv + while (l < n && PA(l,d) <= cv) l++; + while (r >= br1 && PA(r,d) > cv) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + br2 = l; // now: pa[br1..br2-1] == cv < pa[br2..n-1] +} + + +//---------------------------------------------------------------------- +// annBoxSplit - split point array about a orthogonal rectangle +// Split the points in an array about a given orthogonal +// rectangle. On exit, n_in is set to the number of points +// that are inside (or on the boundary of) the rectangle. +// +// All indexing is done indirectly through the index array pidx. +// +//---------------------------------------------------------------------- + +void annBoxSplit( // split points by a box + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension of space + ANNorthRect &box, // the box + int &n_in) // number of points inside (returned) +{ + int l = 0; + int r = n-1; + for(;;) { // partition pa[0..n-1] about box + while (l < n && box.inside(dim, PP(l))) l++; + while (r >= 0 && !box.inside(dim, PP(r))) r--; + if (l > r) break; + PASWAP(l,r); + l++; r--; + } + n_in = l; // now: pa[0..n_in-1] inside and rest outside +} + +//---------------------------------------------------------------------- +// annSplitBalance - compute balance factor for a given plane split +// Balance factor is defined as the number of points lying +// below the splitting value minus n/2 (median). Thus, a +// median split has balance 0, left of this is negative and +// right of this is positive. (The points are unchanged.) +//---------------------------------------------------------------------- + +int annSplitBalance( // determine balance factor of a split + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv) // cutting value +{ + int n_lo = 0; + for(int i = 0; i < n; i++) { // count number less than cv + if (PA(i,d) < cv) n_lo++; + } + return n_lo - n/2; +} + +//---------------------------------------------------------------------- +// annBox2Bnds - convert bounding box to list of bounds +// Given two boxes, an inner box enclosed within a bounding +// box, this routine determines all the sides for which the +// inner box is strictly contained with the bounding box, +// and adds an appropriate entry to a list of bounds. Then +// we allocate storage for the final list of bounds, and return +// the resulting list and its size. +//---------------------------------------------------------------------- + +void annBox2Bnds( // convert inner box to bounds + const ANNorthRect &inner_box, // inner box + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int &n_bnds, // number of bounds (returned) + ANNorthHSArray &bnds) // bounds array (returned) +{ + int i; + n_bnds = 0; // count number of bounds + for (i = 0; i < dim; i++) { + if (inner_box.lo[i] > bnd_box.lo[i]) // low bound is inside + n_bnds++; + if (inner_box.hi[i] < bnd_box.hi[i]) // high bound is inside + n_bnds++; + } + + bnds = new ANNorthHalfSpace[n_bnds]; // allocate appropriate size + + int j = 0; + for (i = 0; i < dim; i++) { // fill the array + if (inner_box.lo[i] > bnd_box.lo[i]) { + bnds[j].cd = i; + bnds[j].cv = inner_box.lo[i]; + bnds[j].sd = +1; + j++; + } + if (inner_box.hi[i] < bnd_box.hi[i]) { + bnds[j].cd = i; + bnds[j].cv = inner_box.hi[i]; + bnds[j].sd = -1; + j++; + } + } +} + +//---------------------------------------------------------------------- +// annBnds2Box - convert list of bounds to bounding box +// Given an enclosing box and a list of bounds, this routine +// computes the corresponding inner box. It is assumed that +// the box points have been allocated already. +//---------------------------------------------------------------------- + +void annBnds2Box( + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int n_bnds, // number of bounds + ANNorthHSArray bnds, // bounds array + ANNorthRect &inner_box) // inner box (returned) +{ + annAssignRect(dim, inner_box, bnd_box); // copy bounding box to inner + + for (int i = 0; i < n_bnds; i++) { + bnds[i].project(inner_box.lo); // project each endpoint + bnds[i].project(inner_box.hi); + } +} diff --git a/dep/ann/kd_util.h b/dep/ann/kd_util.h new file mode 100644 index 00000000..18d7efbd --- /dev/null +++ b/dep/ann/kd_util.h @@ -0,0 +1,133 @@ +//---------------------------------------------------------------------- +// File: kd_util.h +// Programmer: Sunil Arya and David Mount +// Description: Common utilities for kd- trees +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef ANN_kd_util_H +#define ANN_kd_util_H + +#include "kd_tree.h" // kd-tree declarations + +//---------------------------------------------------------------------- +// externally accessible functions +//---------------------------------------------------------------------- + +double annAspectRatio( // compute aspect ratio of box + int dim, // dimension + const ANNorthRect &bnd_box); // bounding cube + +void annEnclRect( // compute smallest enclosing rectangle + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds); // bounding cube (returned) + +void annEnclCube( // compute smallest enclosing cube + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension + ANNorthRect &bnds); // bounding cube (returned) + +ANNdist annBoxDistance( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim); // dimension of space + +// added by vlad 5-1-2008 to allow user to compute flops at runtime in release version +// while keeping the version above fast +ANNdist annBoxDistanceFlops( // compute distance from point to box + const ANNpoint q, // the point + const ANNpoint lo, // low point of box + const ANNpoint hi, // high point of box + int dim); // dimension of space + + +ANNcoord annSpread( // compute point spread along dimension + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d); // dimension to check + +void annMinMax( // compute min and max coordinates along dim + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension to check + ANNcoord& min, // minimum value (returned) + ANNcoord& max); // maximum value (returned) + +int annMaxSpread( // compute dimension of max spread + ANNpointArray pa, // point array + ANNidxArray pidx, // point indices + int n, // number of points + int dim); // dimension of space + +void annMedianSplit( // split points along median value + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord &cv, // cutting value + int n_lo); // split into n_lo and n-n_lo + +void annPlaneSplit( // split points by a plane + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv, // cutting value + int &br1, // first break (values < cv) + int &br2); // second break (values == cv) + +void annBoxSplit( // split points by a box + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int dim, // dimension of space + ANNorthRect &box, // the box + int &n_in); // number of points inside (returned) + +int annSplitBalance( // determine balance factor of a split + ANNpointArray pa, // points to split + ANNidxArray pidx, // point indices + int n, // number of points + int d, // dimension along which to split + ANNcoord cv); // cutting value + +void annBox2Bnds( // convert inner box to bounds + const ANNorthRect &inner_box, // inner box + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int &n_bnds, // number of bounds (returned) + ANNorthHSArray &bnds); // bounds array (returned) + +void annBnds2Box( // convert bounds to inner box + const ANNorthRect &bnd_box, // enclosing box + int dim, // dimension of space + int n_bnds, // number of bounds + ANNorthHSArray bnds, // bounds array + ANNorthRect &inner_box); // inner box (returned) + +#endif diff --git a/dep/ann/perf.cpp b/dep/ann/perf.cpp new file mode 100644 index 00000000..e18a9d03 --- /dev/null +++ b/dep/ann/perf.cpp @@ -0,0 +1,134 @@ +//---------------------------------------------------------------------- +// File: perf.cpp +// Programmer: Sunil Arya and David Mount +// Description: Methods for performance stats +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +// Revision 1.0 04/01/05 +// Changed names to avoid namespace conflicts. +// Added flush after printing performance stats to fix bug +// in Microsoft Windows version. +//---------------------------------------------------------------------- + +#include "ANN.h" // basic ANN includes +#include "ANNperf.h" // performance includes + +using namespace std; // make std:: available + +//---------------------------------------------------------------------- +// Performance statistics +// The following data and routines are used for computing +// performance statistics for nearest neighbor searching. +// Because these routines can slow the code down, they can be +// activated and deactiviated by defining the PERF variable, +// by compiling with the option: -DPERF +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Global counters for performance measurement +//---------------------------------------------------------------------- + +int ann_Ndata_pts = 0; // number of data points +int ann_Nvisit_lfs = 0; // number of leaf nodes visited +int ann_Nvisit_spl = 0; // number of splitting nodes visited +int ann_Nvisit_shr = 0; // number of shrinking nodes visited +int ann_Nvisit_pts = 0; // visited points for one query +int ann_Ncoord_hts = 0; // coordinate hits for one query +int ann_Nfloat_ops = 0; // floating ops for one query +ANNsampStat ann_visit_lfs; // stats on leaf nodes visits +ANNsampStat ann_visit_spl; // stats on splitting nodes visits +ANNsampStat ann_visit_shr; // stats on shrinking nodes visits +ANNsampStat ann_visit_nds; // stats on total nodes visits +ANNsampStat ann_visit_pts; // stats on points visited +ANNsampStat ann_coord_hts; // stats on coordinate hits +ANNsampStat ann_float_ops; // stats on floating ops +// +ANNsampStat ann_average_err; // average error +ANNsampStat ann_rank_err; // rank error + +//---------------------------------------------------------------------- +// Routines for statistics. +//---------------------------------------------------------------------- + +DLL_API void annResetStats(int data_size) // reset stats for a set of queries +{ + ann_Ndata_pts = data_size; + ann_visit_lfs.reset(); + ann_visit_spl.reset(); + ann_visit_shr.reset(); + ann_visit_nds.reset(); + ann_visit_pts.reset(); + ann_coord_hts.reset(); + ann_float_ops.reset(); + ann_average_err.reset(); + ann_rank_err.reset(); +} + +DLL_API void annResetCounts() // reset counts for one query +{ + ann_Nvisit_lfs = 0; + ann_Nvisit_spl = 0; + ann_Nvisit_shr = 0; + ann_Nvisit_pts = 0; + ann_Ncoord_hts = 0; + ann_Nfloat_ops = 0; +} + +DLL_API void annUpdateStats() // update stats with current counts +{ + ann_visit_lfs += ann_Nvisit_lfs; + ann_visit_nds += ann_Nvisit_spl + ann_Nvisit_lfs; + ann_visit_spl += ann_Nvisit_spl; + ann_visit_shr += ann_Nvisit_shr; + ann_visit_pts += ann_Nvisit_pts; + ann_coord_hts += ann_Ncoord_hts; + ann_float_ops += ann_Nfloat_ops; +} + + // print a single statistic +void print_one_stat(char *title, ANNsampStat s, double div) +{ + cout << title << "= [ "; + cout.width(9); cout << s.mean()/div << " : "; + cout.width(9); cout << s.stdDev()/div << " ]<"; + cout.width(9); cout << s.min()/div << " , "; + cout.width(9); cout << s.max()/div << " >\n"; +} + +DLL_API void annPrintStats( // print statistics for a run + ANNbool validate) // true if average errors desired +{ + cout.precision(4); // set floating precision + cout << " (Performance stats: " + << " [ mean : stddev ]< min , max >\n"; + print_one_stat(" leaf_nodes ", ann_visit_lfs, 1); + print_one_stat(" splitting_nodes ", ann_visit_spl, 1); + print_one_stat(" shrinking_nodes ", ann_visit_shr, 1); + print_one_stat(" total_nodes ", ann_visit_nds, 1); + print_one_stat(" points_visited ", ann_visit_pts, 1); + print_one_stat(" coord_hits/pt ", ann_coord_hts, ann_Ndata_pts); + print_one_stat(" floating_ops_(K) ", ann_float_ops, 1000); + if (validate) { + print_one_stat(" average_error ", ann_average_err, 1); + print_one_stat(" rank_error ", ann_rank_err, 1); + } + cout.precision(0); // restore the default + cout << " )\n"; + cout.flush(); +} diff --git a/dep/ann/pr_queue.h b/dep/ann/pr_queue.h new file mode 100644 index 00000000..94d49bcf --- /dev/null +++ b/dep/ann/pr_queue.h @@ -0,0 +1,125 @@ +//---------------------------------------------------------------------- +// File: pr_queue.h +// Programmer: Sunil Arya and David Mount +// Description: Include file for priority queue and related +// structures. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef PR_QUEUE_H +#define PR_QUEUE_H + +#include "ANNx.h" // all ANN includes +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// Basic types. +//---------------------------------------------------------------------- +typedef void *PQinfo; // info field is generic pointer +typedef ANNdist PQkey; // key field is distance + +//---------------------------------------------------------------------- +// Priority queue +// A priority queue is a list of items, along with associated +// priorities. The basic operations are insert and extract_minimum. +// +// The priority queue is maintained using a standard binary heap. +// (Implementation note: Indexing is performed from [1..max] rather +// than the C standard of [0..max-1]. This simplifies parent/child +// computations.) User information consists of a void pointer, +// and the user is responsible for casting this quantity into whatever +// useful form is desired. +// +// Because the priority queue is so central to the efficiency of +// query processing, all the code is inline. +//---------------------------------------------------------------------- + +class ANNpr_queue { + + struct pq_node { // node in priority queue + PQkey key; // key value + PQinfo info; // info field + }; + int n; // number of items in queue + int max_size; // maximum queue size + pq_node *pq; // the priority queue (array of nodes) + +public: + ANNpr_queue(int max) // constructor (given max size) + { + n = 0; // initially empty + max_size = max; // maximum number of items + pq = new pq_node[max+1]; // queue is array [1..max] of nodes + } + + ~ANNpr_queue() // destructor + { delete [] pq; } + + ANNbool empty() // is queue empty? + { if (n==0) return ANNtrue; else return ANNfalse; } + + ANNbool non_empty() // is queue nonempty? + { if (n==0) return ANNfalse; else return ANNtrue; } + + void reset() // make existing queue empty + { n = 0; } + + inline void insert( // insert item (inlined for speed) + PQkey kv, // key value + PQinfo inf) // item info + { + if (++n > max_size) annError("Priority queue overflow.", ANNabort); + register int r = n; + while (r > 1) { // sift up new item + register int p = r/2; + ANN_FLOP(1) // increment floating ops + if (pq[p].key <= kv) // in proper order + break; + pq[r] = pq[p]; // else swap with parent + r = p; + } + pq[r].key = kv; // insert new item at final location + pq[r].info = inf; + } + + inline void extr_min( // extract minimum (inlined for speed) + PQkey &kv, // key (returned) + PQinfo &inf) // item info (returned) + { + kv = pq[1].key; // key of min item + inf = pq[1].info; // information of min item + register PQkey kn = pq[n--].key;// last item in queue + register int p = 1; // p points to item out of position + register int r = p<<1; // left child of p + while (r <= n) { // while r is still within the heap + ANN_FLOP(2) // increment floating ops + // set r to smaller child of p + if (r < n && pq[r].key > pq[r+1].key) r++; + if (kn <= pq[r].key) // in proper order + break; + pq[p] = pq[r]; // else swap with child + p = r; // advance pointers + r = p<<1; + } + pq[p] = pq[n+1]; // insert last item in proper place + } +}; + +#endif diff --git a/dep/ann/pr_queue_k.h b/dep/ann/pr_queue_k.h new file mode 100644 index 00000000..61e02f70 --- /dev/null +++ b/dep/ann/pr_queue_k.h @@ -0,0 +1,138 @@ +//---------------------------------------------------------------------- +// File: pr_queue_k.h +// Programmer: Sunil Arya and David Mount +// Description: Include file for priority queue with k items. +// Last modified: 01/04/05 (Version 1.0) +//---------------------------------------------------------------------- +// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and +// David Mount. All Rights Reserved. +// +// This software and related documentation is part of the Approximate +// Nearest Neighbor Library (ANN). This software is provided under +// the provisions of the Lesser GNU Public License (LGPL). See the +// file ../ReadMe.txt for further information. +// +// The University of Maryland (U.M.) and the authors make no +// representations about the suitability or fitness of this software for +// any purpose. It is provided "as is" without express or implied +// warranty. +//---------------------------------------------------------------------- +// History: +// Revision 0.1 03/04/98 +// Initial release +//---------------------------------------------------------------------- + +#ifndef PR_QUEUE_K_H +#define PR_QUEUE_K_H + +#include "ANNx.h" // all ANN includes +#include "ANNperf.h" // performance evaluation + +//---------------------------------------------------------------------- +// Basic types +//---------------------------------------------------------------------- +typedef ANNdist PQKkey; // key field is distance +typedef int PQKinfo; // info field is int + +//---------------------------------------------------------------------- +// Constants +// The NULL key value is used to initialize the priority queue, and +// so it should be larger than any valid distance, so that it will +// be replaced as legal distance values are inserted. The NULL +// info value must be a nonvalid array index, we use ANN_NULL_IDX, +// which is guaranteed to be negative. +//---------------------------------------------------------------------- + +const PQKkey PQ_NULL_KEY = ANN_DIST_INF; // nonexistent key value +const PQKinfo PQ_NULL_INFO = ANN_NULL_IDX; // nonexistent info value + +//---------------------------------------------------------------------- +// ANNmin_k +// An ANNmin_k structure is one which maintains the smallest +// k values (of type PQKkey) and associated information (of type +// PQKinfo). The special info and key values PQ_NULL_INFO and +// PQ_NULL_KEY means that thise entry is empty. +// +// It is currently implemented using an array with k items. +// Items are stored in increasing sorted order, and insertions +// are made through standard insertion sort. (This is quite +// inefficient, but current applications call for small values +// of k and relatively few insertions.) +// +// Note that the list contains k+1 entries, but the last entry +// is used as a simple placeholder and is otherwise ignored. +//---------------------------------------------------------------------- + +class ANNmin_k { + struct mk_node { // node in min_k structure + PQKkey key; // key value + PQKinfo info; // info field (user defined) + }; + + int k; // max number of keys to store + int n; // number of keys currently active + mk_node *mk; // the list itself + +public: + ANNmin_k(int max) // constructor (given max size) + { + n = 0; // initially no items + k = max; // maximum number of items + mk = new mk_node[max+1]; // sorted array of keys + } + + ~ANNmin_k() // destructor + { delete [] mk; } + + PQKkey ANNmin_key() // return minimum key + { return (n > 0 ? mk[0].key : PQ_NULL_KEY); } + + PQKkey max_key() // return maximum key + { return (n == k ? mk[k-1].key : PQ_NULL_KEY); } + + PQKkey ith_smallest_key(int i) // ith smallest key (i in [0..n-1]) + { return (i < n ? mk[i].key : PQ_NULL_KEY); } + + PQKinfo ith_smallest_info(int i) // info for ith smallest (i in [0..n-1]) + { return (i < n ? mk[i].info : PQ_NULL_INFO); } + + inline void insert( // insert item (inlined for speed) + PQKkey kv, // key value + PQKinfo inf) // item info + { + register int i; + // slide larger values up + for (i = n; i > 0; i--) { + if (mk[i-1].key > kv) + mk[i] = mk[i-1]; + else + break; + } + mk[i].key = kv; // store element here + mk[i].info = inf; + if (n < k) n++; // increment number of items + ANN_FLOP(k-i+1) // increment floating ops + } + + // added by Vlad 5-1-08 to allow user to update flops by calling this + // function even when ANN_PERF is not defined + inline void insertFlops( // insert item (inlined for speed) + PQKkey kv, // key value + PQKinfo inf) // item info + { + register int i; + // slide larger values up + for (i = n; i > 0; i--) { + if (mk[i-1].key > kv) + mk[i] = mk[i-1]; + else + break; + } + mk[i].key = kv; // store element here + mk[i].info = inf; + if (n < k) n++; // increment number of items + ANN_FLOP_ALWAYS(k-i+1) // increment floating ops + } +}; + +#endif diff --git a/dep/blas/CMakeLists.txt b/dep/blas/CMakeLists.txt new file mode 100644 index 00000000..c2b92f42 --- /dev/null +++ b/dep/blas/CMakeLists.txt @@ -0,0 +1,15 @@ + +enable_language(Fortran) + +FILE(GLOB slsrc "*.f") +add_library(depblas ${slsrc}) + +INSTALL(TARGETS depblas DESTINATION lib) + +# Install the header files +SET(blas_HEADERS + depblas.h + ) + +INSTALL(FILES ${blas_HEADERS} DESTINATION include/dep) + diff --git a/dep/blas/LICENSE b/dep/blas/LICENSE new file mode 100644 index 00000000..ad95793e --- /dev/null +++ b/dep/blas/LICENSE @@ -0,0 +1,14 @@ +http://www.netlib.org/blas/faq.html#2 + +The reference BLAS is a freely-available software package. It is available from netlib +via anonymous ftp and the World Wide Web. Thus, it can be included in commercial software +packages (and has been). We only ask that proper credit be given to the authors. + +Like all software, it is copyrighted. It is not trademarked, but we do ask the following: + +If you modify the source for these routines we ask that you change the name of the routine +and comment the changes made to the original. + +We will gladly answer any questions regarding the software. If a modification is done, +however, it is the responsibility of the person who modified the routine to provide +support. diff --git a/dep/blas/caxpy.f b/dep/blas/caxpy.f new file mode 100644 index 00000000..7037c5a5 --- /dev/null +++ b/dep/blas/caxpy.f @@ -0,0 +1,34 @@ + subroutine caxpy(n,ca,cx,incx,cy,incy) +c +c constant times a vector plus a vector. +c jack dongarra, linpack, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*),cy(*),ca + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if (abs(real(ca)) + abs(aimag(ca)) .eq. 0.0 ) return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + cy(iy) = cy(iy) + ca*cx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + cy(i) = cy(i) + ca*cx(i) + 30 continue + return + end diff --git a/dep/blas/ccopy.f b/dep/blas/ccopy.f new file mode 100644 index 00000000..61d5267e --- /dev/null +++ b/dep/blas/ccopy.f @@ -0,0 +1,33 @@ + subroutine ccopy(n,cx,incx,cy,incy) +c +c copies a vector, x, to a vector, y. +c jack dongarra, linpack, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*),cy(*) + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + cy(iy) = cx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + cy(i) = cx(i) + 30 continue + return + end diff --git a/dep/blas/cdotc.f b/dep/blas/cdotc.f new file mode 100644 index 00000000..1d589059 --- /dev/null +++ b/dep/blas/cdotc.f @@ -0,0 +1,38 @@ + complex function cdotc(n,cx,incx,cy,incy) +c +c forms the dot product of two vectors, conjugating the first +c vector. +c jack dongarra, linpack, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*),cy(*),ctemp + integer i,incx,incy,ix,iy,n +c + ctemp = (0.0,0.0) + cdotc = (0.0,0.0) + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + ctemp = ctemp + conjg(cx(ix))*cy(iy) + ix = ix + incx + iy = iy + incy + 10 continue + cdotc = ctemp + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + ctemp = ctemp + conjg(cx(i))*cy(i) + 30 continue + cdotc = ctemp + return + end diff --git a/dep/blas/cdotu.f b/dep/blas/cdotu.f new file mode 100644 index 00000000..d88cea45 --- /dev/null +++ b/dep/blas/cdotu.f @@ -0,0 +1,37 @@ + complex function cdotu(n,cx,incx,cy,incy) +c +c forms the dot product of two vectors. +c jack dongarra, linpack, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*),cy(*),ctemp + integer i,incx,incy,ix,iy,n +c + ctemp = (0.0,0.0) + cdotu = (0.0,0.0) + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + ctemp = ctemp + cx(ix)*cy(iy) + ix = ix + incx + iy = iy + incy + 10 continue + cdotu = ctemp + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + ctemp = ctemp + cx(i)*cy(i) + 30 continue + cdotu = ctemp + return + end diff --git a/dep/blas/cgbmv.f b/dep/blas/cgbmv.f new file mode 100644 index 00000000..5b559c12 --- /dev/null +++ b/dep/blas/cgbmv.f @@ -0,0 +1,322 @@ + SUBROUTINE CGBMV ( TRANS, M, N, KL, KU, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + COMPLEX ALPHA, BETA + INTEGER INCX, INCY, KL, KU, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + COMPLEX A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* CGBMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, or +* +* y := alpha*conjg( A' )*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n band matrix, with kl sub-diagonals and ku super-diagonals. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*conjg( A' )*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* KL - INTEGER. +* On entry, KL specifies the number of sub-diagonals of the +* matrix A. KL must satisfy 0 .le. KL. +* Unchanged on exit. +* +* KU - INTEGER. +* On entry, KU specifies the number of super-diagonals of the +* matrix A. KU must satisfy 0 .le. KU. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, n ). +* Before entry, the leading ( kl + ku + 1 ) by n part of the +* array A must contain the matrix of coefficients, supplied +* column by column, with the leading diagonal of the matrix in +* row ( ku + 1 ) of the array, the first super-diagonal +* starting at position 2 in row ku, the first sub-diagonal +* starting at position 1 in row ( ku + 2 ), and so on. +* Elements in the array A that do not correspond to elements +* in the band matrix (such as the top left ku by ku triangle) +* are not referenced. +* The following program segment will transfer a band matrix +* from conventional full matrix storage to band storage: +* +* DO 20, J = 1, N +* K = KU + 1 - J +* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) +* A( K + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( kl + ku + 1 ). +* Unchanged on exit. +* +* X - COMPLEX array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - COMPLEX . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - COMPLEX array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry, the incremented array Y must contain the +* vector y. On exit, Y is overwritten by the updated vector y. +* +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX ONE + PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) ) + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. Local Scalars .. + COMPLEX TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, K, KUP1, KX, KY, + $ LENX, LENY + LOGICAL NOCONJ +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( KL.LT.0 )THEN + INFO = 4 + ELSE IF( KU.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( KL + KU + 1 ) )THEN + INFO = 8 + ELSE IF( INCX.EQ.0 )THEN + INFO = 10 + ELSE IF( INCY.EQ.0 )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CGBMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the band part of A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + KUP1 = KU + 1 + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + K = KUP1 - J + DO 50, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( I ) = Y( I ) + TEMP*A( K + I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + K = KUP1 - J + DO 70, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( IY ) = Y( IY ) + TEMP*A( K + I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + IF( J.GT.KU ) + $ KY = KY + INCY + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y or y := alpha*conjg( A' )*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = ZERO + K = KUP1 - J + IF( NOCONJ )THEN + DO 90, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( I ) + 90 CONTINUE + ELSE + DO 100, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + CONJG( A( K + I, J ) )*X( I ) + 100 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 110 CONTINUE + ELSE + DO 140, J = 1, N + TEMP = ZERO + IX = KX + K = KUP1 - J + IF( NOCONJ )THEN + DO 120, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + ELSE + DO 130, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + CONJG( A( K + I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + IF( J.GT.KU ) + $ KX = KX + INCX + 140 CONTINUE + END IF + END IF +* + RETURN +* +* End of CGBMV . +* + END diff --git a/dep/blas/cgemm.f b/dep/blas/cgemm.f new file mode 100644 index 00000000..14ebdc07 --- /dev/null +++ b/dep/blas/cgemm.f @@ -0,0 +1,414 @@ + SUBROUTINE CGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, + $ BETA, C, LDC ) +* .. Scalar Arguments .. + CHARACTER*1 TRANSA, TRANSB + INTEGER M, N, K, LDA, LDB, LDC + COMPLEX ALPHA, BETA +* .. Array Arguments .. + COMPLEX A( LDA, * ), B( LDB, * ), C( LDC, * ) +* .. +* +* Purpose +* ======= +* +* CGEMM performs one of the matrix-matrix operations +* +* C := alpha*op( A )*op( B ) + beta*C, +* +* where op( X ) is one of +* +* op( X ) = X or op( X ) = X' or op( X ) = conjg( X' ), +* +* alpha and beta are scalars, and A, B and C are matrices, with op( A ) +* an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. +* +* Parameters +* ========== +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n', op( A ) = A. +* +* TRANSA = 'T' or 't', op( A ) = A'. +* +* TRANSA = 'C' or 'c', op( A ) = conjg( A' ). +* +* Unchanged on exit. +* +* TRANSB - CHARACTER*1. +* On entry, TRANSB specifies the form of op( B ) to be used in +* the matrix multiplication as follows: +* +* TRANSB = 'N' or 'n', op( B ) = B. +* +* TRANSB = 'T' or 't', op( B ) = B'. +* +* TRANSB = 'C' or 'c', op( B ) = conjg( B' ). +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix +* op( A ) and of the matrix C. M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix +* op( B ) and the number of columns of the matrix C. N must be +* at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry, K specifies the number of columns of the matrix +* op( A ) and the number of rows of the matrix op( B ). K must +* be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, ka ), where ka is +* k when TRANSA = 'N' or 'n', and is m otherwise. +* Before entry with TRANSA = 'N' or 'n', the leading m by k +* part of the array A must contain the matrix A, otherwise +* the leading k by m part of the array A must contain the +* matrix A. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When TRANSA = 'N' or 'n' then +* LDA must be at least max( 1, m ), otherwise LDA must be at +* least max( 1, k ). +* Unchanged on exit. +* +* B - COMPLEX array of DIMENSION ( LDB, kb ), where kb is +* n when TRANSB = 'N' or 'n', and is k otherwise. +* Before entry with TRANSB = 'N' or 'n', the leading k by n +* part of the array B must contain the matrix B, otherwise +* the leading n by k part of the array B must contain the +* matrix B. +* Unchanged on exit. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. When TRANSB = 'N' or 'n' then +* LDB must be at least max( 1, k ), otherwise LDB must be at +* least max( 1, n ). +* Unchanged on exit. +* +* BETA - COMPLEX . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then C need not be set on input. +* Unchanged on exit. +* +* C - COMPLEX array of DIMENSION ( LDC, n ). +* Before entry, the leading m by n part of the array C must +* contain the matrix C, except when beta is zero, in which +* case C need not be set on entry. +* On exit, the array C is overwritten by the m by n matrix +* ( alpha*op( A )*op( B ) + beta*C ). +* +* LDC - INTEGER. +* On entry, LDC specifies the first dimension of C as declared +* in the calling (sub) program. LDC must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX +* .. Local Scalars .. + LOGICAL CONJA, CONJB, NOTA, NOTB + INTEGER I, INFO, J, L, NCOLA, NROWA, NROWB + COMPLEX TEMP +* .. Parameters .. + COMPLEX ONE + PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) ) + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. +* .. Executable Statements .. +* +* Set NOTA and NOTB as true if A and B respectively are not +* conjugated or transposed, set CONJA and CONJB as true if A and +* B respectively are to be transposed but not conjugated and set +* NROWA, NCOLA and NROWB as the number of rows and columns of A +* and the number of rows of B respectively. +* + NOTA = LSAME( TRANSA, 'N' ) + NOTB = LSAME( TRANSB, 'N' ) + CONJA = LSAME( TRANSA, 'C' ) + CONJB = LSAME( TRANSB, 'C' ) + IF( NOTA )THEN + NROWA = M + NCOLA = K + ELSE + NROWA = K + NCOLA = M + END IF + IF( NOTB )THEN + NROWB = K + ELSE + NROWB = N + END IF +* +* Test the input parameters. +* + INFO = 0 + IF( ( .NOT.NOTA ).AND. + $ ( .NOT.CONJA ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.NOTB ).AND. + $ ( .NOT.CONJB ).AND. + $ ( .NOT.LSAME( TRANSB, 'T' ) ) )THEN + INFO = 2 + ELSE IF( M .LT.0 )THEN + INFO = 3 + ELSE IF( N .LT.0 )THEN + INFO = 4 + ELSE IF( K .LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 8 + ELSE IF( LDB.LT.MAX( 1, NROWB ) )THEN + INFO = 10 + ELSE IF( LDC.LT.MAX( 1, M ) )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CGEMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ( ALPHA.EQ.ZERO ).OR.( K.EQ.0 ) ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + IF( BETA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + C( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40, J = 1, N + DO 30, I = 1, M + C( I, J ) = BETA*C( I, J ) + 30 CONTINUE + 40 CONTINUE + END IF + RETURN + END IF +* +* Start the operations. +* + IF( NOTB )THEN + IF( NOTA )THEN +* +* Form C := alpha*A*B + beta*C. +* + DO 90, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 50, I = 1, M + C( I, J ) = ZERO + 50 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 60, I = 1, M + C( I, J ) = BETA*C( I, J ) + 60 CONTINUE + END IF + DO 80, L = 1, K + IF( B( L, J ).NE.ZERO )THEN + TEMP = ALPHA*B( L, J ) + DO 70, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 70 CONTINUE + END IF + 80 CONTINUE + 90 CONTINUE + ELSE IF( CONJA )THEN +* +* Form C := alpha*conjg( A' )*B + beta*C. +* + DO 120, J = 1, N + DO 110, I = 1, M + TEMP = ZERO + DO 100, L = 1, K + TEMP = TEMP + CONJG( A( L, I ) )*B( L, J ) + 100 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 110 CONTINUE + 120 CONTINUE + ELSE +* +* Form C := alpha*A'*B + beta*C +* + DO 150, J = 1, N + DO 140, I = 1, M + TEMP = ZERO + DO 130, L = 1, K + TEMP = TEMP + A( L, I )*B( L, J ) + 130 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 140 CONTINUE + 150 CONTINUE + END IF + ELSE IF( NOTA )THEN + IF( CONJB )THEN +* +* Form C := alpha*A*conjg( B' ) + beta*C. +* + DO 200, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 160, I = 1, M + C( I, J ) = ZERO + 160 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 170, I = 1, M + C( I, J ) = BETA*C( I, J ) + 170 CONTINUE + END IF + DO 190, L = 1, K + IF( B( J, L ).NE.ZERO )THEN + TEMP = ALPHA*CONJG( B( J, L ) ) + DO 180, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 180 CONTINUE + END IF + 190 CONTINUE + 200 CONTINUE + ELSE +* +* Form C := alpha*A*B' + beta*C +* + DO 250, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 210, I = 1, M + C( I, J ) = ZERO + 210 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 220, I = 1, M + C( I, J ) = BETA*C( I, J ) + 220 CONTINUE + END IF + DO 240, L = 1, K + IF( B( J, L ).NE.ZERO )THEN + TEMP = ALPHA*B( J, L ) + DO 230, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 230 CONTINUE + END IF + 240 CONTINUE + 250 CONTINUE + END IF + ELSE IF( CONJA )THEN + IF( CONJB )THEN +* +* Form C := alpha*conjg( A' )*conjg( B' ) + beta*C. +* + DO 280, J = 1, N + DO 270, I = 1, M + TEMP = ZERO + DO 260, L = 1, K + TEMP = TEMP + CONJG( A( L, I ) )*CONJG( B( J, L ) ) + 260 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 270 CONTINUE + 280 CONTINUE + ELSE +* +* Form C := alpha*conjg( A' )*B' + beta*C +* + DO 310, J = 1, N + DO 300, I = 1, M + TEMP = ZERO + DO 290, L = 1, K + TEMP = TEMP + CONJG( A( L, I ) )*B( J, L ) + 290 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 300 CONTINUE + 310 CONTINUE + END IF + ELSE + IF( CONJB )THEN +* +* Form C := alpha*A'*conjg( B' ) + beta*C +* + DO 340, J = 1, N + DO 330, I = 1, M + TEMP = ZERO + DO 320, L = 1, K + TEMP = TEMP + A( L, I )*CONJG( B( J, L ) ) + 320 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 330 CONTINUE + 340 CONTINUE + ELSE +* +* Form C := alpha*A'*B' + beta*C +* + DO 370, J = 1, N + DO 360, I = 1, M + TEMP = ZERO + DO 350, L = 1, K + TEMP = TEMP + A( L, I )*B( J, L ) + 350 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 360 CONTINUE + 370 CONTINUE + END IF + END IF +* + RETURN +* +* End of CGEMM . +* + END diff --git a/dep/blas/cgemv.f b/dep/blas/cgemv.f new file mode 100644 index 00000000..04872d8d --- /dev/null +++ b/dep/blas/cgemv.f @@ -0,0 +1,281 @@ + SUBROUTINE CGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + COMPLEX ALPHA, BETA + INTEGER INCX, INCY, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + COMPLEX A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* CGEMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, or +* +* y := alpha*conjg( A' )*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n matrix. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*conjg( A' )*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* X - COMPLEX array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - COMPLEX . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - COMPLEX array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry with BETA non-zero, the incremented array Y +* must contain the vector y. On exit, Y is overwritten by the +* updated vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX ONE + PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) ) + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. Local Scalars .. + COMPLEX TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY, LENX, LENY + LOGICAL NOCONJ +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 6 + ELSE IF( INCX.EQ.0 )THEN + INFO = 8 + ELSE IF( INCY.EQ.0 )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CGEMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + DO 50, I = 1, M + Y( I ) = Y( I ) + TEMP*A( I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + DO 70, I = 1, M + Y( IY ) = Y( IY ) + TEMP*A( I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y or y := alpha*conjg( A' )*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = ZERO + IF( NOCONJ )THEN + DO 90, I = 1, M + TEMP = TEMP + A( I, J )*X( I ) + 90 CONTINUE + ELSE + DO 100, I = 1, M + TEMP = TEMP + CONJG( A( I, J ) )*X( I ) + 100 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 110 CONTINUE + ELSE + DO 140, J = 1, N + TEMP = ZERO + IX = KX + IF( NOCONJ )THEN + DO 120, I = 1, M + TEMP = TEMP + A( I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + ELSE + DO 130, I = 1, M + TEMP = TEMP + CONJG( A( I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 140 CONTINUE + END IF + END IF +* + RETURN +* +* End of CGEMV . +* + END diff --git a/dep/blas/cgerc.f b/dep/blas/cgerc.f new file mode 100644 index 00000000..288e192d --- /dev/null +++ b/dep/blas/cgerc.f @@ -0,0 +1,157 @@ + SUBROUTINE CGERC ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + COMPLEX ALPHA + INTEGER INCX, INCY, LDA, M, N +* .. Array Arguments .. + COMPLEX A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* CGERC performs the rank 1 operation +* +* A := alpha*x*conjg( y' ) + A, +* +* where alpha is a scalar, x is an m element vector, y is an n element +* vector and A is an m by n matrix. +* +* Parameters +* ========== +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - COMPLEX array of dimension at least +* ( 1 + ( m - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the m +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - COMPLEX array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. On exit, A is +* overwritten by the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. Local Scalars .. + COMPLEX TEMP + INTEGER I, INFO, IX, J, JY, KX +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( M.LT.0 )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CGERC ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( INCY.GT.0 )THEN + JY = 1 + ELSE + JY = 1 - ( N - 1 )*INCY + END IF + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*CONJG( Y( JY ) ) + DO 10, I = 1, M + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + END IF + JY = JY + INCY + 20 CONTINUE + ELSE + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( M - 1 )*INCX + END IF + DO 40, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*CONJG( Y( JY ) ) + IX = KX + DO 30, I = 1, M + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + END IF + JY = JY + INCY + 40 CONTINUE + END IF +* + RETURN +* +* End of CGERC . +* + END diff --git a/dep/blas/cgeru.f b/dep/blas/cgeru.f new file mode 100644 index 00000000..8a9ac390 --- /dev/null +++ b/dep/blas/cgeru.f @@ -0,0 +1,157 @@ + SUBROUTINE CGERU ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + COMPLEX ALPHA + INTEGER INCX, INCY, LDA, M, N +* .. Array Arguments .. + COMPLEX A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* CGERU performs the rank 1 operation +* +* A := alpha*x*y' + A, +* +* where alpha is a scalar, x is an m element vector, y is an n element +* vector and A is an m by n matrix. +* +* Parameters +* ========== +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - COMPLEX array of dimension at least +* ( 1 + ( m - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the m +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - COMPLEX array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. On exit, A is +* overwritten by the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. Local Scalars .. + COMPLEX TEMP + INTEGER I, INFO, IX, J, JY, KX +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( M.LT.0 )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CGERU ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( INCY.GT.0 )THEN + JY = 1 + ELSE + JY = 1 - ( N - 1 )*INCY + END IF + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + DO 10, I = 1, M + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + END IF + JY = JY + INCY + 20 CONTINUE + ELSE + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( M - 1 )*INCX + END IF + DO 40, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + IX = KX + DO 30, I = 1, M + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + END IF + JY = JY + INCY + 40 CONTINUE + END IF +* + RETURN +* +* End of CGERU . +* + END diff --git a/dep/blas/cscal.f b/dep/blas/cscal.f new file mode 100644 index 00000000..56eeebac --- /dev/null +++ b/dep/blas/cscal.f @@ -0,0 +1,28 @@ + subroutine cscal(n,ca,cx,incx) +c +c scales a vector by a constant. +c jack dongarra, linpack, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex ca,cx(*) + integer i,incx,n,nincx +c + if( n.le.0 .or. incx.le.0 )return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + nincx = n*incx + do 10 i = 1,nincx,incx + cx(i) = ca*cx(i) + 10 continue + return +c +c code for increment equal to 1 +c + 20 do 30 i = 1,n + cx(i) = ca*cx(i) + 30 continue + return + end diff --git a/dep/blas/csscal.f b/dep/blas/csscal.f new file mode 100644 index 00000000..edd7e555 --- /dev/null +++ b/dep/blas/csscal.f @@ -0,0 +1,29 @@ + subroutine csscal(n,sa,cx,incx) +c +c scales a complex vector by a real constant. +c jack dongarra, linpack, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*) + real sa + integer i,incx,n,nincx +c + if( n.le.0 .or. incx.le.0 )return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + nincx = n*incx + do 10 i = 1,nincx,incx + cx(i) = cmplx(sa*real(cx(i)),sa*aimag(cx(i))) + 10 continue + return +c +c code for increment equal to 1 +c + 20 do 30 i = 1,n + cx(i) = cmplx(sa*real(cx(i)),sa*aimag(cx(i))) + 30 continue + return + end diff --git a/dep/blas/cswap.f b/dep/blas/cswap.f new file mode 100644 index 00000000..ede4495f --- /dev/null +++ b/dep/blas/cswap.f @@ -0,0 +1,36 @@ + subroutine cswap (n,cx,incx,cy,incy) +c +c interchanges two vectors. +c jack dongarra, linpack, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*),cy(*),ctemp + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments not equal +c to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + ctemp = cx(ix) + cx(ix) = cy(iy) + cy(iy) = ctemp + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 + 20 do 30 i = 1,n + ctemp = cx(i) + cx(i) = cy(i) + cy(i) = ctemp + 30 continue + return + end diff --git a/dep/blas/ctbsv.f b/dep/blas/ctbsv.f new file mode 100644 index 00000000..abe4c77a --- /dev/null +++ b/dep/blas/ctbsv.f @@ -0,0 +1,381 @@ + SUBROUTINE CTBSV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, K, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + COMPLEX A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* CTBSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, or conjg( A' )*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular band matrix, with ( k + 1 ) +* diagonals. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' conjg( A' )*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with UPLO = 'U' or 'u', K specifies the number of +* super-diagonals of the matrix A. +* On entry with UPLO = 'L' or 'l', K specifies the number of +* sub-diagonals of the matrix A. +* K must satisfy 0 .le. K. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) +* by n part of the array A must contain the upper triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row +* ( k + 1 ) of the array, the first super-diagonal starting at +* position 2 in row k, and so on. The top left k by k triangle +* of the array A is not referenced. +* The following program segment will transfer an upper +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = K + 1 - J +* DO 10, I = MAX( 1, J - K ), J +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) +* by n part of the array A must contain the lower triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row 1 of +* the array, the first sub-diagonal starting at position 1 in +* row 2, and so on. The bottom right k by k triangle of the +* array A is not referenced. +* The following program segment will transfer a lower +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = 1 - J +* DO 10, I = J, MIN( N, J + K ) +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Note that when DIAG = 'U' or 'u' the elements of the array A +* corresponding to the diagonal elements of the matrix are not +* referenced, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( k + 1 ). +* Unchanged on exit. +* +* X - COMPLEX array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. Local Scalars .. + COMPLEX TEMP + INTEGER I, INFO, IX, J, JX, KPLUS1, KX, L + LOGICAL NOCONJ, NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( K.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( K + 1 ) )THEN + INFO = 7 + ELSE IF( INCX.EQ.0 )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CTBSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed by sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + L = KPLUS1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( KPLUS1, J ) + TEMP = X( J ) + DO 10, I = J - 1, MAX( 1, J - K ), -1 + X( I ) = X( I ) - TEMP*A( L + I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 40, J = N, 1, -1 + KX = KX - INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = KPLUS1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( KPLUS1, J ) + TEMP = X( JX ) + DO 30, I = J - 1, MAX( 1, J - K ), -1 + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX - INCX + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + L = 1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( 1, J ) + TEMP = X( J ) + DO 50, I = J + 1, MIN( N, J + K ) + X( I ) = X( I ) - TEMP*A( L + I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + KX = KX + INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = 1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( 1, J ) + TEMP = X( JX ) + DO 70, I = J + 1, MIN( N, J + K ) + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX + INCX + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A' )*x or x := inv( conjg( A') )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = X( J ) + L = KPLUS1 - J + IF( NOCONJ )THEN + DO 90, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + ELSE + DO 100, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - CONJG( A( L + I, J ) )*X( I ) + 100 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( KPLUS1, J ) ) + END IF + X( J ) = TEMP + 110 CONTINUE + ELSE + JX = KX + DO 140, J = 1, N + TEMP = X( JX ) + IX = KX + L = KPLUS1 - J + IF( NOCONJ )THEN + DO 120, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + ELSE + DO 130, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - CONJG( A( L + I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( KPLUS1, J ) ) + END IF + X( JX ) = TEMP + JX = JX + INCX + IF( J.GT.K ) + $ KX = KX + INCX + 140 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 170, J = N, 1, -1 + TEMP = X( J ) + L = 1 - J + IF( NOCONJ )THEN + DO 150, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( I ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + ELSE + DO 160, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - CONJG( A( L + I, J ) )*X( I ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( 1, J ) ) + END IF + X( J ) = TEMP + 170 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 200, J = N, 1, -1 + TEMP = X( JX ) + IX = KX + L = 1 - J + IF( NOCONJ )THEN + DO 180, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX - INCX + 180 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + ELSE + DO 190, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - CONJG( A( L + I, J ) )*X( IX ) + IX = IX - INCX + 190 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( 1, J ) ) + END IF + X( JX ) = TEMP + JX = JX - INCX + IF( ( N - J ).GE.K ) + $ KX = KX - INCX + 200 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of CTBSV . +* + END diff --git a/dep/blas/ctrmm.f b/dep/blas/ctrmm.f new file mode 100644 index 00000000..6c75e490 --- /dev/null +++ b/dep/blas/ctrmm.f @@ -0,0 +1,392 @@ + SUBROUTINE CTRMM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + COMPLEX ALPHA +* .. Array Arguments .. + COMPLEX A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* CTRMM performs one of the matrix-matrix operations +* +* B := alpha*op( A )*B, or B := alpha*B*op( A ) +* +* where alpha is a scalar, B is an m by n matrix, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A' or op( A ) = conjg( A' ). +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) multiplies B from +* the left or right as follows: +* +* SIDE = 'L' or 'l' B := alpha*op( A )*B. +* +* SIDE = 'R' or 'r' B := alpha*B*op( A ). +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = conjg( A' ). +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - COMPLEX array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the matrix B, and on exit is overwritten by the +* transformed matrix. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOCONJ, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + COMPLEX TEMP +* .. Parameters .. + COMPLEX ONE + PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) ) + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOCONJ = LSAME( TRANSA, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CTRMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*A*B. +* + IF( UPPER )THEN + DO 50, J = 1, N + DO 40, K = 1, M + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + DO 30, I = 1, K - 1 + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 30 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + B( K, J ) = TEMP + END IF + 40 CONTINUE + 50 CONTINUE + ELSE + DO 80, J = 1, N + DO 70 K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + B( K, J ) = TEMP + IF( NOUNIT ) + $ B( K, J ) = B( K, J )*A( K, K ) + DO 60, I = K + 1, M + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 60 CONTINUE + END IF + 70 CONTINUE + 80 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A' or B := alpha*B*conjg( A' ). +* + IF( UPPER )THEN + DO 120, J = 1, N + DO 110, I = M, 1, -1 + TEMP = B( I, J ) + IF( NOCONJ )THEN + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 90, K = 1, I - 1 + TEMP = TEMP + A( K, I )*B( K, J ) + 90 CONTINUE + ELSE + IF( NOUNIT ) + $ TEMP = TEMP*CONJG( A( I, I ) ) + DO 100, K = 1, I - 1 + TEMP = TEMP + CONJG( A( K, I ) )*B( K, J ) + 100 CONTINUE + END IF + B( I, J ) = ALPHA*TEMP + 110 CONTINUE + 120 CONTINUE + ELSE + DO 160, J = 1, N + DO 150, I = 1, M + TEMP = B( I, J ) + IF( NOCONJ )THEN + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 130, K = I + 1, M + TEMP = TEMP + A( K, I )*B( K, J ) + 130 CONTINUE + ELSE + IF( NOUNIT ) + $ TEMP = TEMP*CONJG( A( I, I ) ) + DO 140, K = I + 1, M + TEMP = TEMP + CONJG( A( K, I ) )*B( K, J ) + 140 CONTINUE + END IF + B( I, J ) = ALPHA*TEMP + 150 CONTINUE + 160 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*A. +* + IF( UPPER )THEN + DO 200, J = N, 1, -1 + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 170, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 170 CONTINUE + DO 190, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 180, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 180 CONTINUE + END IF + 190 CONTINUE + 200 CONTINUE + ELSE + DO 240, J = 1, N + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 210, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 210 CONTINUE + DO 230, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 220, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 220 CONTINUE + END IF + 230 CONTINUE + 240 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A' or B := alpha*B*conjg( A' ). +* + IF( UPPER )THEN + DO 280, K = 1, N + DO 260, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = ALPHA*A( J, K ) + ELSE + TEMP = ALPHA*CONJG( A( J, K ) ) + END IF + DO 250, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 250 CONTINUE + END IF + 260 CONTINUE + TEMP = ALPHA + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = TEMP*A( K, K ) + ELSE + TEMP = TEMP*CONJG( A( K, K ) ) + END IF + END IF + IF( TEMP.NE.ONE )THEN + DO 270, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 270 CONTINUE + END IF + 280 CONTINUE + ELSE + DO 320, K = N, 1, -1 + DO 300, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = ALPHA*A( J, K ) + ELSE + TEMP = ALPHA*CONJG( A( J, K ) ) + END IF + DO 290, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 290 CONTINUE + END IF + 300 CONTINUE + TEMP = ALPHA + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = TEMP*A( K, K ) + ELSE + TEMP = TEMP*CONJG( A( K, K ) ) + END IF + END IF + IF( TEMP.NE.ONE )THEN + DO 310, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 310 CONTINUE + END IF + 320 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of CTRMM . +* + END diff --git a/dep/blas/ctrsm.f b/dep/blas/ctrsm.f new file mode 100644 index 00000000..f9b74dcc --- /dev/null +++ b/dep/blas/ctrsm.f @@ -0,0 +1,414 @@ + SUBROUTINE CTRSM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + COMPLEX ALPHA +* .. Array Arguments .. + COMPLEX A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* CTRSM solves one of the matrix equations +* +* op( A )*X = alpha*B, or X*op( A ) = alpha*B, +* +* where alpha is a scalar, X and B are m by n matrices, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A' or op( A ) = conjg( A' ). +* +* The matrix X is overwritten on B. +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) appears on the left +* or right of X as follows: +* +* SIDE = 'L' or 'l' op( A )*X = alpha*B. +* +* SIDE = 'R' or 'r' X*op( A ) = alpha*B. +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = conjg( A' ). +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX . +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - COMPLEX array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the right-hand side matrix B, and on exit is +* overwritten by the solution matrix X. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOCONJ, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + COMPLEX TEMP +* .. Parameters .. + COMPLEX ONE + PARAMETER ( ONE = ( 1.0E+0, 0.0E+0 ) ) + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOCONJ = LSAME( TRANSA, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CTRSM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*inv( A )*B. +* + IF( UPPER )THEN + DO 60, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 30, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 30 CONTINUE + END IF + DO 50, K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 40, I = 1, K - 1 + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 40 CONTINUE + END IF + 50 CONTINUE + 60 CONTINUE + ELSE + DO 100, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 70, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 70 CONTINUE + END IF + DO 90 K = 1, M + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 80, I = K + 1, M + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 80 CONTINUE + END IF + 90 CONTINUE + 100 CONTINUE + END IF + ELSE +* +* Form B := alpha*inv( A' )*B +* or B := alpha*inv( conjg( A' ) )*B. +* + IF( UPPER )THEN + DO 140, J = 1, N + DO 130, I = 1, M + TEMP = ALPHA*B( I, J ) + IF( NOCONJ )THEN + DO 110, K = 1, I - 1 + TEMP = TEMP - A( K, I )*B( K, J ) + 110 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + ELSE + DO 120, K = 1, I - 1 + TEMP = TEMP - CONJG( A( K, I ) )*B( K, J ) + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( I, I ) ) + END IF + B( I, J ) = TEMP + 130 CONTINUE + 140 CONTINUE + ELSE + DO 180, J = 1, N + DO 170, I = M, 1, -1 + TEMP = ALPHA*B( I, J ) + IF( NOCONJ )THEN + DO 150, K = I + 1, M + TEMP = TEMP - A( K, I )*B( K, J ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + ELSE + DO 160, K = I + 1, M + TEMP = TEMP - CONJG( A( K, I ) )*B( K, J ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( I, I ) ) + END IF + B( I, J ) = TEMP + 170 CONTINUE + 180 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*inv( A ). +* + IF( UPPER )THEN + DO 230, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 190, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 190 CONTINUE + END IF + DO 210, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + DO 200, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 200 CONTINUE + END IF + 210 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 220, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 220 CONTINUE + END IF + 230 CONTINUE + ELSE + DO 280, J = N, 1, -1 + IF( ALPHA.NE.ONE )THEN + DO 240, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 240 CONTINUE + END IF + DO 260, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + DO 250, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 250 CONTINUE + END IF + 260 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 270, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 270 CONTINUE + END IF + 280 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*inv( A' ) +* or B := alpha*B*inv( conjg( A' ) ). +* + IF( UPPER )THEN + DO 330, K = N, 1, -1 + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = ONE/A( K, K ) + ELSE + TEMP = ONE/CONJG( A( K, K ) ) + END IF + DO 290, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 290 CONTINUE + END IF + DO 310, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = A( J, K ) + ELSE + TEMP = CONJG( A( J, K ) ) + END IF + DO 300, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 300 CONTINUE + END IF + 310 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 320, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 320 CONTINUE + END IF + 330 CONTINUE + ELSE + DO 380, K = 1, N + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = ONE/A( K, K ) + ELSE + TEMP = ONE/CONJG( A( K, K ) ) + END IF + DO 340, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 340 CONTINUE + END IF + DO 360, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = A( J, K ) + ELSE + TEMP = CONJG( A( J, K ) ) + END IF + DO 350, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 350 CONTINUE + END IF + 360 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 370, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 370 CONTINUE + END IF + 380 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of CTRSM . +* + END diff --git a/dep/blas/ctrsv.f b/dep/blas/ctrsv.f new file mode 100644 index 00000000..a14b1abf --- /dev/null +++ b/dep/blas/ctrsv.f @@ -0,0 +1,324 @@ + SUBROUTINE CTRSV ( UPLO, TRANS, DIAG, N, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + COMPLEX A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* CTRSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, or conjg( A' )*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular matrix. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' conjg( A' )*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* A - COMPLEX array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* X - COMPLEX array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX ZERO + PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ) ) +* .. Local Scalars .. + COMPLEX TEMP + INTEGER I, INFO, IX, J, JX, KX + LOGICAL NOCONJ, NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC CONJG, MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 6 + ELSE IF( INCX.EQ.0 )THEN + INFO = 8 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'CTRSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( J ) = X( J )/A( J, J ) + TEMP = X( J ) + DO 10, I = J - 1, 1, -1 + X( I ) = X( I ) - TEMP*A( I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + JX = KX + ( N - 1 )*INCX + DO 40, J = N, 1, -1 + IF( X( JX ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( J, J ) + TEMP = X( JX ) + IX = JX + DO 30, I = J - 1, 1, -1 + IX = IX - INCX + X( IX ) = X( IX ) - TEMP*A( I, J ) + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( J ) = X( J )/A( J, J ) + TEMP = X( J ) + DO 50, I = J + 1, N + X( I ) = X( I ) - TEMP*A( I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( J, J ) + TEMP = X( JX ) + IX = JX + DO 70, I = J + 1, N + IX = IX + INCX + X( IX ) = X( IX ) - TEMP*A( I, J ) + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A' )*x or x := inv( conjg( A' ) )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = X( J ) + IF( NOCONJ )THEN + DO 90, I = 1, J - 1 + TEMP = TEMP - A( I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 100, I = 1, J - 1 + TEMP = TEMP - CONJG( A( I, J ) )*X( I ) + 100 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( J, J ) ) + END IF + X( J ) = TEMP + 110 CONTINUE + ELSE + JX = KX + DO 140, J = 1, N + IX = KX + TEMP = X( JX ) + IF( NOCONJ )THEN + DO 120, I = 1, J - 1 + TEMP = TEMP - A( I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 130, I = 1, J - 1 + TEMP = TEMP - CONJG( A( I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( J, J ) ) + END IF + X( JX ) = TEMP + JX = JX + INCX + 140 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 170, J = N, 1, -1 + TEMP = X( J ) + IF( NOCONJ )THEN + DO 150, I = N, J + 1, -1 + TEMP = TEMP - A( I, J )*X( I ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 160, I = N, J + 1, -1 + TEMP = TEMP - CONJG( A( I, J ) )*X( I ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( J, J ) ) + END IF + X( J ) = TEMP + 170 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 200, J = N, 1, -1 + IX = KX + TEMP = X( JX ) + IF( NOCONJ )THEN + DO 180, I = N, J + 1, -1 + TEMP = TEMP - A( I, J )*X( IX ) + IX = IX - INCX + 180 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 190, I = N, J + 1, -1 + TEMP = TEMP - CONJG( A( I, J ) )*X( IX ) + IX = IX - INCX + 190 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/CONJG( A( J, J ) ) + END IF + X( JX ) = TEMP + JX = JX - INCX + 200 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of CTRSV . +* + END diff --git a/dep/blas/d1mach.f b/dep/blas/d1mach.f new file mode 100644 index 00000000..232582a7 --- /dev/null +++ b/dep/blas/d1mach.f @@ -0,0 +1,209 @@ + DOUBLE PRECISION FUNCTION D1MACH(I) + INTEGER I +C +C DOUBLE-PRECISION MACHINE CONSTANTS +C D1MACH( 1) = B**(EMIN-1), THE SMALLEST POSITIVE MAGNITUDE. +C D1MACH( 2) = B**EMAX*(1 - B**(-T)), THE LARGEST MAGNITUDE. +C D1MACH( 3) = B**(-T), THE SMALLEST RELATIVE SPACING. +C D1MACH( 4) = B**(1-T), THE LARGEST RELATIVE SPACING. +C D1MACH( 5) = LOG10(B) +C + INTEGER SMALL(2) + INTEGER LARGE(2) + INTEGER RIGHT(2) + INTEGER DIVER(2) + INTEGER LOG10(2) + INTEGER SC, CRAY1(38), J + COMMON /D9MACH/ CRAY1 + SAVE SMALL, LARGE, RIGHT, DIVER, LOG10, SC + DOUBLE PRECISION DMACH(5) + EQUIVALENCE (DMACH(1),SMALL(1)) + EQUIVALENCE (DMACH(2),LARGE(1)) + EQUIVALENCE (DMACH(3),RIGHT(1)) + EQUIVALENCE (DMACH(4),DIVER(1)) + EQUIVALENCE (DMACH(5),LOG10(1)) +C THIS VERSION ADAPTS AUTOMATICALLY TO MOST CURRENT MACHINES. +C R1MACH CAN HANDLE AUTO-DOUBLE COMPILING, BUT THIS VERSION OF +C D1MACH DOES NOT, BECAUSE WE DO NOT HAVE QUAD CONSTANTS FOR +C MANY MACHINES YET. +C TO COMPILE ON OLDER MACHINES, ADD A C IN COLUMN 1 +C ON THE NEXT LINE + DATA SC/0/ +C AND REMOVE THE C FROM COLUMN 1 IN ONE OF THE SECTIONS BELOW. +C CONSTANTS FOR EVEN OLDER MACHINES CAN BE OBTAINED BY +C mail netlib@research.bell-labs.com +C send old1mach from blas +C PLEASE SEND CORRECTIONS TO dmg OR ehg@bell-labs.com. +C +C MACHINE CONSTANTS FOR THE HONEYWELL DPS 8/70 SERIES. +C DATA SMALL(1),SMALL(2) / O402400000000, O000000000000 / +C DATA LARGE(1),LARGE(2) / O376777777777, O777777777777 / +C DATA RIGHT(1),RIGHT(2) / O604400000000, O000000000000 / +C DATA DIVER(1),DIVER(2) / O606400000000, O000000000000 / +C DATA LOG10(1),LOG10(2) / O776464202324, O117571775714 /, SC/987/ +C +C MACHINE CONSTANTS FOR PDP-11 FORTRANS SUPPORTING +C 32-BIT INTEGERS. +C DATA SMALL(1),SMALL(2) / 8388608, 0 / +C DATA LARGE(1),LARGE(2) / 2147483647, -1 / +C DATA RIGHT(1),RIGHT(2) / 612368384, 0 / +C DATA DIVER(1),DIVER(2) / 620756992, 0 / +C DATA LOG10(1),LOG10(2) / 1067065498, -2063872008 /, SC/987/ +C +C MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES. +C DATA SMALL(1),SMALL(2) / O000040000000, O000000000000 / +C DATA LARGE(1),LARGE(2) / O377777777777, O777777777777 / +C DATA RIGHT(1),RIGHT(2) / O170540000000, O000000000000 / +C DATA DIVER(1),DIVER(2) / O170640000000, O000000000000 / +C DATA LOG10(1),LOG10(2) / O177746420232, O411757177572 /, SC/987/ +C +C ON FIRST CALL, IF NO DATA UNCOMMENTED, TEST MACHINE TYPES. + IF (SC .NE. 987) THEN + DMACH(1) = 1.D13 + IF ( SMALL(1) .EQ. 1117925532 + * .AND. SMALL(2) .EQ. -448790528) THEN +* *** IEEE BIG ENDIAN *** + SMALL(1) = 1048576 + SMALL(2) = 0 + LARGE(1) = 2146435071 + LARGE(2) = -1 + RIGHT(1) = 1017118720 + RIGHT(2) = 0 + DIVER(1) = 1018167296 + DIVER(2) = 0 + LOG10(1) = 1070810131 + LOG10(2) = 1352628735 + ELSE IF ( SMALL(2) .EQ. 1117925532 + * .AND. SMALL(1) .EQ. -448790528) THEN +* *** IEEE LITTLE ENDIAN *** + SMALL(2) = 1048576 + SMALL(1) = 0 + LARGE(2) = 2146435071 + LARGE(1) = -1 + RIGHT(2) = 1017118720 + RIGHT(1) = 0 + DIVER(2) = 1018167296 + DIVER(1) = 0 + LOG10(2) = 1070810131 + LOG10(1) = 1352628735 + ELSE IF ( SMALL(1) .EQ. -2065213935 + * .AND. SMALL(2) .EQ. 10752) THEN +* *** VAX WITH D_FLOATING *** + SMALL(1) = 128 + SMALL(2) = 0 + LARGE(1) = -32769 + LARGE(2) = -1 + RIGHT(1) = 9344 + RIGHT(2) = 0 + DIVER(1) = 9472 + DIVER(2) = 0 + LOG10(1) = 546979738 + LOG10(2) = -805796613 + ELSE IF ( SMALL(1) .EQ. 1267827943 + * .AND. SMALL(2) .EQ. 704643072) THEN +* *** IBM MAINFRAME *** + SMALL(1) = 1048576 + SMALL(2) = 0 + LARGE(1) = 2147483647 + LARGE(2) = -1 + RIGHT(1) = 856686592 + RIGHT(2) = 0 + DIVER(1) = 873463808 + DIVER(2) = 0 + LOG10(1) = 1091781651 + LOG10(2) = 1352628735 + ELSE IF ( SMALL(1) .EQ. 1120022684 + * .AND. SMALL(2) .EQ. -448790528) THEN +* *** CONVEX C-1 *** + SMALL(1) = 1048576 + SMALL(2) = 0 + LARGE(1) = 2147483647 + LARGE(2) = -1 + RIGHT(1) = 1019215872 + RIGHT(2) = 0 + DIVER(1) = 1020264448 + DIVER(2) = 0 + LOG10(1) = 1072907283 + LOG10(2) = 1352628735 + ELSE IF ( SMALL(1) .EQ. 815547074 + * .AND. SMALL(2) .EQ. 58688) THEN +* *** VAX G-FLOATING *** + SMALL(1) = 16 + SMALL(2) = 0 + LARGE(1) = -32769 + LARGE(2) = -1 + RIGHT(1) = 15552 + RIGHT(2) = 0 + DIVER(1) = 15568 + DIVER(2) = 0 + LOG10(1) = 1142112243 + LOG10(2) = 2046775455 + ELSE + DMACH(2) = 1.D27 + 1 + DMACH(3) = 1.D27 + LARGE(2) = LARGE(2) - RIGHT(2) + IF (LARGE(2) .EQ. 64 .AND. SMALL(2) .EQ. 0) THEN + CRAY1(1) = 67291416 + DO 10 J = 1, 20 + CRAY1(J+1) = CRAY1(J) + CRAY1(J) + 10 CONTINUE + CRAY1(22) = CRAY1(21) + 321322 + DO 20 J = 22, 37 + CRAY1(J+1) = CRAY1(J) + CRAY1(J) + 20 CONTINUE + IF (CRAY1(38) .EQ. SMALL(1)) THEN +* *** CRAY *** + CALL I1MCRY(SMALL(1), J, 8285, 8388608, 0) + SMALL(2) = 0 + CALL I1MCRY(LARGE(1), J, 24574, 16777215, 16777215) + CALL I1MCRY(LARGE(2), J, 0, 16777215, 16777214) + CALL I1MCRY(RIGHT(1), J, 16291, 8388608, 0) + RIGHT(2) = 0 + CALL I1MCRY(DIVER(1), J, 16292, 8388608, 0) + DIVER(2) = 0 + CALL I1MCRY(LOG10(1), J, 16383, 10100890, 8715215) + CALL I1MCRY(LOG10(2), J, 0, 16226447, 9001388) + ELSE + WRITE(*,9000) + STOP 779 + END IF + ELSE + WRITE(*,9000) + STOP 779 + END IF + END IF + SC = 987 + END IF +* SANITY CHECK + IF (DMACH(4) .GE. 1.0D0) STOP 778 + IF (I .LT. 1 .OR. I .GT. 5) THEN + WRITE(*,*) 'D1MACH(I): I =',I,' is out of bounds.' + STOP + END IF + D1MACH = DMACH(I) + RETURN + 9000 FORMAT(/' Adjust D1MACH by uncommenting data statements'/ + *' appropriate for your machine.') +* /* Standard C source for D1MACH -- remove the * in column 1 */ +*#include +*#include +*#include +*double d1mach_(long *i) +*{ +* switch(*i){ +* case 1: return DBL_MIN; +* case 2: return DBL_MAX; +* case 3: return DBL_EPSILON/FLT_RADIX; +* case 4: return DBL_EPSILON; +* case 5: return log10((double)FLT_RADIX); +* } +* fprintf(stderr, "invalid argument: d1mach(%ld)\n", *i); +* exit(1); return 0; /* some compilers demand return values */ +*} + END + SUBROUTINE I1MCRY(A, A1, B, C, D) +**** SPECIAL COMPUTATION FOR OLD CRAY MACHINES **** + INTEGER A, A1, B, C, D + A1 = 16777216*B + C + A = 16777216*A1 + D + END diff --git a/dep/blas/dasum.f b/dep/blas/dasum.f new file mode 100644 index 00000000..c270060c --- /dev/null +++ b/dep/blas/dasum.f @@ -0,0 +1,45 @@ + double precision function dasum(n,dx,incx) +c +c takes the sum of the absolute values. +c uses unrolled loops for increment equal to one. +c jack dongarra, linpack, 3/11/78. +c modified to correct problem with negative increment, 8/21/90. +c + double precision dx(1),dtemp + integer i,incx,ix,m,mp1,n +c + dasum = 0.0d0 + dtemp = 0.0d0 + if(n.le.0)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + do 10 i = 1,n + dtemp = dtemp + dabs(dx(ix)) + ix = ix + incx + 10 continue + dasum = dtemp + return +c +c code for increment equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,6) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + dtemp = dtemp + dabs(dx(i)) + 30 continue + if( n .lt. 6 ) go to 60 + 40 mp1 = m + 1 + do 50 i = mp1,n,6 + dtemp = dtemp + dabs(dx(i)) + dabs(dx(i + 1)) + dabs(dx(i + 2)) + * + dabs(dx(i + 3)) + dabs(dx(i + 4)) + dabs(dx(i + 5)) + 50 continue + 60 dasum = dtemp + return + end diff --git a/dep/blas/daxpy.f b/dep/blas/daxpy.f new file mode 100644 index 00000000..55bfe6b1 --- /dev/null +++ b/dep/blas/daxpy.f @@ -0,0 +1,47 @@ + subroutine daxpy(n,da,dx,incx,dy,incy) +c +c constant times a vector plus a vector. +c uses unrolled loops for increments equal to one. +c jack dongarra, linpack, 3/11/78. +c + double precision dx(1),dy(1),da + integer i,incx,incy,ix,iy,m,mp1,n +c + if(n.le.0)return + if (da .eq. 0.0d0) return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + dy(iy) = dy(iy) + da*dx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,4) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + dy(i) = dy(i) + da*dx(i) + 30 continue + if( n .lt. 4 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,4 + dy(i) = dy(i) + da*dx(i) + dy(i + 1) = dy(i + 1) + da*dx(i + 1) + dy(i + 2) = dy(i + 2) + da*dx(i + 2) + dy(i + 3) = dy(i + 3) + da*dx(i + 3) + 50 continue + return + end diff --git a/dep/blas/dcopy.f b/dep/blas/dcopy.f new file mode 100644 index 00000000..c8731701 --- /dev/null +++ b/dep/blas/dcopy.f @@ -0,0 +1,49 @@ + subroutine dcopy(n,dx,incx,dy,incy) +c +c copies a vector, x, to a vector, y. +c uses unrolled loops for increments equal to one. +c jack dongarra, linpack, 3/11/78. +c + double precision dx(1),dy(1) + integer i,incx,incy,ix,iy,m,mp1,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + dy(iy) = dx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,7) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + dy(i) = dx(i) + 30 continue + if( n .lt. 7 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,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) + 50 continue + return + end diff --git a/dep/blas/ddot.f b/dep/blas/ddot.f new file mode 100644 index 00000000..625dbcb8 --- /dev/null +++ b/dep/blas/ddot.f @@ -0,0 +1,48 @@ + double precision function ddot(n,dx,incx,dy,incy) +c +c forms the dot product of two vectors. +c uses unrolled loops for increments equal to one. +c jack dongarra, linpack, 3/11/78. +c + double precision dx(1),dy(1),dtemp + integer i,incx,incy,ix,iy,m,mp1,n +c + ddot = 0.0d0 + dtemp = 0.0d0 + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + dtemp = dtemp + dx(ix)*dy(iy) + ix = ix + incx + iy = iy + incy + 10 continue + ddot = dtemp + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,5) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + dtemp = dtemp + dx(i)*dy(i) + 30 continue + if( n .lt. 5 ) go to 60 + 40 mp1 = m + 1 + do 50 i = mp1,n,5 + dtemp = 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) + 50 continue + 60 ddot = dtemp + return + end diff --git a/dep/blas/depblas.h b/dep/blas/depblas.h new file mode 100644 index 00000000..c06edae7 --- /dev/null +++ b/dep/blas/depblas.h @@ -0,0 +1,39 @@ +#ifndef BLAS_H +#define BLAS_H + +#include "ftndefs.h" + +// Computes the dot product for two vectors +// see ddot.f for details +extern FTN_FUNC double FTN_NAME(ddot)(int*, double*, int*, double*, int*); + +// Copies the contents of a double* array into another double* array +// see dcopy.f for details +extern FTN_FUNC void FTN_NAME(dcopy)(int*, double*, int *, double*, int*); + +// Scales a double* array by a constant +// see dscal.f for details +extern FTN_FUNC void FTN_NAME(dscal)(int*, double*, double*, int*); + +// Computes constant times a vector plus a vector +// see daxpy.f for details +extern FTN_FUNC void FTN_NAME(daxpy)(int*, double*, double*, int*, double*, int*); + +// Computes the Euclidean norm of a vector +// see dnrm2.f for details +extern FTN_FUNC double FTN_NAME(dnrm2)(int*, double*, int*); + +// Symmetric matrix-Vector product +// see dsymv.f for details about the arguments +extern FTN_FUNC void FTN_NAME(dsymv)(char*, int*, double*, double*, int*, double*, int*, double*, double*, int*); + +// Performs linear matrix-vector operations +// see dgemv.f for details +extern FTN_FUNC void FTN_NAME(dgemv)(char*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int*); + +// Performs matrix-matrix operations +// see dgemm.f for details +extern FTN_FUNC void FTN_NAME(dgemm)(char*, char*, int*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int*); + + +#endif /* BLAS_H */ diff --git a/dep/blas/dgbmv.f b/dep/blas/dgbmv.f new file mode 100644 index 00000000..e9c8f76f --- /dev/null +++ b/dep/blas/dgbmv.f @@ -0,0 +1,300 @@ + SUBROUTINE DGBMV ( TRANS, M, N, KL, KU, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA, BETA + INTEGER INCX, INCY, KL, KU, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* DGBMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n band matrix, with kl sub-diagonals and ku super-diagonals. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* KL - INTEGER. +* On entry, KL specifies the number of sub-diagonals of the +* matrix A. KL must satisfy 0 .le. KL. +* Unchanged on exit. +* +* KU - INTEGER. +* On entry, KU specifies the number of super-diagonals of the +* matrix A. KU must satisfy 0 .le. KU. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry, the leading ( kl + ku + 1 ) by n part of the +* array A must contain the matrix of coefficients, supplied +* column by column, with the leading diagonal of the matrix in +* row ( ku + 1 ) of the array, the first super-diagonal +* starting at position 2 in row ku, the first sub-diagonal +* starting at position 1 in row ( ku + 2 ), and so on. +* Elements in the array A that do not correspond to elements +* in the band matrix (such as the top left ku by ku triangle) +* are not referenced. +* The following program segment will transfer a band matrix +* from conventional full matrix storage to band storage: +* +* DO 20, J = 1, N +* K = KU + 1 - J +* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) +* A( K + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( kl + ku + 1 ). +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - DOUBLE PRECISION. +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - DOUBLE PRECISION array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry, the incremented array Y must contain the +* vector y. On exit, Y is overwritten by the updated vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, K, KUP1, KX, KY, + $ LENX, LENY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( KL.LT.0 )THEN + INFO = 4 + ELSE IF( KU.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( KL + KU + 1 ) )THEN + INFO = 8 + ELSE IF( INCX.EQ.0 )THEN + INFO = 10 + ELSE IF( INCY.EQ.0 )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DGBMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the band part of A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + KUP1 = KU + 1 + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + K = KUP1 - J + DO 50, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( I ) = Y( I ) + TEMP*A( K + I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + K = KUP1 - J + DO 70, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( IY ) = Y( IY ) + TEMP*A( K + I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + IF( J.GT.KU ) + $ KY = KY + INCY + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 100, J = 1, N + TEMP = ZERO + K = KUP1 - J + DO 90, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( I ) + 90 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 100 CONTINUE + ELSE + DO 120, J = 1, N + TEMP = ZERO + IX = KX + K = KUP1 - J + DO 110, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( IX ) + IX = IX + INCX + 110 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + IF( J.GT.KU ) + $ KX = KX + INCX + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGBMV . +* + END diff --git a/dep/blas/dgemm.f b/dep/blas/dgemm.f new file mode 100644 index 00000000..baabe4c5 --- /dev/null +++ b/dep/blas/dgemm.f @@ -0,0 +1,313 @@ + SUBROUTINE DGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, + $ BETA, C, LDC ) +* .. Scalar Arguments .. + CHARACTER*1 TRANSA, TRANSB + INTEGER M, N, K, LDA, LDB, LDC + DOUBLE PRECISION ALPHA, BETA +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * ) +* .. +* +* Purpose +* ======= +* +* DGEMM performs one of the matrix-matrix operations +* +* C := alpha*op( A )*op( B ) + beta*C, +* +* where op( X ) is one of +* +* op( X ) = X or op( X ) = X', +* +* alpha and beta are scalars, and A, B and C are matrices, with op( A ) +* an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. +* +* Parameters +* ========== +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n', op( A ) = A. +* +* TRANSA = 'T' or 't', op( A ) = A'. +* +* TRANSA = 'C' or 'c', op( A ) = A'. +* +* Unchanged on exit. +* +* TRANSB - CHARACTER*1. +* On entry, TRANSB specifies the form of op( B ) to be used in +* the matrix multiplication as follows: +* +* TRANSB = 'N' or 'n', op( B ) = B. +* +* TRANSB = 'T' or 't', op( B ) = B'. +* +* TRANSB = 'C' or 'c', op( B ) = B'. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix +* op( A ) and of the matrix C. M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix +* op( B ) and the number of columns of the matrix C. N must be +* at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry, K specifies the number of columns of the matrix +* op( A ) and the number of rows of the matrix op( B ). K must +* be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is +* k when TRANSA = 'N' or 'n', and is m otherwise. +* Before entry with TRANSA = 'N' or 'n', the leading m by k +* part of the array A must contain the matrix A, otherwise +* the leading k by m part of the array A must contain the +* matrix A. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When TRANSA = 'N' or 'n' then +* LDA must be at least max( 1, m ), otherwise LDA must be at +* least max( 1, k ). +* Unchanged on exit. +* +* B - DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is +* n when TRANSB = 'N' or 'n', and is k otherwise. +* Before entry with TRANSB = 'N' or 'n', the leading k by n +* part of the array B must contain the matrix B, otherwise +* the leading n by k part of the array B must contain the +* matrix B. +* Unchanged on exit. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. When TRANSB = 'N' or 'n' then +* LDB must be at least max( 1, k ), otherwise LDB must be at +* least max( 1, n ). +* Unchanged on exit. +* +* BETA - DOUBLE PRECISION. +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then C need not be set on input. +* Unchanged on exit. +* +* C - DOUBLE PRECISION array of DIMENSION ( LDC, n ). +* Before entry, the leading m by n part of the array C must +* contain the matrix C, except when beta is zero, in which +* case C need not be set on entry. +* On exit, the array C is overwritten by the m by n matrix +* ( alpha*op( A )*op( B ) + beta*C ). +* +* LDC - INTEGER. +* On entry, LDC specifies the first dimension of C as declared +* in the calling (sub) program. LDC must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. Local Scalars .. + LOGICAL NOTA, NOTB + INTEGER I, INFO, J, L, NCOLA, NROWA, NROWB + DOUBLE PRECISION TEMP +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Executable Statements .. +* +* Set NOTA and NOTB as true if A and B respectively are not +* transposed and set NROWA, NCOLA and NROWB as the number of rows +* and columns of A and the number of rows of B respectively. +* + NOTA = LSAME( TRANSA, 'N' ) + NOTB = LSAME( TRANSB, 'N' ) + IF( NOTA )THEN + NROWA = M + NCOLA = K + ELSE + NROWA = K + NCOLA = M + END IF + IF( NOTB )THEN + NROWB = K + ELSE + NROWB = N + END IF +* +* Test the input parameters. +* + INFO = 0 + IF( ( .NOT.NOTA ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.NOTB ).AND. + $ ( .NOT.LSAME( TRANSB, 'C' ) ).AND. + $ ( .NOT.LSAME( TRANSB, 'T' ) ) )THEN + INFO = 2 + ELSE IF( M .LT.0 )THEN + INFO = 3 + ELSE IF( N .LT.0 )THEN + INFO = 4 + ELSE IF( K .LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 8 + ELSE IF( LDB.LT.MAX( 1, NROWB ) )THEN + INFO = 10 + ELSE IF( LDC.LT.MAX( 1, M ) )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DGEMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ( ALPHA.EQ.ZERO ).OR.( K.EQ.0 ) ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* And if alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + IF( BETA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + C( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40, J = 1, N + DO 30, I = 1, M + C( I, J ) = BETA*C( I, J ) + 30 CONTINUE + 40 CONTINUE + END IF + RETURN + END IF +* +* Start the operations. +* + IF( NOTB )THEN + IF( NOTA )THEN +* +* Form C := alpha*A*B + beta*C. +* + DO 90, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 50, I = 1, M + C( I, J ) = ZERO + 50 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 60, I = 1, M + C( I, J ) = BETA*C( I, J ) + 60 CONTINUE + END IF + DO 80, L = 1, K + IF( B( L, J ).NE.ZERO )THEN + TEMP = ALPHA*B( L, J ) + DO 70, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 70 CONTINUE + END IF + 80 CONTINUE + 90 CONTINUE + ELSE +* +* Form C := alpha*A'*B + beta*C +* + DO 120, J = 1, N + DO 110, I = 1, M + TEMP = ZERO + DO 100, L = 1, K + TEMP = TEMP + A( L, I )*B( L, J ) + 100 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 110 CONTINUE + 120 CONTINUE + END IF + ELSE + IF( NOTA )THEN +* +* Form C := alpha*A*B' + beta*C +* + DO 170, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 130, I = 1, M + C( I, J ) = ZERO + 130 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 140, I = 1, M + C( I, J ) = BETA*C( I, J ) + 140 CONTINUE + END IF + DO 160, L = 1, K + IF( B( J, L ).NE.ZERO )THEN + TEMP = ALPHA*B( J, L ) + DO 150, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 150 CONTINUE + END IF + 160 CONTINUE + 170 CONTINUE + ELSE +* +* Form C := alpha*A'*B' + beta*C +* + DO 200, J = 1, N + DO 190, I = 1, M + TEMP = ZERO + DO 180, L = 1, K + TEMP = TEMP + A( L, I )*B( J, L ) + 180 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 190 CONTINUE + 200 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEMM . +* + END diff --git a/dep/blas/dgemv.f b/dep/blas/dgemv.f new file mode 100644 index 00000000..8ef80b3a --- /dev/null +++ b/dep/blas/dgemv.f @@ -0,0 +1,261 @@ + SUBROUTINE DGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA, BETA + INTEGER INCX, INCY, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* DGEMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n matrix. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - DOUBLE PRECISION. +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - DOUBLE PRECISION array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry with BETA non-zero, the incremented array Y +* must contain the vector y. On exit, Y is overwritten by the +* updated vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY, LENX, LENY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 6 + ELSE IF( INCX.EQ.0 )THEN + INFO = 8 + ELSE IF( INCY.EQ.0 )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DGEMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + DO 50, I = 1, M + Y( I ) = Y( I ) + TEMP*A( I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + DO 70, I = 1, M + Y( IY ) = Y( IY ) + TEMP*A( I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 100, J = 1, N + TEMP = ZERO + DO 90, I = 1, M + TEMP = TEMP + A( I, J )*X( I ) + 90 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 100 CONTINUE + ELSE + DO 120, J = 1, N + TEMP = ZERO + IX = KX + DO 110, I = 1, M + TEMP = TEMP + A( I, J )*X( IX ) + IX = IX + INCX + 110 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEMV . +* + END diff --git a/dep/blas/dger.f b/dep/blas/dger.f new file mode 100644 index 00000000..d316000a --- /dev/null +++ b/dep/blas/dger.f @@ -0,0 +1,157 @@ + SUBROUTINE DGER ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA + INTEGER INCX, INCY, LDA, M, N +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* DGER performs the rank 1 operation +* +* A := alpha*x*y' + A, +* +* where alpha is a scalar, x is an m element vector, y is an n element +* vector and A is an m by n matrix. +* +* Parameters +* ========== +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of dimension at least +* ( 1 + ( m - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the m +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. On exit, A is +* overwritten by the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I, INFO, IX, J, JY, KX +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( M.LT.0 )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DGER ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( INCY.GT.0 )THEN + JY = 1 + ELSE + JY = 1 - ( N - 1 )*INCY + END IF + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + DO 10, I = 1, M + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + END IF + JY = JY + INCY + 20 CONTINUE + ELSE + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( M - 1 )*INCX + END IF + DO 40, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + IX = KX + DO 30, I = 1, M + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + END IF + JY = JY + INCY + 40 CONTINUE + END IF +* + RETURN +* +* End of DGER . +* + END diff --git a/dep/blas/dnrm2.f b/dep/blas/dnrm2.f new file mode 100644 index 00000000..bed70cc1 --- /dev/null +++ b/dep/blas/dnrm2.f @@ -0,0 +1,130 @@ + double precision function dnrm2 ( n, dx, incx) + integer i, incx, ix, j, n, next + double precision dx(1), cutlo, cuthi, hitest, sum, xmax,zero,one + data zero, one /0.0d0, 1.0d0/ +c +c euclidean norm of the n-vector stored in dx() with storage +c increment incx . +c if n .le. 0 return with result = 0. +c if n .ge. 1 then incx must be .ge. 1 +c +c c.l.lawson, 1978 jan 08 +c modified to correct problem with negative increment, 8/21/90. +c +c four phase method using two built-in constants that are +c hopefully applicable to all machines. +c cutlo = maximum of dsqrt(u/eps) over all known machines. +c cuthi = minimum of dsqrt(v) over all known machines. +c where +c eps = smallest no. such that eps + 1. .gt. 1. +c u = smallest positive no. (underflow limit) +c v = largest no. (overflow limit) +c +c brief outline of algorithm.. +c +c phase 1 scans zero components. +c move to phase 2 when a component is nonzero and .le. cutlo +c move to phase 3 when a component is .gt. cutlo +c move to phase 4 when a component is .ge. cuthi/m +c where m = n for x() real and m = 2*n for complex. +c +c values for cutlo and cuthi.. +c from the environmental parameters listed in the imsl converter +c document the limiting values are as follows.. +c cutlo, s.p. u/eps = 2**(-102) for honeywell. close seconds are +c univac and dec at 2**(-103) +c thus cutlo = 2**(-51) = 4.44089e-16 +c cuthi, s.p. v = 2**127 for univac, honeywell, and dec. +c thus cuthi = 2**(63.5) = 1.30438e19 +c cutlo, d.p. u/eps = 2**(-67) for honeywell and dec. +c thus cutlo = 2**(-33.5) = 8.23181d-11 +c cuthi, d.p. same as s.p. cuthi = 1.30438d19 +c data cutlo, cuthi / 8.232d-11, 1.304d19 / +c data cutlo, cuthi / 4.441e-16, 1.304e19 / +c data cutlo, cuthi / 8.232d-11, 1.304d19 / +c.... from Ed Anderson + data cutlo / 0.1415686533102923D-145 / + data cuthi / 0.1340780792994260D+155 / +c + if(n .gt. 0) go to 10 + dnrm2 = zero + go to 300 +c + 10 assign 30 to next + sum = zero + i = 1 + if( incx .lt. 0 )i = (-n+1)*incx + 1 + ix = 1 +c begin main loop + 20 go to next,(30, 50, 70, 110) + 30 if( dabs(dx(i)) .gt. cutlo) go to 85 + assign 50 to next + xmax = zero +c +c phase 1. sum is zero +c + 50 if( dx(i) .eq. zero) go to 200 + if( dabs(dx(i)) .gt. cutlo) go to 85 +c +c prepare for phase 2. + assign 70 to next + go to 105 +c +c prepare for phase 4. +c + 100 continue + assign 110 to next + sum = (sum / dx(i)) / dx(i) + 105 xmax = dabs(dx(i)) + go to 115 +c +c phase 2. sum is small. +c scale to avoid destructive underflow. +c + 70 if( dabs(dx(i)) .gt. cutlo ) go to 75 +c +c common code for phases 2 and 4. +c in phase 4 sum is large. scale to avoid overflow. +c + 110 if( dabs(dx(i)) .le. xmax ) go to 115 + sum = one + sum * (xmax / dx(i))**2 + xmax = dabs(dx(i)) + go to 200 +c + 115 sum = sum + (dx(i)/xmax)**2 + go to 200 +c +c +c prepare for phase 3. +c + 75 sum = (sum * xmax) * xmax +c +c +c for real or d.p. set hitest = cuthi/n +c for complex set hitest = cuthi/(2*n) +c + 85 hitest = cuthi/float( n ) +c +c phase 3. sum is mid-range. no scaling. +c + do 95 j = ix,n + if(dabs(dx(i)) .ge. hitest) go to 100 + sum = sum + dx(i)**2 + i = i + incx + 95 continue + dnrm2 = dsqrt( sum ) + go to 300 +c + 200 continue + ix = ix + 1 + i = i + incx + if( ix .le. n ) go to 20 +c +c end of main loop. +c +c compute square root and adjust for scaling. +c + dnrm2 = xmax * dsqrt(sum) + 300 continue + return + end diff --git a/dep/blas/drot.f b/dep/blas/drot.f new file mode 100644 index 00000000..dd78ff8c --- /dev/null +++ b/dep/blas/drot.f @@ -0,0 +1,36 @@ + subroutine drot (n,dx,incx,dy,incy,c,s) +c +c applies a plane rotation. +c jack dongarra, linpack, 3/11/78. +c + double precision dx(1),dy(1),dtemp,c,s + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments not equal +c to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + dtemp = c*dx(ix) + s*dy(iy) + dy(iy) = c*dy(iy) - s*dx(ix) + dx(ix) = dtemp + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + dtemp = c*dx(i) + s*dy(i) + dy(i) = c*dy(i) - s*dx(i) + dx(i) = dtemp + 30 continue + return + end diff --git a/dep/blas/drotg.f b/dep/blas/drotg.f new file mode 100644 index 00000000..67838e2c --- /dev/null +++ b/dep/blas/drotg.f @@ -0,0 +1,27 @@ + subroutine drotg(da,db,c,s) +c +c construct givens plane rotation. +c jack dongarra, linpack, 3/11/78. +c + double precision da,db,c,s,roe,scale,r,z +c + roe = db + if( dabs(da) .gt. dabs(db) ) roe = da + scale = dabs(da) + dabs(db) + if( scale .ne. 0.0d0 ) go to 10 + c = 1.0d0 + s = 0.0d0 + r = 0.0d0 + z = 0.0d0 + go to 20 + 10 r = scale*dsqrt((da/scale)**2 + (db/scale)**2) + r = dsign(1.0d0,roe)*r + c = da/r + s = db/r + z = 1.0d0 + if( dabs(da) .gt. dabs(db) ) z = s + if( dabs(db) .ge. dabs(da) .and. c .ne. 0.0d0 ) z = 1.0d0/c + 20 da = r + db = z + return + end diff --git a/dep/blas/dscal.f b/dep/blas/dscal.f new file mode 100644 index 00000000..2133cb94 --- /dev/null +++ b/dep/blas/dscal.f @@ -0,0 +1,44 @@ + subroutine dscal(n,da,dx,incx) +c +c scales a vector by a constant. +c uses unrolled loops for increment equal to one. +c jack dongarra, linpack, 3/11/78. +c modified to correct problem with negative increment, 8/21/90. +c + double precision da,dx(1) + integer i,incx,ix,m,mp1,n +c + if(n.le.0)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + do 10 i = 1,n + dx(ix) = da*dx(ix) + ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,5) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + dx(i) = da*dx(i) + 30 continue + if( n .lt. 5 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,5 + dx(i) = da*dx(i) + dx(i + 1) = da*dx(i + 1) + dx(i + 2) = da*dx(i + 2) + dx(i + 3) = da*dx(i + 3) + dx(i + 4) = da*dx(i + 4) + 50 continue + return + end diff --git a/dep/blas/dswap.f b/dep/blas/dswap.f new file mode 100644 index 00000000..4a5e827d --- /dev/null +++ b/dep/blas/dswap.f @@ -0,0 +1,55 @@ + subroutine dswap (n,dx,incx,dy,incy) +c +c interchanges two vectors. +c uses unrolled loops for increments equal one. +c jack dongarra, linpack, 3/11/78. +c + double precision dx(1),dy(1),dtemp + integer i,incx,incy,ix,iy,m,mp1,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments not equal +c to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + dtemp = dx(ix) + dx(ix) = dy(iy) + dy(iy) = dtemp + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,3) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + dtemp = dx(i) + dx(i) = dy(i) + dy(i) = dtemp + 30 continue + if( n .lt. 3 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,3 + dtemp = dx(i) + dx(i) = dy(i) + dy(i) = dtemp + dtemp = dx(i + 1) + dx(i + 1) = dy(i + 1) + dy(i + 1) = dtemp + dtemp = dx(i + 2) + dx(i + 2) = dy(i + 2) + dy(i + 2) = dtemp + 50 continue + return + end diff --git a/dep/blas/dsymv.f b/dep/blas/dsymv.f new file mode 100644 index 00000000..7592d156 --- /dev/null +++ b/dep/blas/dsymv.f @@ -0,0 +1,262 @@ + SUBROUTINE DSYMV ( UPLO, N, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA, BETA + INTEGER INCX, INCY, LDA, N + CHARACTER*1 UPLO +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* DSYMV performs the matrix-vector operation +* +* y := alpha*A*x + beta*y, +* +* where alpha and beta are scalars, x and y are n element vectors and +* A is an n by n symmetric matrix. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array A is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of A +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of A +* is to be referenced. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular part of the symmetric matrix and the strictly +* lower triangular part of A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular part of the symmetric matrix and the strictly +* upper triangular part of A is not referenced. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - DOUBLE PRECISION. +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. On exit, Y is overwritten by the updated +* vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. Local Scalars .. + DOUBLE PRECISION TEMP1, TEMP2 + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO, 'U' ).AND. + $ .NOT.LSAME( UPLO, 'L' ) )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 5 + ELSE IF( INCX.EQ.0 )THEN + INFO = 7 + ELSE IF( INCY.EQ.0 )THEN + INFO = 10 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DSYMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( N.EQ.0 ).OR.( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* Set up the start points in X and Y. +* + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( N - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( N - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the triangular part +* of A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, N + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, N + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, N + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, N + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + IF( LSAME( UPLO, 'U' ) )THEN +* +* Form y when A is stored in upper triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 60, J = 1, N + TEMP1 = ALPHA*X( J ) + TEMP2 = ZERO + DO 50, I = 1, J - 1 + Y( I ) = Y( I ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( I ) + 50 CONTINUE + Y( J ) = Y( J ) + TEMP1*A( J, J ) + ALPHA*TEMP2 + 60 CONTINUE + ELSE + JX = KX + JY = KY + DO 80, J = 1, N + TEMP1 = ALPHA*X( JX ) + TEMP2 = ZERO + IX = KX + IY = KY + DO 70, I = 1, J - 1 + Y( IY ) = Y( IY ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( IX ) + IX = IX + INCX + IY = IY + INCY + 70 CONTINUE + Y( JY ) = Y( JY ) + TEMP1*A( J, J ) + ALPHA*TEMP2 + JX = JX + INCX + JY = JY + INCY + 80 CONTINUE + END IF + ELSE +* +* Form y when A is stored in lower triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 100, J = 1, N + TEMP1 = ALPHA*X( J ) + TEMP2 = ZERO + Y( J ) = Y( J ) + TEMP1*A( J, J ) + DO 90, I = J + 1, N + Y( I ) = Y( I ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( I ) + 90 CONTINUE + Y( J ) = Y( J ) + ALPHA*TEMP2 + 100 CONTINUE + ELSE + JX = KX + JY = KY + DO 120, J = 1, N + TEMP1 = ALPHA*X( JX ) + TEMP2 = ZERO + Y( JY ) = Y( JY ) + TEMP1*A( J, J ) + IX = JX + IY = JY + DO 110, I = J + 1, N + IX = IX + INCX + IY = IY + INCY + Y( IY ) = Y( IY ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( IX ) + 110 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP2 + JX = JX + INCX + JY = JY + INCY + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of DSYMV . +* + END diff --git a/dep/blas/dsyr2.f b/dep/blas/dsyr2.f new file mode 100644 index 00000000..918ad8a7 --- /dev/null +++ b/dep/blas/dsyr2.f @@ -0,0 +1,230 @@ + SUBROUTINE DSYR2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA + INTEGER INCX, INCY, LDA, N + CHARACTER*1 UPLO +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* DSYR2 performs the symmetric rank 2 operation +* +* A := alpha*x*y' + alpha*y*x' + A, +* +* where alpha is a scalar, x and y are n element vectors and A is an n +* by n symmetric matrix. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array A is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of A +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of A +* is to be referenced. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular part of the symmetric matrix and the strictly +* lower triangular part of A is not referenced. On exit, the +* upper triangular part of the array A is overwritten by the +* upper triangular part of the updated matrix. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular part of the symmetric matrix and the strictly +* upper triangular part of A is not referenced. On exit, the +* lower triangular part of the array A is overwritten by the +* lower triangular part of the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. Local Scalars .. + DOUBLE PRECISION TEMP1, TEMP2 + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO, 'U' ).AND. + $ .NOT.LSAME( UPLO, 'L' ) )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DSYR2 ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Set up the start points in X and Y if the increments are not both +* unity. +* + IF( ( INCX.NE.1 ).OR.( INCY.NE.1 ) )THEN + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( N - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( N - 1 )*INCY + END IF + JX = KX + JY = KY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the triangular part +* of A. +* + IF( LSAME( UPLO, 'U' ) )THEN +* +* Form A when A is stored in the upper triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 20, J = 1, N + IF( ( X( J ).NE.ZERO ).OR.( Y( J ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( J ) + TEMP2 = ALPHA*X( J ) + DO 10, I = 1, J + A( I, J ) = A( I, J ) + X( I )*TEMP1 + Y( I )*TEMP2 + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + DO 40, J = 1, N + IF( ( X( JX ).NE.ZERO ).OR.( Y( JY ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( JY ) + TEMP2 = ALPHA*X( JX ) + IX = KX + IY = KY + DO 30, I = 1, J + A( I, J ) = A( I, J ) + X( IX )*TEMP1 + $ + Y( IY )*TEMP2 + IX = IX + INCX + IY = IY + INCY + 30 CONTINUE + END IF + JX = JX + INCX + JY = JY + INCY + 40 CONTINUE + END IF + ELSE +* +* Form A when A is stored in the lower triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 60, J = 1, N + IF( ( X( J ).NE.ZERO ).OR.( Y( J ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( J ) + TEMP2 = ALPHA*X( J ) + DO 50, I = J, N + A( I, J ) = A( I, J ) + X( I )*TEMP1 + Y( I )*TEMP2 + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( ( X( JX ).NE.ZERO ).OR.( Y( JY ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( JY ) + TEMP2 = ALPHA*X( JX ) + IX = JX + IY = JY + DO 70, I = J, N + A( I, J ) = A( I, J ) + X( IX )*TEMP1 + $ + Y( IY )*TEMP2 + IX = IX + INCX + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + JY = JY + INCY + 80 CONTINUE + END IF + END IF +* + RETURN +* +* End of DSYR2 . +* + END diff --git a/dep/blas/dsyr2k.f b/dep/blas/dsyr2k.f new file mode 100644 index 00000000..0a7cc877 --- /dev/null +++ b/dep/blas/dsyr2k.f @@ -0,0 +1,326 @@ + SUBROUTINE DSYR2K(UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA,BETA + INTEGER K,LDA,LDB,LDC,N + CHARACTER TRANS,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) +* .. +* +* Purpose +* ======= +* +* DSYR2K performs one of the symmetric rank 2k operations +* +* C := alpha*A*B' + alpha*B*A' + beta*C, +* +* or +* +* C := alpha*A'*B + alpha*B'*A + beta*C, +* +* where alpha and beta are scalars, C is an n by n symmetric matrix +* and A and B are n by k matrices in the first case and k by n +* matrices in the second case. +* +* Arguments +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array C is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of C +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of C +* is to be referenced. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' C := alpha*A*B' + alpha*B*A' + +* beta*C. +* +* TRANS = 'T' or 't' C := alpha*A'*B + alpha*B'*A + +* beta*C. +* +* TRANS = 'C' or 'c' C := alpha*A'*B + alpha*B'*A + +* beta*C. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix C. N must be +* at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with TRANS = 'N' or 'n', K specifies the number +* of columns of the matrices A and B, and on entry with +* TRANS = 'T' or 't' or 'C' or 'c', K specifies the number +* of rows of the matrices A and B. K must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is +* k when TRANS = 'N' or 'n', and is n otherwise. +* Before entry with TRANS = 'N' or 'n', the leading n by k +* part of the array A must contain the matrix A, otherwise +* the leading k by n part of the array A must contain the +* matrix A. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When TRANS = 'N' or 'n' +* then LDA must be at least max( 1, n ), otherwise LDA must +* be at least max( 1, k ). +* Unchanged on exit. +* +* B - DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is +* k when TRANS = 'N' or 'n', and is n otherwise. +* Before entry with TRANS = 'N' or 'n', the leading n by k +* part of the array B must contain the matrix B, otherwise +* the leading k by n part of the array B must contain the +* matrix B. +* Unchanged on exit. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. When TRANS = 'N' or 'n' +* then LDB must be at least max( 1, n ), otherwise LDB must +* be at least max( 1, k ). +* Unchanged on exit. +* +* BETA - DOUBLE PRECISION. +* On entry, BETA specifies the scalar beta. +* Unchanged on exit. +* +* C - DOUBLE PRECISION array of DIMENSION ( LDC, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array C must contain the upper +* triangular part of the symmetric matrix and the strictly +* lower triangular part of C is not referenced. On exit, the +* upper triangular part of the array C is overwritten by the +* upper triangular part of the updated matrix. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array C must contain the lower +* triangular part of the symmetric matrix and the strictly +* upper triangular part of C is not referenced. On exit, the +* lower triangular part of the array C is overwritten by the +* lower triangular part of the updated matrix. +* +* LDC - INTEGER. +* On entry, LDC specifies the first dimension of C as declared +* in the calling (sub) program. LDC must be at least +* max( 1, n ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP1,TEMP2 + INTEGER I,INFO,J,L,NROWA + LOGICAL UPPER +* .. +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* +* Test the input parameters. +* + IF (LSAME(TRANS,'N')) THEN + NROWA = N + ELSE + NROWA = K + END IF + UPPER = LSAME(UPLO,'U') +* + INFO = 0 + IF ((.NOT.UPPER) .AND. (.NOT.LSAME(UPLO,'L'))) THEN + INFO = 1 + ELSE IF ((.NOT.LSAME(TRANS,'N')) .AND. + + (.NOT.LSAME(TRANS,'T')) .AND. + + (.NOT.LSAME(TRANS,'C'))) THEN + INFO = 2 + ELSE IF (N.LT.0) THEN + INFO = 3 + ELSE IF (K.LT.0) THEN + INFO = 4 + ELSE IF (LDA.LT.MAX(1,NROWA)) THEN + INFO = 7 + ELSE IF (LDB.LT.MAX(1,NROWA)) THEN + INFO = 9 + ELSE IF (LDC.LT.MAX(1,N)) THEN + INFO = 12 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DSYR2K',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF ((N.EQ.0) .OR. (((ALPHA.EQ.ZERO).OR. + + (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN +* +* And when alpha.eq.zero. +* + IF (ALPHA.EQ.ZERO) THEN + IF (UPPER) THEN + IF (BETA.EQ.ZERO) THEN + DO 20 J = 1,N + DO 10 I = 1,J + C(I,J) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40 J = 1,N + DO 30 I = 1,J + C(I,J) = BETA*C(I,J) + 30 CONTINUE + 40 CONTINUE + END IF + ELSE + IF (BETA.EQ.ZERO) THEN + DO 60 J = 1,N + DO 50 I = J,N + C(I,J) = ZERO + 50 CONTINUE + 60 CONTINUE + ELSE + DO 80 J = 1,N + DO 70 I = J,N + C(I,J) = BETA*C(I,J) + 70 CONTINUE + 80 CONTINUE + END IF + END IF + RETURN + END IF +* +* Start the operations. +* + IF (LSAME(TRANS,'N')) THEN +* +* Form C := alpha*A*B' + alpha*B*A' + C. +* + IF (UPPER) THEN + DO 130 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 90 I = 1,J + C(I,J) = ZERO + 90 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 100 I = 1,J + C(I,J) = BETA*C(I,J) + 100 CONTINUE + END IF + DO 120 L = 1,K + IF ((A(J,L).NE.ZERO) .OR. (B(J,L).NE.ZERO)) THEN + TEMP1 = ALPHA*B(J,L) + TEMP2 = ALPHA*A(J,L) + DO 110 I = 1,J + C(I,J) = C(I,J) + A(I,L)*TEMP1 + + + B(I,L)*TEMP2 + 110 CONTINUE + END IF + 120 CONTINUE + 130 CONTINUE + ELSE + DO 180 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 140 I = J,N + C(I,J) = ZERO + 140 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 150 I = J,N + C(I,J) = BETA*C(I,J) + 150 CONTINUE + END IF + DO 170 L = 1,K + IF ((A(J,L).NE.ZERO) .OR. (B(J,L).NE.ZERO)) THEN + TEMP1 = ALPHA*B(J,L) + TEMP2 = ALPHA*A(J,L) + DO 160 I = J,N + C(I,J) = C(I,J) + A(I,L)*TEMP1 + + + B(I,L)*TEMP2 + 160 CONTINUE + END IF + 170 CONTINUE + 180 CONTINUE + END IF + ELSE +* +* Form C := alpha*A'*B + alpha*B'*A + C. +* + IF (UPPER) THEN + DO 210 J = 1,N + DO 200 I = 1,J + TEMP1 = ZERO + TEMP2 = ZERO + DO 190 L = 1,K + TEMP1 = TEMP1 + A(L,I)*B(L,J) + TEMP2 = TEMP2 + B(L,I)*A(L,J) + 190 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP1 + ALPHA*TEMP2 + ELSE + C(I,J) = BETA*C(I,J) + ALPHA*TEMP1 + + + ALPHA*TEMP2 + END IF + 200 CONTINUE + 210 CONTINUE + ELSE + DO 240 J = 1,N + DO 230 I = J,N + TEMP1 = ZERO + TEMP2 = ZERO + DO 220 L = 1,K + TEMP1 = TEMP1 + A(L,I)*B(L,J) + TEMP2 = TEMP2 + B(L,I)*A(L,J) + 220 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP1 + ALPHA*TEMP2 + ELSE + C(I,J) = BETA*C(I,J) + ALPHA*TEMP1 + + + ALPHA*TEMP2 + END IF + 230 CONTINUE + 240 CONTINUE + END IF + END IF +* + RETURN +* +* End of DSYR2K. +* + END diff --git a/dep/blas/dsyrk.f b/dep/blas/dsyrk.f new file mode 100644 index 00000000..8d461fe9 --- /dev/null +++ b/dep/blas/dsyrk.f @@ -0,0 +1,295 @@ + SUBROUTINE DSYRK(UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC) +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA,BETA + INTEGER K,LDA,LDC,N + CHARACTER TRANS,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),C(LDC,*) +* .. +* +* Purpose +* ======= +* +* DSYRK performs one of the symmetric rank k operations +* +* C := alpha*A*A' + beta*C, +* +* or +* +* C := alpha*A'*A + beta*C, +* +* where alpha and beta are scalars, C is an n by n symmetric matrix +* and A is an n by k matrix in the first case and a k by n matrix +* in the second case. +* +* Arguments +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array C is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of C +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of C +* is to be referenced. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' C := alpha*A*A' + beta*C. +* +* TRANS = 'T' or 't' C := alpha*A'*A + beta*C. +* +* TRANS = 'C' or 'c' C := alpha*A'*A + beta*C. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix C. N must be +* at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with TRANS = 'N' or 'n', K specifies the number +* of columns of the matrix A, and on entry with +* TRANS = 'T' or 't' or 'C' or 'c', K specifies the number +* of rows of the matrix A. K must be at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is +* k when TRANS = 'N' or 'n', and is n otherwise. +* Before entry with TRANS = 'N' or 'n', the leading n by k +* part of the array A must contain the matrix A, otherwise +* the leading k by n part of the array A must contain the +* matrix A. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When TRANS = 'N' or 'n' +* then LDA must be at least max( 1, n ), otherwise LDA must +* be at least max( 1, k ). +* Unchanged on exit. +* +* BETA - DOUBLE PRECISION. +* On entry, BETA specifies the scalar beta. +* Unchanged on exit. +* +* C - DOUBLE PRECISION array of DIMENSION ( LDC, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array C must contain the upper +* triangular part of the symmetric matrix and the strictly +* lower triangular part of C is not referenced. On exit, the +* upper triangular part of the array C is overwritten by the +* upper triangular part of the updated matrix. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array C must contain the lower +* triangular part of the symmetric matrix and the strictly +* upper triangular part of C is not referenced. On exit, the +* lower triangular part of the array C is overwritten by the +* lower triangular part of the updated matrix. +* +* LDC - INTEGER. +* On entry, LDC specifies the first dimension of C as declared +* in the calling (sub) program. LDC must be at least +* max( 1, n ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,J,L,NROWA + LOGICAL UPPER +* .. +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* +* Test the input parameters. +* + IF (LSAME(TRANS,'N')) THEN + NROWA = N + ELSE + NROWA = K + END IF + UPPER = LSAME(UPLO,'U') +* + INFO = 0 + IF ((.NOT.UPPER) .AND. (.NOT.LSAME(UPLO,'L'))) THEN + INFO = 1 + ELSE IF ((.NOT.LSAME(TRANS,'N')) .AND. + + (.NOT.LSAME(TRANS,'T')) .AND. + + (.NOT.LSAME(TRANS,'C'))) THEN + INFO = 2 + ELSE IF (N.LT.0) THEN + INFO = 3 + ELSE IF (K.LT.0) THEN + INFO = 4 + ELSE IF (LDA.LT.MAX(1,NROWA)) THEN + INFO = 7 + ELSE IF (LDC.LT.MAX(1,N)) THEN + INFO = 10 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DSYRK ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF ((N.EQ.0) .OR. (((ALPHA.EQ.ZERO).OR. + + (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN +* +* And when alpha.eq.zero. +* + IF (ALPHA.EQ.ZERO) THEN + IF (UPPER) THEN + IF (BETA.EQ.ZERO) THEN + DO 20 J = 1,N + DO 10 I = 1,J + C(I,J) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40 J = 1,N + DO 30 I = 1,J + C(I,J) = BETA*C(I,J) + 30 CONTINUE + 40 CONTINUE + END IF + ELSE + IF (BETA.EQ.ZERO) THEN + DO 60 J = 1,N + DO 50 I = J,N + C(I,J) = ZERO + 50 CONTINUE + 60 CONTINUE + ELSE + DO 80 J = 1,N + DO 70 I = J,N + C(I,J) = BETA*C(I,J) + 70 CONTINUE + 80 CONTINUE + END IF + END IF + RETURN + END IF +* +* Start the operations. +* + IF (LSAME(TRANS,'N')) THEN +* +* Form C := alpha*A*A' + beta*C. +* + IF (UPPER) THEN + DO 130 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 90 I = 1,J + C(I,J) = ZERO + 90 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 100 I = 1,J + C(I,J) = BETA*C(I,J) + 100 CONTINUE + END IF + DO 120 L = 1,K + IF (A(J,L).NE.ZERO) THEN + TEMP = ALPHA*A(J,L) + DO 110 I = 1,J + C(I,J) = C(I,J) + TEMP*A(I,L) + 110 CONTINUE + END IF + 120 CONTINUE + 130 CONTINUE + ELSE + DO 180 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 140 I = J,N + C(I,J) = ZERO + 140 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 150 I = J,N + C(I,J) = BETA*C(I,J) + 150 CONTINUE + END IF + DO 170 L = 1,K + IF (A(J,L).NE.ZERO) THEN + TEMP = ALPHA*A(J,L) + DO 160 I = J,N + C(I,J) = C(I,J) + TEMP*A(I,L) + 160 CONTINUE + END IF + 170 CONTINUE + 180 CONTINUE + END IF + ELSE +* +* Form C := alpha*A'*A + beta*C. +* + IF (UPPER) THEN + DO 210 J = 1,N + DO 200 I = 1,J + TEMP = ZERO + DO 190 L = 1,K + TEMP = TEMP + A(L,I)*A(L,J) + 190 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP + ELSE + C(I,J) = ALPHA*TEMP + BETA*C(I,J) + END IF + 200 CONTINUE + 210 CONTINUE + ELSE + DO 240 J = 1,N + DO 230 I = J,N + TEMP = ZERO + DO 220 L = 1,K + TEMP = TEMP + A(L,I)*A(L,J) + 220 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP + ELSE + C(I,J) = ALPHA*TEMP + BETA*C(I,J) + END IF + 230 CONTINUE + 240 CONTINUE + END IF + END IF +* + RETURN +* +* End of DSYRK . +* + END diff --git a/dep/blas/dtbsv.f b/dep/blas/dtbsv.f new file mode 100644 index 00000000..d87ed82d --- /dev/null +++ b/dep/blas/dtbsv.f @@ -0,0 +1,346 @@ + SUBROUTINE DTBSV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, K, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* DTBSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular band matrix, with ( k + 1 ) +* diagonals. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' A'*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with UPLO = 'U' or 'u', K specifies the number of +* super-diagonals of the matrix A. +* On entry with UPLO = 'L' or 'l', K specifies the number of +* sub-diagonals of the matrix A. +* K must satisfy 0 .le. K. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) +* by n part of the array A must contain the upper triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row +* ( k + 1 ) of the array, the first super-diagonal starting at +* position 2 in row k, and so on. The top left k by k triangle +* of the array A is not referenced. +* The following program segment will transfer an upper +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = K + 1 - J +* DO 10, I = MAX( 1, J - K ), J +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) +* by n part of the array A must contain the lower triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row 1 of +* the array, the first sub-diagonal starting at position 1 in +* row 2, and so on. The bottom right k by k triangle of the +* array A is not referenced. +* The following program segment will transfer a lower +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = 1 - J +* DO 10, I = J, MIN( N, J + K ) +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Note that when DIAG = 'U' or 'u' the elements of the array A +* corresponding to the diagonal elements of the matrix are not +* referenced, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( k + 1 ). +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I, INFO, IX, J, JX, KPLUS1, KX, L + LOGICAL NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( K.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( K + 1 ) )THEN + INFO = 7 + ELSE IF( INCX.EQ.0 )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DTBSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOUNIT = LSAME( DIAG, 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed by sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + L = KPLUS1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( KPLUS1, J ) + TEMP = X( J ) + DO 10, I = J - 1, MAX( 1, J - K ), -1 + X( I ) = X( I ) - TEMP*A( L + I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 40, J = N, 1, -1 + KX = KX - INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = KPLUS1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( KPLUS1, J ) + TEMP = X( JX ) + DO 30, I = J - 1, MAX( 1, J - K ), -1 + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX - INCX + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + L = 1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( 1, J ) + TEMP = X( J ) + DO 50, I = J + 1, MIN( N, J + K ) + X( I ) = X( I ) - TEMP*A( L + I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + KX = KX + INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = 1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( 1, J ) + TEMP = X( JX ) + DO 70, I = J + 1, MIN( N, J + K ) + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX + INCX + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A')*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 100, J = 1, N + TEMP = X( J ) + L = KPLUS1 - J + DO 90, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + X( J ) = TEMP + 100 CONTINUE + ELSE + JX = KX + DO 120, J = 1, N + TEMP = X( JX ) + IX = KX + L = KPLUS1 - J + DO 110, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX + INCX + 110 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + X( JX ) = TEMP + JX = JX + INCX + IF( J.GT.K ) + $ KX = KX + INCX + 120 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 140, J = N, 1, -1 + TEMP = X( J ) + L = 1 - J + DO 130, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( I ) + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + X( J ) = TEMP + 140 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 160, J = N, 1, -1 + TEMP = X( JX ) + IX = KX + L = 1 - J + DO 150, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX - INCX + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + X( JX ) = TEMP + JX = JX - INCX + IF( ( N - J ).GE.K ) + $ KX = KX - INCX + 160 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTBSV . +* + END diff --git a/dep/blas/dtrmm.f b/dep/blas/dtrmm.f new file mode 100644 index 00000000..f98da46a --- /dev/null +++ b/dep/blas/dtrmm.f @@ -0,0 +1,355 @@ + SUBROUTINE DTRMM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + DOUBLE PRECISION ALPHA +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DTRMM performs one of the matrix-matrix operations +* +* B := alpha*op( A )*B, or B := alpha*B*op( A ), +* +* where alpha is a scalar, B is an m by n matrix, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A'. +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) multiplies B from +* the left or right as follows: +* +* SIDE = 'L' or 'l' B := alpha*op( A )*B. +* +* SIDE = 'R' or 'r' B := alpha*B*op( A ). +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = A'. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - DOUBLE PRECISION array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the matrix B, and on exit is overwritten by the +* transformed matrix. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + DOUBLE PRECISION TEMP +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DTRMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*A*B. +* + IF( UPPER )THEN + DO 50, J = 1, N + DO 40, K = 1, M + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + DO 30, I = 1, K - 1 + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 30 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + B( K, J ) = TEMP + END IF + 40 CONTINUE + 50 CONTINUE + ELSE + DO 80, J = 1, N + DO 70 K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + B( K, J ) = TEMP + IF( NOUNIT ) + $ B( K, J ) = B( K, J )*A( K, K ) + DO 60, I = K + 1, M + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 60 CONTINUE + END IF + 70 CONTINUE + 80 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A'. +* + IF( UPPER )THEN + DO 110, J = 1, N + DO 100, I = M, 1, -1 + TEMP = B( I, J ) + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 90, K = 1, I - 1 + TEMP = TEMP + A( K, I )*B( K, J ) + 90 CONTINUE + B( I, J ) = ALPHA*TEMP + 100 CONTINUE + 110 CONTINUE + ELSE + DO 140, J = 1, N + DO 130, I = 1, M + TEMP = B( I, J ) + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 120, K = I + 1, M + TEMP = TEMP + A( K, I )*B( K, J ) + 120 CONTINUE + B( I, J ) = ALPHA*TEMP + 130 CONTINUE + 140 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*A. +* + IF( UPPER )THEN + DO 180, J = N, 1, -1 + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 150, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 150 CONTINUE + DO 170, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 160, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 160 CONTINUE + END IF + 170 CONTINUE + 180 CONTINUE + ELSE + DO 220, J = 1, N + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 190, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 190 CONTINUE + DO 210, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 200, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 200 CONTINUE + END IF + 210 CONTINUE + 220 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A'. +* + IF( UPPER )THEN + DO 260, K = 1, N + DO 240, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + TEMP = ALPHA*A( J, K ) + DO 230, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 230 CONTINUE + END IF + 240 CONTINUE + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + IF( TEMP.NE.ONE )THEN + DO 250, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 250 CONTINUE + END IF + 260 CONTINUE + ELSE + DO 300, K = N, 1, -1 + DO 280, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + TEMP = ALPHA*A( J, K ) + DO 270, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 270 CONTINUE + END IF + 280 CONTINUE + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + IF( TEMP.NE.ONE )THEN + DO 290, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 290 CONTINUE + END IF + 300 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRMM . +* + END diff --git a/dep/blas/dtrmv.f b/dep/blas/dtrmv.f new file mode 100644 index 00000000..1648d9b1 --- /dev/null +++ b/dep/blas/dtrmv.f @@ -0,0 +1,278 @@ + SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +* .. Scalar Arguments .. + INTEGER INCX,LDA,N + CHARACTER DIAG,TRANS,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),X(*) +* .. +* +* Purpose +* ======= +* +* DTRMV performs one of the matrix-vector operations +* +* x := A*x, or x := A'*x, +* +* where x is an n element vector and A is an n by n unit, or non-unit, +* upper or lower triangular matrix. +* +* Arguments +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' x := A*x. +* +* TRANS = 'T' or 't' x := A'*x. +* +* TRANS = 'C' or 'c' x := A'*x. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* X - DOUBLE PRECISION array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. On exit, X is overwritten with the +* tranformed vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER (ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,IX,J,JX,KX + LOGICAL NOUNIT +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* +* Test the input parameters. +* + INFO = 0 + IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN + INFO = 1 + ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND. + + .NOT.LSAME(TRANS,'C')) THEN + INFO = 2 + ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN + INFO = 3 + ELSE IF (N.LT.0) THEN + INFO = 4 + ELSE IF (LDA.LT.MAX(1,N)) THEN + INFO = 6 + ELSE IF (INCX.EQ.0) THEN + INFO = 8 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DTRMV ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF (N.EQ.0) RETURN +* + NOUNIT = LSAME(DIAG,'N') +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF (INCX.LE.0) THEN + KX = 1 - (N-1)*INCX + ELSE IF (INCX.NE.1) THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF (LSAME(TRANS,'N')) THEN +* +* Form x := A*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 20 J = 1,N + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 10 I = 1,J - 1 + X(I) = X(I) + TEMP*A(I,J) + 10 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 20 CONTINUE + ELSE + JX = KX + DO 40 J = 1,N + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 30 I = 1,J - 1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX + INCX + 30 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX + INCX + 40 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 60 J = N,1,-1 + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 50 I = N,J + 1,-1 + X(I) = X(I) + TEMP*A(I,J) + 50 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 60 CONTINUE + ELSE + KX = KX + (N-1)*INCX + JX = KX + DO 80 J = N,1,-1 + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 70 I = N,J + 1,-1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX - INCX + 70 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX - INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := A'*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 100 J = N,1,-1 + TEMP = X(J) + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 90 I = J - 1,1,-1 + TEMP = TEMP + A(I,J)*X(I) + 90 CONTINUE + X(J) = TEMP + 100 CONTINUE + ELSE + JX = KX + (N-1)*INCX + DO 120 J = N,1,-1 + TEMP = X(JX) + IX = JX + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 110 I = J - 1,1,-1 + IX = IX - INCX + TEMP = TEMP + A(I,J)*X(IX) + 110 CONTINUE + X(JX) = TEMP + JX = JX - INCX + 120 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 140 J = 1,N + TEMP = X(J) + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 130 I = J + 1,N + TEMP = TEMP + A(I,J)*X(I) + 130 CONTINUE + X(J) = TEMP + 140 CONTINUE + ELSE + JX = KX + DO 160 J = 1,N + TEMP = X(JX) + IX = JX + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 150 I = J + 1,N + IX = IX + INCX + TEMP = TEMP + A(I,J)*X(IX) + 150 CONTINUE + X(JX) = TEMP + JX = JX + INCX + 160 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRMV . +* + END diff --git a/dep/blas/dtrsm.f b/dep/blas/dtrsm.f new file mode 100644 index 00000000..e8425142 --- /dev/null +++ b/dep/blas/dtrsm.f @@ -0,0 +1,378 @@ + SUBROUTINE DTRSM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + DOUBLE PRECISION ALPHA +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DTRSM solves one of the matrix equations +* +* op( A )*X = alpha*B, or X*op( A ) = alpha*B, +* +* where alpha is a scalar, X and B are m by n matrices, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A'. +* +* The matrix X is overwritten on B. +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) appears on the left +* or right of X as follows: +* +* SIDE = 'L' or 'l' op( A )*X = alpha*B. +* +* SIDE = 'R' or 'r' X*op( A ) = alpha*B. +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = A'. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - DOUBLE PRECISION. +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - DOUBLE PRECISION array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the right-hand side matrix B, and on exit is +* overwritten by the solution matrix X. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + DOUBLE PRECISION TEMP +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'DTRSM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*inv( A )*B. +* + IF( UPPER )THEN + DO 60, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 30, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 30 CONTINUE + END IF + DO 50, K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 40, I = 1, K - 1 + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 40 CONTINUE + END IF + 50 CONTINUE + 60 CONTINUE + ELSE + DO 100, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 70, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 70 CONTINUE + END IF + DO 90 K = 1, M + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 80, I = K + 1, M + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 80 CONTINUE + END IF + 90 CONTINUE + 100 CONTINUE + END IF + ELSE +* +* Form B := alpha*inv( A' )*B. +* + IF( UPPER )THEN + DO 130, J = 1, N + DO 120, I = 1, M + TEMP = ALPHA*B( I, J ) + DO 110, K = 1, I - 1 + TEMP = TEMP - A( K, I )*B( K, J ) + 110 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + B( I, J ) = TEMP + 120 CONTINUE + 130 CONTINUE + ELSE + DO 160, J = 1, N + DO 150, I = M, 1, -1 + TEMP = ALPHA*B( I, J ) + DO 140, K = I + 1, M + TEMP = TEMP - A( K, I )*B( K, J ) + 140 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + B( I, J ) = TEMP + 150 CONTINUE + 160 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*inv( A ). +* + IF( UPPER )THEN + DO 210, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 170, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 170 CONTINUE + END IF + DO 190, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + DO 180, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 180 CONTINUE + END IF + 190 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 200, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 200 CONTINUE + END IF + 210 CONTINUE + ELSE + DO 260, J = N, 1, -1 + IF( ALPHA.NE.ONE )THEN + DO 220, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 220 CONTINUE + END IF + DO 240, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + DO 230, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 230 CONTINUE + END IF + 240 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 250, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 250 CONTINUE + END IF + 260 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*inv( A' ). +* + IF( UPPER )THEN + DO 310, K = N, 1, -1 + IF( NOUNIT )THEN + TEMP = ONE/A( K, K ) + DO 270, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 270 CONTINUE + END IF + DO 290, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + TEMP = A( J, K ) + DO 280, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 280 CONTINUE + END IF + 290 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 300, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 300 CONTINUE + END IF + 310 CONTINUE + ELSE + DO 360, K = 1, N + IF( NOUNIT )THEN + TEMP = ONE/A( K, K ) + DO 320, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 320 CONTINUE + END IF + DO 340, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + TEMP = A( J, K ) + DO 330, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 330 CONTINUE + END IF + 340 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 350, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 350 CONTINUE + END IF + 360 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRSM . +* + END diff --git a/dep/blas/dzasum.f b/dep/blas/dzasum.f new file mode 100644 index 00000000..d21c1ffc --- /dev/null +++ b/dep/blas/dzasum.f @@ -0,0 +1,34 @@ + double precision function dzasum(n,zx,incx) +c +c takes the sum of the absolute values. +c jack dongarra, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*) + double precision stemp,dcabs1 + integer i,incx,ix,n +c + dzasum = 0.0d0 + stemp = 0.0d0 + if( n.le.0 .or. incx.le.0 )return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + do 10 i = 1,n + stemp = stemp + dcabs1(zx(ix)) + ix = ix + incx + 10 continue + dzasum = stemp + return +c +c code for increment equal to 1 +c + 20 do 30 i = 1,n + stemp = stemp + dcabs1(zx(i)) + 30 continue + dzasum = stemp + return + end diff --git a/dep/blas/dznrm2.f b/dep/blas/dznrm2.f new file mode 100644 index 00000000..205ce393 --- /dev/null +++ b/dep/blas/dznrm2.f @@ -0,0 +1,67 @@ + DOUBLE PRECISION FUNCTION DZNRM2( N, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, N +* .. Array Arguments .. + COMPLEX*16 X( * ) +* .. +* +* DZNRM2 returns the euclidean norm of a vector via the function +* name, so that +* +* DZNRM2 := sqrt( conjg( x' )*x ) +* +* +* +* -- This version written on 25-October-1982. +* Modified on 14-October-1993 to inline the call to ZLASSQ. +* Sven Hammarling, Nag Ltd. +* +* +* .. Parameters .. + DOUBLE PRECISION ONE , ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. Local Scalars .. + INTEGER IX + DOUBLE PRECISION NORM, SCALE, SSQ, TEMP +* .. Intrinsic Functions .. + INTRINSIC ABS, DIMAG, DBLE, SQRT +* .. +* .. Executable Statements .. + IF( N.LT.1 .OR. INCX.LT.1 )THEN + NORM = ZERO + ELSE + SCALE = ZERO + SSQ = ONE +* The following loop is equivalent to this call to the LAPACK +* auxiliary routine: +* CALL ZLASSQ( N, X, INCX, SCALE, SSQ ) +* + DO 10, IX = 1, 1 + ( N - 1 )*INCX, INCX + IF( DBLE( X( IX ) ).NE.ZERO )THEN + TEMP = ABS( DBLE( X( IX ) ) ) + IF( SCALE.LT.TEMP )THEN + SSQ = ONE + SSQ*( SCALE/TEMP )**2 + SCALE = TEMP + ELSE + SSQ = SSQ + ( TEMP/SCALE )**2 + END IF + END IF + IF( DIMAG( X( IX ) ).NE.ZERO )THEN + TEMP = ABS( DIMAG( X( IX ) ) ) + IF( SCALE.LT.TEMP )THEN + SSQ = ONE + SSQ*( SCALE/TEMP )**2 + SCALE = TEMP + ELSE + SSQ = SSQ + ( TEMP/SCALE )**2 + END IF + END IF + 10 CONTINUE + NORM = SCALE * SQRT( SSQ ) + END IF +* + DZNRM2 = NORM + RETURN +* +* End of DZNRM2. +* + END diff --git a/dep/blas/icamax.f b/dep/blas/icamax.f new file mode 100644 index 00000000..b13d4904 --- /dev/null +++ b/dep/blas/icamax.f @@ -0,0 +1,43 @@ + integer function icamax(n,cx,incx) +c +c finds the index of element having max. absolute value. +c jack dongarra, linpack, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*) + real smax + integer i,incx,ix,n + complex zdum + real cabs1 + cabs1(zdum) = abs(real(zdum)) + abs(aimag(zdum)) +c + icamax = 0 + if( n.lt.1 .or. incx.le.0 ) return + icamax = 1 + if(n.eq.1)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + smax = cabs1(cx(1)) + ix = ix + incx + do 10 i = 2,n + if(cabs1(cx(ix)).le.smax) go to 5 + icamax = i + smax = cabs1(cx(ix)) + 5 ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c + 20 smax = cabs1(cx(1)) + do 30 i = 2,n + if(cabs1(cx(i)).le.smax) go to 30 + icamax = i + smax = cabs1(cx(i)) + 30 continue + return + end diff --git a/dep/blas/idamax.f b/dep/blas/idamax.f new file mode 100644 index 00000000..d01b088b --- /dev/null +++ b/dep/blas/idamax.f @@ -0,0 +1,39 @@ + integer function idamax(n,dx,incx) +c +c finds the index of element having max. absolute value. +c jack dongarra, linpack, 3/11/78. +c modified to correct problem with negative increment, 8/21/90. +c + double precision dx(1),dmax + integer i,incx,ix,n +c + idamax = 0 + if( n .lt. 1 ) return + idamax = 1 + if(n.eq.1)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + dmax = dabs(dx(ix)) + ix = ix + incx + do 10 i = 2,n + if(dabs(dx(ix)).le.dmax) go to 5 + idamax = i + dmax = dabs(dx(ix)) + 5 ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c + 20 dmax = dabs(dx(1)) + do 30 i = 2,n + if(dabs(dx(i)).le.dmax) go to 30 + idamax = i + dmax = dabs(dx(i)) + 30 continue + return + end diff --git a/dep/blas/isamax.f b/dep/blas/isamax.f new file mode 100644 index 00000000..345fae60 --- /dev/null +++ b/dep/blas/isamax.f @@ -0,0 +1,39 @@ + integer function isamax(n,sx,incx) +c +c finds the index of element having max. absolute value. +c jack dongarra, linpack, 3/11/78. +c modified to correct problem with negative increment, 8/21/90. +c + real sx(1),smax + integer i,incx,ix,n +c + isamax = 0 + if( n .lt. 1 ) return + isamax = 1 + if(n.eq.1)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + smax = abs(sx(ix)) + ix = ix + incx + do 10 i = 2,n + if(abs(sx(ix)).le.smax) go to 5 + isamax = i + smax = abs(sx(ix)) + 5 ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c + 20 smax = abs(sx(1)) + do 30 i = 2,n + if(abs(sx(i)).le.smax) go to 30 + isamax = i + smax = abs(sx(i)) + 30 continue + return + end diff --git a/dep/blas/izamax.f b/dep/blas/izamax.f new file mode 100644 index 00000000..a8f84865 --- /dev/null +++ b/dep/blas/izamax.f @@ -0,0 +1,49 @@ + integer function izamax(n,zx,incx) +c +c finds the index of element having max. absolute value. +c jack dongarra, 1/15/85. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*) + double precision smax + integer i,incx,ix,n + double precision dcabs1 +c + izamax = 0 + if( n.lt.1 .or. incx.le.0 )return + izamax = 1 + if(n.eq.1)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + smax = dcabs1(zx(1)) + ix = ix + incx + do 10 i = 2,n + if(dcabs1(zx(ix)).le.smax) go to 5 + izamax = i + smax = dcabs1(zx(ix)) + 5 ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c + 20 smax = dcabs1(zx(1)) + do 30 i = 2,n + if(dcabs1(zx(i)).le.smax) go to 30 + izamax = i + smax = dcabs1(zx(i)) + 30 continue + return + end + double precision function dcabs1(z) + double complex z,zz + double precision t(2) + equivalence (zz,t(1)) + zz = z + dcabs1 = dabs(t(1)) + dabs(t(2)) + return + end diff --git a/dep/blas/lsame.f b/dep/blas/lsame.f new file mode 100644 index 00000000..f5369026 --- /dev/null +++ b/dep/blas/lsame.f @@ -0,0 +1,85 @@ + LOGICAL FUNCTION LSAME(CA,CB) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER CA,CB +* .. +* +* Purpose +* ======= +* +* LSAME returns .TRUE. if CA is the same letter as CB regardless of +* case. +* +* Arguments +* ========= +* +* CA (input) CHARACTER*1 +* +* CB (input) CHARACTER*1 +* CA and CB specify the single characters to be compared. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA,INTB,ZCODE +* .. +* +* Test if the characters are equal +* + LSAME = CA .EQ. CB + IF (LSAME) RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR('Z') +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR(CA) + INTB = ICHAR(CB) +* + IF (ZCODE.EQ.90 .OR. ZCODE.EQ.122) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF (INTA.GE.97 .AND. INTA.LE.122) INTA = INTA - 32 + IF (INTB.GE.97 .AND. INTB.LE.122) INTB = INTB - 32 +* + ELSE IF (ZCODE.EQ.233 .OR. ZCODE.EQ.169) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF (INTA.GE.129 .AND. INTA.LE.137 .OR. + + INTA.GE.145 .AND. INTA.LE.153 .OR. + + INTA.GE.162 .AND. INTA.LE.169) INTA = INTA + 64 + IF (INTB.GE.129 .AND. INTB.LE.137 .OR. + + INTB.GE.145 .AND. INTB.LE.153 .OR. + + INTB.GE.162 .AND. INTB.LE.169) INTB = INTB + 64 +* + ELSE IF (ZCODE.EQ.218 .OR. ZCODE.EQ.250) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF (INTA.GE.225 .AND. INTA.LE.250) INTA = INTA - 32 + IF (INTB.GE.225 .AND. INTB.LE.250) INTB = INTB - 32 + END IF + LSAME = INTA .EQ. INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/dep/blas/sasum.f b/dep/blas/sasum.f new file mode 100644 index 00000000..e33964c0 --- /dev/null +++ b/dep/blas/sasum.f @@ -0,0 +1,45 @@ + real function sasum(n,sx,incx) +c +c takes the sum of the absolute values. +c uses unrolled loops for increment equal to one. +c jack dongarra, linpack, 3/11/78. +c modified to correct problem with negative increment, 8/21/90. +c + real sx(1),stemp + integer i,incx,ix,m,mp1,n +c + sasum = 0.0e0 + stemp = 0.0e0 + if(n.le.0)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + do 10 i = 1,n + stemp = stemp + abs(sx(ix)) + ix = ix + incx + 10 continue + sasum = stemp + return +c +c code for increment equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,6) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + stemp = stemp + abs(sx(i)) + 30 continue + if( n .lt. 6 ) go to 60 + 40 mp1 = m + 1 + do 50 i = mp1,n,6 + stemp = stemp + abs(sx(i)) + abs(sx(i + 1)) + abs(sx(i + 2)) + * + abs(sx(i + 3)) + abs(sx(i + 4)) + abs(sx(i + 5)) + 50 continue + 60 sasum = stemp + return + end diff --git a/dep/blas/saxpy.f b/dep/blas/saxpy.f new file mode 100644 index 00000000..f23f6659 --- /dev/null +++ b/dep/blas/saxpy.f @@ -0,0 +1,47 @@ + subroutine saxpy(n,sa,sx,incx,sy,incy) +c +c constant times a vector plus a vector. +c uses unrolled loop for increments equal to one. +c jack dongarra, linpack, 3/11/78. +c + real sx(1),sy(1),sa + integer i,incx,incy,ix,iy,m,mp1,n +c + if(n.le.0)return + if (sa .eq. 0.0) return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + sy(iy) = sy(iy) + sa*sx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,4) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + sy(i) = sy(i) + sa*sx(i) + 30 continue + if( n .lt. 4 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,4 + sy(i) = sy(i) + sa*sx(i) + sy(i + 1) = sy(i + 1) + sa*sx(i + 1) + sy(i + 2) = sy(i + 2) + sa*sx(i + 2) + sy(i + 3) = sy(i + 3) + sa*sx(i + 3) + 50 continue + return + end diff --git a/dep/blas/scasum.f b/dep/blas/scasum.f new file mode 100644 index 00000000..b6c0ea07 --- /dev/null +++ b/dep/blas/scasum.f @@ -0,0 +1,34 @@ + real function scasum(n,cx,incx) +c +c takes the sum of the absolute values of a complex vector and +c returns a single precision result. +c jack dongarra, linpack, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + complex cx(*) + real stemp + integer i,incx,n,nincx +c + scasum = 0.0e0 + stemp = 0.0e0 + if( n.le.0 .or. incx.le.0 )return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + nincx = n*incx + do 10 i = 1,nincx,incx + stemp = stemp + abs(real(cx(i))) + abs(aimag(cx(i))) + 10 continue + scasum = stemp + return +c +c code for increment equal to 1 +c + 20 do 30 i = 1,n + stemp = stemp + abs(real(cx(i))) + abs(aimag(cx(i))) + 30 continue + scasum = stemp + return + end diff --git a/dep/blas/scnrm2.f b/dep/blas/scnrm2.f new file mode 100644 index 00000000..8bfe9ae7 --- /dev/null +++ b/dep/blas/scnrm2.f @@ -0,0 +1,67 @@ + REAL FUNCTION SCNRM2( N, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, N +* .. Array Arguments .. + COMPLEX X( * ) +* .. +* +* SCNRM2 returns the euclidean norm of a vector via the function +* name, so that +* +* SCNRM2 := sqrt( conjg( x' )*x ) +* +* +* +* -- This version written on 25-October-1982. +* Modified on 14-October-1993 to inline the call to CLASSQ. +* Sven Hammarling, Nag Ltd. +* +* +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. Local Scalars .. + INTEGER IX + REAL NORM, SCALE, SSQ, TEMP +* .. Intrinsic Functions .. + INTRINSIC ABS, AIMAG, REAL, SQRT +* .. +* .. Executable Statements .. + IF( N.LT.1 .OR. INCX.LT.1 )THEN + NORM = ZERO + ELSE + SCALE = ZERO + SSQ = ONE +* The following loop is equivalent to this call to the LAPACK +* auxiliary routine: +* CALL CLASSQ( N, X, INCX, SCALE, SSQ ) +* + DO 10, IX = 1, 1 + ( N - 1 )*INCX, INCX + IF( REAL( X( IX ) ).NE.ZERO )THEN + TEMP = ABS( REAL( X( IX ) ) ) + IF( SCALE.LT.TEMP )THEN + SSQ = ONE + SSQ*( SCALE/TEMP )**2 + SCALE = TEMP + ELSE + SSQ = SSQ + ( TEMP/SCALE )**2 + END IF + END IF + IF( AIMAG( X( IX ) ).NE.ZERO )THEN + TEMP = ABS( AIMAG( X( IX ) ) ) + IF( SCALE.LT.TEMP )THEN + SSQ = ONE + SSQ*( SCALE/TEMP )**2 + SCALE = TEMP + ELSE + SSQ = SSQ + ( TEMP/SCALE )**2 + END IF + END IF + 10 CONTINUE + NORM = SCALE * SQRT( SSQ ) + END IF +* + SCNRM2 = NORM + RETURN +* +* End of SCNRM2. +* + END diff --git a/dep/blas/scopy.f b/dep/blas/scopy.f new file mode 100644 index 00000000..86db4290 --- /dev/null +++ b/dep/blas/scopy.f @@ -0,0 +1,49 @@ + subroutine scopy(n,sx,incx,sy,incy) +c +c copies a vector, x, to a vector, y. +c uses unrolled loops for increments equal to 1. +c jack dongarra, linpack, 3/11/78. +c + real sx(1),sy(1) + integer i,incx,incy,ix,iy,m,mp1,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + sy(iy) = sx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,7) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + sy(i) = sx(i) + 30 continue + if( n .lt. 7 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,7 + sy(i) = sx(i) + sy(i + 1) = sx(i + 1) + sy(i + 2) = sx(i + 2) + sy(i + 3) = sx(i + 3) + sy(i + 4) = sx(i + 4) + sy(i + 5) = sx(i + 5) + sy(i + 6) = sx(i + 6) + 50 continue + return + end diff --git a/dep/blas/sdot.f b/dep/blas/sdot.f new file mode 100644 index 00000000..10a45f2d --- /dev/null +++ b/dep/blas/sdot.f @@ -0,0 +1,48 @@ + real function sdot(n,sx,incx,sy,incy) +c +c forms the dot product of two vectors. +c uses unrolled loops for increments equal to one. +c jack dongarra, linpack, 3/11/78. +c + real sx(1),sy(1),stemp + integer i,incx,incy,ix,iy,m,mp1,n +c + stemp = 0.0e0 + sdot = 0.0e0 + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + stemp = stemp + sx(ix)*sy(iy) + ix = ix + incx + iy = iy + incy + 10 continue + sdot = stemp + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,5) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + stemp = stemp + sx(i)*sy(i) + 30 continue + if( n .lt. 5 ) go to 60 + 40 mp1 = m + 1 + do 50 i = mp1,n,5 + stemp = stemp + sx(i)*sy(i) + sx(i + 1)*sy(i + 1) + + * sx(i + 2)*sy(i + 2) + sx(i + 3)*sy(i + 3) + sx(i + 4)*sy(i + 4) + 50 continue + 60 sdot = stemp + return + end diff --git a/dep/blas/sgbmv.f b/dep/blas/sgbmv.f new file mode 100644 index 00000000..926abd73 --- /dev/null +++ b/dep/blas/sgbmv.f @@ -0,0 +1,300 @@ + SUBROUTINE SGBMV ( TRANS, M, N, KL, KU, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + REAL ALPHA, BETA + INTEGER INCX, INCY, KL, KU, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + REAL A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* SGBMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n band matrix, with kl sub-diagonals and ku super-diagonals. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* KL - INTEGER. +* On entry, KL specifies the number of sub-diagonals of the +* matrix A. KL must satisfy 0 .le. KL. +* Unchanged on exit. +* +* KU - INTEGER. +* On entry, KU specifies the number of super-diagonals of the +* matrix A. KU must satisfy 0 .le. KU. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, n ). +* Before entry, the leading ( kl + ku + 1 ) by n part of the +* array A must contain the matrix of coefficients, supplied +* column by column, with the leading diagonal of the matrix in +* row ( ku + 1 ) of the array, the first super-diagonal +* starting at position 2 in row ku, the first sub-diagonal +* starting at position 1 in row ( ku + 2 ), and so on. +* Elements in the array A that do not correspond to elements +* in the band matrix (such as the top left ku by ku triangle) +* are not referenced. +* The following program segment will transfer a band matrix +* from conventional full matrix storage to band storage: +* +* DO 20, J = 1, N +* K = KU + 1 - J +* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) +* A( K + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( kl + ku + 1 ). +* Unchanged on exit. +* +* X - REAL array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - REAL . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - REAL array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry, the incremented array Y must contain the +* vector y. On exit, Y is overwritten by the updated vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. Local Scalars .. + REAL TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, K, KUP1, KX, KY, + $ LENX, LENY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( KL.LT.0 )THEN + INFO = 4 + ELSE IF( KU.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( KL + KU + 1 ) )THEN + INFO = 8 + ELSE IF( INCX.EQ.0 )THEN + INFO = 10 + ELSE IF( INCY.EQ.0 )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'SGBMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the band part of A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + KUP1 = KU + 1 + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + K = KUP1 - J + DO 50, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( I ) = Y( I ) + TEMP*A( K + I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + K = KUP1 - J + DO 70, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( IY ) = Y( IY ) + TEMP*A( K + I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + IF( J.GT.KU ) + $ KY = KY + INCY + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 100, J = 1, N + TEMP = ZERO + K = KUP1 - J + DO 90, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( I ) + 90 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 100 CONTINUE + ELSE + DO 120, J = 1, N + TEMP = ZERO + IX = KX + K = KUP1 - J + DO 110, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( IX ) + IX = IX + INCX + 110 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + IF( J.GT.KU ) + $ KX = KX + INCX + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of SGBMV . +* + END diff --git a/dep/blas/sgemm.f b/dep/blas/sgemm.f new file mode 100644 index 00000000..8dc77297 --- /dev/null +++ b/dep/blas/sgemm.f @@ -0,0 +1,313 @@ + SUBROUTINE SGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, + $ BETA, C, LDC ) +* .. Scalar Arguments .. + CHARACTER*1 TRANSA, TRANSB + INTEGER M, N, K, LDA, LDB, LDC + REAL ALPHA, BETA +* .. Array Arguments .. + REAL A( LDA, * ), B( LDB, * ), C( LDC, * ) +* .. +* +* Purpose +* ======= +* +* SGEMM performs one of the matrix-matrix operations +* +* C := alpha*op( A )*op( B ) + beta*C, +* +* where op( X ) is one of +* +* op( X ) = X or op( X ) = X', +* +* alpha and beta are scalars, and A, B and C are matrices, with op( A ) +* an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. +* +* Parameters +* ========== +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n', op( A ) = A. +* +* TRANSA = 'T' or 't', op( A ) = A'. +* +* TRANSA = 'C' or 'c', op( A ) = A'. +* +* Unchanged on exit. +* +* TRANSB - CHARACTER*1. +* On entry, TRANSB specifies the form of op( B ) to be used in +* the matrix multiplication as follows: +* +* TRANSB = 'N' or 'n', op( B ) = B. +* +* TRANSB = 'T' or 't', op( B ) = B'. +* +* TRANSB = 'C' or 'c', op( B ) = B'. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix +* op( A ) and of the matrix C. M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix +* op( B ) and the number of columns of the matrix C. N must be +* at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry, K specifies the number of columns of the matrix +* op( A ) and the number of rows of the matrix op( B ). K must +* be at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, ka ), where ka is +* k when TRANSA = 'N' or 'n', and is m otherwise. +* Before entry with TRANSA = 'N' or 'n', the leading m by k +* part of the array A must contain the matrix A, otherwise +* the leading k by m part of the array A must contain the +* matrix A. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When TRANSA = 'N' or 'n' then +* LDA must be at least max( 1, m ), otherwise LDA must be at +* least max( 1, k ). +* Unchanged on exit. +* +* B - REAL array of DIMENSION ( LDB, kb ), where kb is +* n when TRANSB = 'N' or 'n', and is k otherwise. +* Before entry with TRANSB = 'N' or 'n', the leading k by n +* part of the array B must contain the matrix B, otherwise +* the leading n by k part of the array B must contain the +* matrix B. +* Unchanged on exit. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. When TRANSB = 'N' or 'n' then +* LDB must be at least max( 1, k ), otherwise LDB must be at +* least max( 1, n ). +* Unchanged on exit. +* +* BETA - REAL . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then C need not be set on input. +* Unchanged on exit. +* +* C - REAL array of DIMENSION ( LDC, n ). +* Before entry, the leading m by n part of the array C must +* contain the matrix C, except when beta is zero, in which +* case C need not be set on entry. +* On exit, the array C is overwritten by the m by n matrix +* ( alpha*op( A )*op( B ) + beta*C ). +* +* LDC - INTEGER. +* On entry, LDC specifies the first dimension of C as declared +* in the calling (sub) program. LDC must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. Local Scalars .. + LOGICAL NOTA, NOTB + INTEGER I, INFO, J, L, NCOLA, NROWA, NROWB + REAL TEMP +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. +* .. Executable Statements .. +* +* Set NOTA and NOTB as true if A and B respectively are not +* transposed and set NROWA, NCOLA and NROWB as the number of rows +* and columns of A and the number of rows of B respectively. +* + NOTA = LSAME( TRANSA, 'N' ) + NOTB = LSAME( TRANSB, 'N' ) + IF( NOTA )THEN + NROWA = M + NCOLA = K + ELSE + NROWA = K + NCOLA = M + END IF + IF( NOTB )THEN + NROWB = K + ELSE + NROWB = N + END IF +* +* Test the input parameters. +* + INFO = 0 + IF( ( .NOT.NOTA ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.NOTB ).AND. + $ ( .NOT.LSAME( TRANSB, 'C' ) ).AND. + $ ( .NOT.LSAME( TRANSB, 'T' ) ) )THEN + INFO = 2 + ELSE IF( M .LT.0 )THEN + INFO = 3 + ELSE IF( N .LT.0 )THEN + INFO = 4 + ELSE IF( K .LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 8 + ELSE IF( LDB.LT.MAX( 1, NROWB ) )THEN + INFO = 10 + ELSE IF( LDC.LT.MAX( 1, M ) )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'SGEMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ( ALPHA.EQ.ZERO ).OR.( K.EQ.0 ) ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* And if alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + IF( BETA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + C( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40, J = 1, N + DO 30, I = 1, M + C( I, J ) = BETA*C( I, J ) + 30 CONTINUE + 40 CONTINUE + END IF + RETURN + END IF +* +* Start the operations. +* + IF( NOTB )THEN + IF( NOTA )THEN +* +* Form C := alpha*A*B + beta*C. +* + DO 90, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 50, I = 1, M + C( I, J ) = ZERO + 50 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 60, I = 1, M + C( I, J ) = BETA*C( I, J ) + 60 CONTINUE + END IF + DO 80, L = 1, K + IF( B( L, J ).NE.ZERO )THEN + TEMP = ALPHA*B( L, J ) + DO 70, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 70 CONTINUE + END IF + 80 CONTINUE + 90 CONTINUE + ELSE +* +* Form C := alpha*A'*B + beta*C +* + DO 120, J = 1, N + DO 110, I = 1, M + TEMP = ZERO + DO 100, L = 1, K + TEMP = TEMP + A( L, I )*B( L, J ) + 100 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 110 CONTINUE + 120 CONTINUE + END IF + ELSE + IF( NOTA )THEN +* +* Form C := alpha*A*B' + beta*C +* + DO 170, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 130, I = 1, M + C( I, J ) = ZERO + 130 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 140, I = 1, M + C( I, J ) = BETA*C( I, J ) + 140 CONTINUE + END IF + DO 160, L = 1, K + IF( B( J, L ).NE.ZERO )THEN + TEMP = ALPHA*B( J, L ) + DO 150, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 150 CONTINUE + END IF + 160 CONTINUE + 170 CONTINUE + ELSE +* +* Form C := alpha*A'*B' + beta*C +* + DO 200, J = 1, N + DO 190, I = 1, M + TEMP = ZERO + DO 180, L = 1, K + TEMP = TEMP + A( L, I )*B( J, L ) + 180 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 190 CONTINUE + 200 CONTINUE + END IF + END IF +* + RETURN +* +* End of SGEMM . +* + END diff --git a/dep/blas/sgemv.f b/dep/blas/sgemv.f new file mode 100644 index 00000000..4b47f047 --- /dev/null +++ b/dep/blas/sgemv.f @@ -0,0 +1,261 @@ + SUBROUTINE SGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + REAL ALPHA, BETA + INTEGER INCX, INCY, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + REAL A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* SGEMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n matrix. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*A'*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* X - REAL array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - REAL . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - REAL array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry with BETA non-zero, the incremented array Y +* must contain the vector y. On exit, Y is overwritten by the +* updated vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. Local Scalars .. + REAL TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY, LENX, LENY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 6 + ELSE IF( INCX.EQ.0 )THEN + INFO = 8 + ELSE IF( INCY.EQ.0 )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'SGEMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + DO 50, I = 1, M + Y( I ) = Y( I ) + TEMP*A( I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + DO 70, I = 1, M + Y( IY ) = Y( IY ) + TEMP*A( I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 100, J = 1, N + TEMP = ZERO + DO 90, I = 1, M + TEMP = TEMP + A( I, J )*X( I ) + 90 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 100 CONTINUE + ELSE + DO 120, J = 1, N + TEMP = ZERO + IX = KX + DO 110, I = 1, M + TEMP = TEMP + A( I, J )*X( IX ) + IX = IX + INCX + 110 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of SGEMV . +* + END diff --git a/dep/blas/sger.f b/dep/blas/sger.f new file mode 100644 index 00000000..f336b417 --- /dev/null +++ b/dep/blas/sger.f @@ -0,0 +1,157 @@ + SUBROUTINE SGER ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + REAL ALPHA + INTEGER INCX, INCY, LDA, M, N +* .. Array Arguments .. + REAL A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* SGER performs the rank 1 operation +* +* A := alpha*x*y' + A, +* +* where alpha is a scalar, x is an m element vector, y is an n element +* vector and A is an m by n matrix. +* +* Parameters +* ========== +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - REAL array of dimension at least +* ( 1 + ( m - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the m +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - REAL array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. On exit, A is +* overwritten by the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + REAL ZERO + PARAMETER ( ZERO = 0.0E+0 ) +* .. Local Scalars .. + REAL TEMP + INTEGER I, INFO, IX, J, JY, KX +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( M.LT.0 )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'SGER ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( INCY.GT.0 )THEN + JY = 1 + ELSE + JY = 1 - ( N - 1 )*INCY + END IF + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + DO 10, I = 1, M + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + END IF + JY = JY + INCY + 20 CONTINUE + ELSE + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( M - 1 )*INCX + END IF + DO 40, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + IX = KX + DO 30, I = 1, M + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + END IF + JY = JY + INCY + 40 CONTINUE + END IF +* + RETURN +* +* End of SGER . +* + END diff --git a/dep/blas/snrm2.f b/dep/blas/snrm2.f new file mode 100644 index 00000000..97147bfc --- /dev/null +++ b/dep/blas/snrm2.f @@ -0,0 +1,133 @@ + real function snrm2 ( n, sx, incx) + integer i, incx, ix, j, n, next + real sx(1), cutlo, cuthi, hitest, sum, xmax, zero, one + data zero, one /0.0e0, 1.0e0/ +c +c euclidean norm of the n-vector stored in sx() with storage +c increment incx . +c if n .le. 0 return with result = 0. +c if n .ge. 1 then incx must be .ge. 1 +c +c c.l.lawson, 1978 jan 08 +c modified to correct problem with negative increment, 8/21/90. +c +c four phase method using two built-in constants that are +c hopefully applicable to all machines. +c cutlo = maximum of sqrt(u/eps) over all known machines. +c cuthi = minimum of sqrt(v) over all known machines. +c where +c eps = smallest no. such that eps + 1. .gt. 1. +c u = smallest positive no. (underflow limit) +c v = largest no. (overflow limit) +c +c brief outline of algorithm.. +c +c phase 1 scans zero components. +c move to phase 2 when a component is nonzero and .le. cutlo +c move to phase 3 when a component is .gt. cutlo +c move to phase 4 when a component is .ge. cuthi/m +c where m = n for x() real and m = 2*n for complex. +c +c values for cutlo and cuthi.. +c from the environmental parameters listed in the imsl converter +c document the limiting values are as follows.. +c cutlo, s.p. u/eps = 2**(-102) for honeywell. close seconds are +c univac and dec at 2**(-103) +c thus cutlo = 2**(-51) = 4.44089e-16 +c cuthi, s.p. v = 2**127 for univac, honeywell, and dec. +c thus cuthi = 2**(63.5) = 1.30438e19 +c cutlo, d.p. u/eps = 2**(-67) for honeywell and dec. +c thus cutlo = 2**(-33.5) = 8.23181d-11 +c cuthi, d.p. same as s.p. cuthi = 1.30438d19 +c data cutlo, cuthi / 8.232d-11, 1.304d19 / +c data cutlo, cuthi / 4.441e-16, 1.304e19 / +c data cutlo, cuthi / 4.441e-16, 1.304e19 / +c... from Ed Anderson (for Cray) +c data cutlo / 0300315520236314774737b / +c data cuthi / 0500004000000000000000b / +c... from Ed Anderson (for Sun4) + data cutlo / 0.44408921E-15 / + data cuthi / 0.18446743E+20 / +c + if(n .gt. 0) go to 10 + snrm2 = zero + go to 300 +c + 10 assign 30 to next + sum = zero + i = 1 + if(incx.lt.0)i = (-n+1)*incx + 1 + ix = 1 +c begin main loop + 20 go to next,(30, 50, 70, 110) + 30 if( abs(sx(i)) .gt. cutlo) go to 85 + assign 50 to next + xmax = zero +c +c phase 1. sum is zero +c + 50 if( sx(i) .eq. zero) go to 200 + if( abs(sx(i)) .gt. cutlo) go to 85 +c +c prepare for phase 2. + assign 70 to next + go to 105 +c +c prepare for phase 4. +c + 100 continue + assign 110 to next + sum = (sum / sx(i)) / sx(i) + 105 xmax = abs(sx(i)) + go to 115 +c +c phase 2. sum is small. +c scale to avoid destructive underflow. +c + 70 if( abs(sx(i)) .gt. cutlo ) go to 75 +c +c common code for phases 2 and 4. +c in phase 4 sum is large. scale to avoid overflow. +c + 110 if( abs(sx(i)) .le. xmax ) go to 115 + sum = one + sum * (xmax / sx(i))**2 + xmax = abs(sx(i)) + go to 200 +c + 115 sum = sum + (sx(i)/xmax)**2 + go to 200 +c +c +c prepare for phase 3. +c + 75 sum = (sum * xmax) * xmax +c +c +c for real or d.p. set hitest = cuthi/n +c for complex set hitest = cuthi/(2*n) +c + 85 hitest = cuthi/float( n ) +c +c phase 3. sum is mid-range. no scaling. +c + do 95 j = ix, n + if(abs(sx(i)) .ge. hitest) go to 100 + sum = sum + sx(i)**2 + i = i + incx + 95 continue + snrm2 = sqrt( sum ) + go to 300 +c + 200 continue + ix = ix + 1 + i = i + incx + if( ix .le. n ) go to 20 +c +c end of main loop. +c +c compute square root and adjust for scaling. +c + snrm2 = xmax * sqrt(sum) + 300 continue + return + end diff --git a/dep/blas/srot.f b/dep/blas/srot.f new file mode 100644 index 00000000..4887afe3 --- /dev/null +++ b/dep/blas/srot.f @@ -0,0 +1,36 @@ + subroutine srot (n,sx,incx,sy,incy,c,s) +c +c applies a plane rotation. +c jack dongarra, linpack, 3/11/78. +c + real sx(1),sy(1),stemp,c,s + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments not equal +c to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + stemp = c*sx(ix) + s*sy(iy) + sy(iy) = c*sy(iy) - s*sx(ix) + sx(ix) = stemp + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + stemp = c*sx(i) + s*sy(i) + sy(i) = c*sy(i) - s*sx(i) + sx(i) = stemp + 30 continue + return + end diff --git a/dep/blas/srotg.f b/dep/blas/srotg.f new file mode 100644 index 00000000..84d1922a --- /dev/null +++ b/dep/blas/srotg.f @@ -0,0 +1,27 @@ + subroutine srotg(sa,sb,c,s) +c +c construct givens plane rotation. +c jack dongarra, linpack, 3/11/78. +c + real sa,sb,c,s,roe,scale,r,z +c + roe = sb + if( abs(sa) .gt. abs(sb) ) roe = sa + scale = abs(sa) + abs(sb) + if( scale .ne. 0.0 ) go to 10 + c = 1.0 + s = 0.0 + r = 0.0 + z = 0.0 + go to 20 + 10 r = scale*sqrt((sa/scale)**2 + (sb/scale)**2) + r = sign(1.0,roe)*r + c = sa/r + s = sb/r + z = 1.0 + if( abs(sa) .gt. abs(sb) ) z = s + if( abs(sb) .ge. abs(sa) .and. c .ne. 0.0 ) z = 1.0/c + 20 sa = r + sb = z + return + end diff --git a/dep/blas/sscal.f b/dep/blas/sscal.f new file mode 100644 index 00000000..f29d9cd1 --- /dev/null +++ b/dep/blas/sscal.f @@ -0,0 +1,44 @@ + subroutine sscal(n,sa,sx,incx) +c +c scales a vector by a constant. +c uses unrolled loops for increment equal to 1. +c jack dongarra, linpack, 3/11/78. +c modified to correct problem with negative increment, 8/21/90. +c + real sa,sx(1) + integer i,incx,ix,m,mp1,n +c + if(n.le.0)return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + do 10 i = 1,n + sx(ix) = sa*sx(ix) + ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,5) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + sx(i) = sa*sx(i) + 30 continue + if( n .lt. 5 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,5 + sx(i) = sa*sx(i) + sx(i + 1) = sa*sx(i + 1) + sx(i + 2) = sa*sx(i + 2) + sx(i + 3) = sa*sx(i + 3) + sx(i + 4) = sa*sx(i + 4) + 50 continue + return + end diff --git a/dep/blas/sswap.f b/dep/blas/sswap.f new file mode 100644 index 00000000..5bc79750 --- /dev/null +++ b/dep/blas/sswap.f @@ -0,0 +1,55 @@ + subroutine sswap (n,sx,incx,sy,incy) +c +c interchanges two vectors. +c uses unrolled loops for increments equal to 1. +c jack dongarra, linpack, 3/11/78. +c + real sx(1),sy(1),stemp + integer i,incx,incy,ix,iy,m,mp1,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments not equal +c to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + stemp = sx(ix) + sx(ix) = sy(iy) + sy(iy) = stemp + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c +c +c clean-up loop +c + 20 m = mod(n,3) + if( m .eq. 0 ) go to 40 + do 30 i = 1,m + stemp = sx(i) + sx(i) = sy(i) + sy(i) = stemp + 30 continue + if( n .lt. 3 ) return + 40 mp1 = m + 1 + do 50 i = mp1,n,3 + stemp = sx(i) + sx(i) = sy(i) + sy(i) = stemp + stemp = sx(i + 1) + sx(i + 1) = sy(i + 1) + sy(i + 1) = stemp + stemp = sx(i + 2) + sx(i + 2) = sy(i + 2) + sy(i + 2) = stemp + 50 continue + return + end diff --git a/dep/blas/ssymv.f b/dep/blas/ssymv.f new file mode 100644 index 00000000..9819ba80 --- /dev/null +++ b/dep/blas/ssymv.f @@ -0,0 +1,262 @@ + SUBROUTINE SSYMV ( UPLO, N, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + REAL ALPHA, BETA + INTEGER INCX, INCY, LDA, N + CHARACTER*1 UPLO +* .. Array Arguments .. + REAL A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* SSYMV performs the matrix-vector operation +* +* y := alpha*A*x + beta*y, +* +* where alpha and beta are scalars, x and y are n element vectors and +* A is an n by n symmetric matrix. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array A is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of A +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of A +* is to be referenced. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular part of the symmetric matrix and the strictly +* lower triangular part of A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular part of the symmetric matrix and the strictly +* upper triangular part of A is not referenced. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* X - REAL array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - REAL . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - REAL array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. On exit, Y is overwritten by the updated +* vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. Local Scalars .. + REAL TEMP1, TEMP2 + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO, 'U' ).AND. + $ .NOT.LSAME( UPLO, 'L' ) )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 5 + ELSE IF( INCX.EQ.0 )THEN + INFO = 7 + ELSE IF( INCY.EQ.0 )THEN + INFO = 10 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'SSYMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( N.EQ.0 ).OR.( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* Set up the start points in X and Y. +* + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( N - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( N - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the triangular part +* of A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, N + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, N + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, N + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, N + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + IF( LSAME( UPLO, 'U' ) )THEN +* +* Form y when A is stored in upper triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 60, J = 1, N + TEMP1 = ALPHA*X( J ) + TEMP2 = ZERO + DO 50, I = 1, J - 1 + Y( I ) = Y( I ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( I ) + 50 CONTINUE + Y( J ) = Y( J ) + TEMP1*A( J, J ) + ALPHA*TEMP2 + 60 CONTINUE + ELSE + JX = KX + JY = KY + DO 80, J = 1, N + TEMP1 = ALPHA*X( JX ) + TEMP2 = ZERO + IX = KX + IY = KY + DO 70, I = 1, J - 1 + Y( IY ) = Y( IY ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( IX ) + IX = IX + INCX + IY = IY + INCY + 70 CONTINUE + Y( JY ) = Y( JY ) + TEMP1*A( J, J ) + ALPHA*TEMP2 + JX = JX + INCX + JY = JY + INCY + 80 CONTINUE + END IF + ELSE +* +* Form y when A is stored in lower triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 100, J = 1, N + TEMP1 = ALPHA*X( J ) + TEMP2 = ZERO + Y( J ) = Y( J ) + TEMP1*A( J, J ) + DO 90, I = J + 1, N + Y( I ) = Y( I ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( I ) + 90 CONTINUE + Y( J ) = Y( J ) + ALPHA*TEMP2 + 100 CONTINUE + ELSE + JX = KX + JY = KY + DO 120, J = 1, N + TEMP1 = ALPHA*X( JX ) + TEMP2 = ZERO + Y( JY ) = Y( JY ) + TEMP1*A( J, J ) + IX = JX + IY = JY + DO 110, I = J + 1, N + IX = IX + INCX + IY = IY + INCY + Y( IY ) = Y( IY ) + TEMP1*A( I, J ) + TEMP2 = TEMP2 + A( I, J )*X( IX ) + 110 CONTINUE + Y( JY ) = Y( JY ) + ALPHA*TEMP2 + JX = JX + INCX + JY = JY + INCY + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of SSYMV . +* + END diff --git a/dep/blas/ssyr2.f b/dep/blas/ssyr2.f new file mode 100644 index 00000000..ac20fc9d --- /dev/null +++ b/dep/blas/ssyr2.f @@ -0,0 +1,230 @@ + SUBROUTINE SSYR2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + REAL ALPHA + INTEGER INCX, INCY, LDA, N + CHARACTER*1 UPLO +* .. Array Arguments .. + REAL A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* SSYR2 performs the symmetric rank 2 operation +* +* A := alpha*x*y' + alpha*y*x' + A, +* +* where alpha is a scalar, x and y are n element vectors and A is an n +* by n symmetric matrix. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the upper or lower +* triangular part of the array A is to be referenced as +* follows: +* +* UPLO = 'U' or 'u' Only the upper triangular part of A +* is to be referenced. +* +* UPLO = 'L' or 'l' Only the lower triangular part of A +* is to be referenced. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - REAL array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - REAL array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular part of the symmetric matrix and the strictly +* lower triangular part of A is not referenced. On exit, the +* upper triangular part of the array A is overwritten by the +* upper triangular part of the updated matrix. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular part of the symmetric matrix and the strictly +* upper triangular part of A is not referenced. On exit, the +* lower triangular part of the array A is overwritten by the +* lower triangular part of the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + REAL ZERO + PARAMETER ( ZERO = 0.0E+0 ) +* .. Local Scalars .. + REAL TEMP1, TEMP2 + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO, 'U' ).AND. + $ .NOT.LSAME( UPLO, 'L' ) )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'SSYR2 ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Set up the start points in X and Y if the increments are not both +* unity. +* + IF( ( INCX.NE.1 ).OR.( INCY.NE.1 ) )THEN + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( N - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( N - 1 )*INCY + END IF + JX = KX + JY = KY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the triangular part +* of A. +* + IF( LSAME( UPLO, 'U' ) )THEN +* +* Form A when A is stored in the upper triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 20, J = 1, N + IF( ( X( J ).NE.ZERO ).OR.( Y( J ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( J ) + TEMP2 = ALPHA*X( J ) + DO 10, I = 1, J + A( I, J ) = A( I, J ) + X( I )*TEMP1 + Y( I )*TEMP2 + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + DO 40, J = 1, N + IF( ( X( JX ).NE.ZERO ).OR.( Y( JY ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( JY ) + TEMP2 = ALPHA*X( JX ) + IX = KX + IY = KY + DO 30, I = 1, J + A( I, J ) = A( I, J ) + X( IX )*TEMP1 + $ + Y( IY )*TEMP2 + IX = IX + INCX + IY = IY + INCY + 30 CONTINUE + END IF + JX = JX + INCX + JY = JY + INCY + 40 CONTINUE + END IF + ELSE +* +* Form A when A is stored in the lower triangle. +* + IF( ( INCX.EQ.1 ).AND.( INCY.EQ.1 ) )THEN + DO 60, J = 1, N + IF( ( X( J ).NE.ZERO ).OR.( Y( J ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( J ) + TEMP2 = ALPHA*X( J ) + DO 50, I = J, N + A( I, J ) = A( I, J ) + X( I )*TEMP1 + Y( I )*TEMP2 + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( ( X( JX ).NE.ZERO ).OR.( Y( JY ).NE.ZERO ) )THEN + TEMP1 = ALPHA*Y( JY ) + TEMP2 = ALPHA*X( JX ) + IX = JX + IY = JY + DO 70, I = J, N + A( I, J ) = A( I, J ) + X( IX )*TEMP1 + $ + Y( IY )*TEMP2 + IX = IX + INCX + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + JY = JY + INCY + 80 CONTINUE + END IF + END IF +* + RETURN +* +* End of SSYR2 . +* + END diff --git a/dep/blas/stbsv.f b/dep/blas/stbsv.f new file mode 100644 index 00000000..96ebe26c --- /dev/null +++ b/dep/blas/stbsv.f @@ -0,0 +1,346 @@ + SUBROUTINE STBSV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, K, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + REAL A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* STBSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular band matrix, with ( k + 1 ) +* diagonals. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' A'*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with UPLO = 'U' or 'u', K specifies the number of +* super-diagonals of the matrix A. +* On entry with UPLO = 'L' or 'l', K specifies the number of +* sub-diagonals of the matrix A. +* K must satisfy 0 .le. K. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) +* by n part of the array A must contain the upper triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row +* ( k + 1 ) of the array, the first super-diagonal starting at +* position 2 in row k, and so on. The top left k by k triangle +* of the array A is not referenced. +* The following program segment will transfer an upper +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = K + 1 - J +* DO 10, I = MAX( 1, J - K ), J +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) +* by n part of the array A must contain the lower triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row 1 of +* the array, the first sub-diagonal starting at position 1 in +* row 2, and so on. The bottom right k by k triangle of the +* array A is not referenced. +* The following program segment will transfer a lower +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = 1 - J +* DO 10, I = J, MIN( N, J + K ) +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Note that when DIAG = 'U' or 'u' the elements of the array A +* corresponding to the diagonal elements of the matrix are not +* referenced, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( k + 1 ). +* Unchanged on exit. +* +* X - REAL array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + REAL ZERO + PARAMETER ( ZERO = 0.0E+0 ) +* .. Local Scalars .. + REAL TEMP + INTEGER I, INFO, IX, J, JX, KPLUS1, KX, L + LOGICAL NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( K.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( K + 1 ) )THEN + INFO = 7 + ELSE IF( INCX.EQ.0 )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'STBSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOUNIT = LSAME( DIAG, 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed by sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + L = KPLUS1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( KPLUS1, J ) + TEMP = X( J ) + DO 10, I = J - 1, MAX( 1, J - K ), -1 + X( I ) = X( I ) - TEMP*A( L + I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 40, J = N, 1, -1 + KX = KX - INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = KPLUS1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( KPLUS1, J ) + TEMP = X( JX ) + DO 30, I = J - 1, MAX( 1, J - K ), -1 + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX - INCX + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + L = 1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( 1, J ) + TEMP = X( J ) + DO 50, I = J + 1, MIN( N, J + K ) + X( I ) = X( I ) - TEMP*A( L + I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + KX = KX + INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = 1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( 1, J ) + TEMP = X( JX ) + DO 70, I = J + 1, MIN( N, J + K ) + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX + INCX + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A')*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 100, J = 1, N + TEMP = X( J ) + L = KPLUS1 - J + DO 90, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + X( J ) = TEMP + 100 CONTINUE + ELSE + JX = KX + DO 120, J = 1, N + TEMP = X( JX ) + IX = KX + L = KPLUS1 - J + DO 110, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX + INCX + 110 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + X( JX ) = TEMP + JX = JX + INCX + IF( J.GT.K ) + $ KX = KX + INCX + 120 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 140, J = N, 1, -1 + TEMP = X( J ) + L = 1 - J + DO 130, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( I ) + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + X( J ) = TEMP + 140 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 160, J = N, 1, -1 + TEMP = X( JX ) + IX = KX + L = 1 - J + DO 150, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX - INCX + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + X( JX ) = TEMP + JX = JX - INCX + IF( ( N - J ).GE.K ) + $ KX = KX - INCX + 160 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of STBSV . +* + END diff --git a/dep/blas/strmm.f b/dep/blas/strmm.f new file mode 100644 index 00000000..0cc51ffd --- /dev/null +++ b/dep/blas/strmm.f @@ -0,0 +1,355 @@ + SUBROUTINE STRMM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + REAL ALPHA +* .. Array Arguments .. + REAL A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* STRMM performs one of the matrix-matrix operations +* +* B := alpha*op( A )*B, or B := alpha*B*op( A ), +* +* where alpha is a scalar, B is an m by n matrix, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A'. +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) multiplies B from +* the left or right as follows: +* +* SIDE = 'L' or 'l' B := alpha*op( A )*B. +* +* SIDE = 'R' or 'r' B := alpha*B*op( A ). +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = A'. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - REAL array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the matrix B, and on exit is overwritten by the +* transformed matrix. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + REAL TEMP +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'STRMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*A*B. +* + IF( UPPER )THEN + DO 50, J = 1, N + DO 40, K = 1, M + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + DO 30, I = 1, K - 1 + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 30 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + B( K, J ) = TEMP + END IF + 40 CONTINUE + 50 CONTINUE + ELSE + DO 80, J = 1, N + DO 70 K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + B( K, J ) = TEMP + IF( NOUNIT ) + $ B( K, J ) = B( K, J )*A( K, K ) + DO 60, I = K + 1, M + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 60 CONTINUE + END IF + 70 CONTINUE + 80 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A'. +* + IF( UPPER )THEN + DO 110, J = 1, N + DO 100, I = M, 1, -1 + TEMP = B( I, J ) + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 90, K = 1, I - 1 + TEMP = TEMP + A( K, I )*B( K, J ) + 90 CONTINUE + B( I, J ) = ALPHA*TEMP + 100 CONTINUE + 110 CONTINUE + ELSE + DO 140, J = 1, N + DO 130, I = 1, M + TEMP = B( I, J ) + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 120, K = I + 1, M + TEMP = TEMP + A( K, I )*B( K, J ) + 120 CONTINUE + B( I, J ) = ALPHA*TEMP + 130 CONTINUE + 140 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*A. +* + IF( UPPER )THEN + DO 180, J = N, 1, -1 + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 150, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 150 CONTINUE + DO 170, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 160, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 160 CONTINUE + END IF + 170 CONTINUE + 180 CONTINUE + ELSE + DO 220, J = 1, N + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 190, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 190 CONTINUE + DO 210, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 200, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 200 CONTINUE + END IF + 210 CONTINUE + 220 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A'. +* + IF( UPPER )THEN + DO 260, K = 1, N + DO 240, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + TEMP = ALPHA*A( J, K ) + DO 230, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 230 CONTINUE + END IF + 240 CONTINUE + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + IF( TEMP.NE.ONE )THEN + DO 250, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 250 CONTINUE + END IF + 260 CONTINUE + ELSE + DO 300, K = N, 1, -1 + DO 280, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + TEMP = ALPHA*A( J, K ) + DO 270, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 270 CONTINUE + END IF + 280 CONTINUE + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + IF( TEMP.NE.ONE )THEN + DO 290, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 290 CONTINUE + END IF + 300 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of STRMM . +* + END diff --git a/dep/blas/strsm.f b/dep/blas/strsm.f new file mode 100644 index 00000000..1c80a7ae --- /dev/null +++ b/dep/blas/strsm.f @@ -0,0 +1,378 @@ + SUBROUTINE STRSM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + REAL ALPHA +* .. Array Arguments .. + REAL A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* STRSM solves one of the matrix equations +* +* op( A )*X = alpha*B, or X*op( A ) = alpha*B, +* +* where alpha is a scalar, X and B are m by n matrices, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A'. +* +* The matrix X is overwritten on B. +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) appears on the left +* or right of X as follows: +* +* SIDE = 'L' or 'l' op( A )*X = alpha*B. +* +* SIDE = 'R' or 'r' X*op( A ) = alpha*B. +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = A'. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - REAL . +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - REAL array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - REAL array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the right-hand side matrix B, and on exit is +* overwritten by the solution matrix X. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + REAL TEMP +* .. Parameters .. + REAL ONE , ZERO + PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'STRSM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*inv( A )*B. +* + IF( UPPER )THEN + DO 60, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 30, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 30 CONTINUE + END IF + DO 50, K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 40, I = 1, K - 1 + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 40 CONTINUE + END IF + 50 CONTINUE + 60 CONTINUE + ELSE + DO 100, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 70, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 70 CONTINUE + END IF + DO 90 K = 1, M + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 80, I = K + 1, M + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 80 CONTINUE + END IF + 90 CONTINUE + 100 CONTINUE + END IF + ELSE +* +* Form B := alpha*inv( A' )*B. +* + IF( UPPER )THEN + DO 130, J = 1, N + DO 120, I = 1, M + TEMP = ALPHA*B( I, J ) + DO 110, K = 1, I - 1 + TEMP = TEMP - A( K, I )*B( K, J ) + 110 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + B( I, J ) = TEMP + 120 CONTINUE + 130 CONTINUE + ELSE + DO 160, J = 1, N + DO 150, I = M, 1, -1 + TEMP = ALPHA*B( I, J ) + DO 140, K = I + 1, M + TEMP = TEMP - A( K, I )*B( K, J ) + 140 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + B( I, J ) = TEMP + 150 CONTINUE + 160 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*inv( A ). +* + IF( UPPER )THEN + DO 210, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 170, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 170 CONTINUE + END IF + DO 190, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + DO 180, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 180 CONTINUE + END IF + 190 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 200, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 200 CONTINUE + END IF + 210 CONTINUE + ELSE + DO 260, J = N, 1, -1 + IF( ALPHA.NE.ONE )THEN + DO 220, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 220 CONTINUE + END IF + DO 240, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + DO 230, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 230 CONTINUE + END IF + 240 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 250, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 250 CONTINUE + END IF + 260 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*inv( A' ). +* + IF( UPPER )THEN + DO 310, K = N, 1, -1 + IF( NOUNIT )THEN + TEMP = ONE/A( K, K ) + DO 270, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 270 CONTINUE + END IF + DO 290, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + TEMP = A( J, K ) + DO 280, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 280 CONTINUE + END IF + 290 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 300, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 300 CONTINUE + END IF + 310 CONTINUE + ELSE + DO 360, K = 1, N + IF( NOUNIT )THEN + TEMP = ONE/A( K, K ) + DO 320, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 320 CONTINUE + END IF + DO 340, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + TEMP = A( J, K ) + DO 330, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 330 CONTINUE + END IF + 340 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 350, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 350 CONTINUE + END IF + 360 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of STRSM . +* + END diff --git a/dep/blas/xerbla.f b/dep/blas/xerbla.f new file mode 100644 index 00000000..3a84150e --- /dev/null +++ b/dep/blas/xerbla.f @@ -0,0 +1,48 @@ + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- LAPACK auxiliary routine (preliminary version) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* Purpose +* ======= +* +* XERBLA is an error handler for the LAPACK routines. +* It is called by an LAPACK routine if an input parameter has an +* invalid value. A message is printed and execution stops. +* +* Installers may consider modifying the STOP statement in order to +* call system-specific exception-handling facilities. +* +* Arguments +* ========= +* +* SRNAME (input) CHARACTER*(*) +* The name of the routine which called XERBLA. +* +* INFO (input) INTEGER +* The position of the invalid parameter in the parameter list +* of the calling routine. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/dep/blas/zaxpy.f b/dep/blas/zaxpy.f new file mode 100644 index 00000000..4fa3b1e4 --- /dev/null +++ b/dep/blas/zaxpy.f @@ -0,0 +1,34 @@ + subroutine zaxpy(n,za,zx,incx,zy,incy) +c +c constant times a vector plus a vector. +c jack dongarra, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*),zy(*),za + integer i,incx,incy,ix,iy,n + double precision dcabs1 + if(n.le.0)return + if (dcabs1(za) .eq. 0.0d0) return + if (incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + zy(iy) = zy(iy) + za*zx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + zy(i) = zy(i) + za*zx(i) + 30 continue + return + end diff --git a/dep/blas/zcopy.f b/dep/blas/zcopy.f new file mode 100644 index 00000000..9ccfa880 --- /dev/null +++ b/dep/blas/zcopy.f @@ -0,0 +1,33 @@ + subroutine zcopy(n,zx,incx,zy,incy) +c +c copies a vector, x, to a vector, y. +c jack dongarra, linpack, 4/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*),zy(*) + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + zy(iy) = zx(ix) + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + zy(i) = zx(i) + 30 continue + return + end diff --git a/dep/blas/zdotc.f b/dep/blas/zdotc.f new file mode 100644 index 00000000..d6ac6853 --- /dev/null +++ b/dep/blas/zdotc.f @@ -0,0 +1,36 @@ + double complex function zdotc(n,zx,incx,zy,incy) +c +c forms the dot product of a vector. +c jack dongarra, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*),zy(*),ztemp + integer i,incx,incy,ix,iy,n + ztemp = (0.0d0,0.0d0) + zdotc = (0.0d0,0.0d0) + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + ztemp = ztemp + dconjg(zx(ix))*zy(iy) + ix = ix + incx + iy = iy + incy + 10 continue + zdotc = ztemp + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + ztemp = ztemp + dconjg(zx(i))*zy(i) + 30 continue + zdotc = ztemp + return + end diff --git a/dep/blas/zdotu.f b/dep/blas/zdotu.f new file mode 100644 index 00000000..329e9885 --- /dev/null +++ b/dep/blas/zdotu.f @@ -0,0 +1,36 @@ + double complex function zdotu(n,zx,incx,zy,incy) +c +c forms the dot product of two vectors. +c jack dongarra, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*),zy(*),ztemp + integer i,incx,incy,ix,iy,n + ztemp = (0.0d0,0.0d0) + zdotu = (0.0d0,0.0d0) + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments +c not equal to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + ztemp = ztemp + zx(ix)*zy(iy) + ix = ix + incx + iy = iy + incy + 10 continue + zdotu = ztemp + return +c +c code for both increments equal to 1 +c + 20 do 30 i = 1,n + ztemp = ztemp + zx(i)*zy(i) + 30 continue + zdotu = ztemp + return + end diff --git a/dep/blas/zdscal.f b/dep/blas/zdscal.f new file mode 100644 index 00000000..8123424d --- /dev/null +++ b/dep/blas/zdscal.f @@ -0,0 +1,30 @@ + subroutine zdscal(n,da,zx,incx) +c +c scales a vector by a constant. +c jack dongarra, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*) + double precision da + integer i,incx,ix,n +c + if( n.le.0 .or. incx.le.0 )return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + do 10 i = 1,n + zx(ix) = dcmplx(da,0.0d0)*zx(ix) + ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c + 20 do 30 i = 1,n + zx(i) = dcmplx(da,0.0d0)*zx(i) + 30 continue + return + end diff --git a/dep/blas/zgbmv.f b/dep/blas/zgbmv.f new file mode 100644 index 00000000..91ce9a60 --- /dev/null +++ b/dep/blas/zgbmv.f @@ -0,0 +1,322 @@ + SUBROUTINE ZGBMV ( TRANS, M, N, KL, KU, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + COMPLEX*16 ALPHA, BETA + INTEGER INCX, INCY, KL, KU, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* ZGBMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, or +* +* y := alpha*conjg( A' )*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n band matrix, with kl sub-diagonals and ku super-diagonals. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*conjg( A' )*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* KL - INTEGER. +* On entry, KL specifies the number of sub-diagonals of the +* matrix A. KL must satisfy 0 .le. KL. +* Unchanged on exit. +* +* KU - INTEGER. +* On entry, KU specifies the number of super-diagonals of the +* matrix A. KU must satisfy 0 .le. KU. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry, the leading ( kl + ku + 1 ) by n part of the +* array A must contain the matrix of coefficients, supplied +* column by column, with the leading diagonal of the matrix in +* row ( ku + 1 ) of the array, the first super-diagonal +* starting at position 2 in row ku, the first sub-diagonal +* starting at position 1 in row ( ku + 2 ), and so on. +* Elements in the array A that do not correspond to elements +* in the band matrix (such as the top left ku by ku triangle) +* are not referenced. +* The following program segment will transfer a band matrix +* from conventional full matrix storage to band storage: +* +* DO 20, J = 1, N +* K = KU + 1 - J +* DO 10, I = MAX( 1, J - KU ), MIN( M, J + KL ) +* A( K + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( kl + ku + 1 ). +* Unchanged on exit. +* +* X - COMPLEX*16 array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - COMPLEX*16 . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - COMPLEX*16 array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry, the incremented array Y must contain the +* vector y. On exit, Y is overwritten by the updated vector y. +* +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, K, KUP1, KX, KY, + $ LENX, LENY + LOGICAL NOCONJ +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( KL.LT.0 )THEN + INFO = 4 + ELSE IF( KU.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( KL + KU + 1 ) )THEN + INFO = 8 + ELSE IF( INCX.EQ.0 )THEN + INFO = 10 + ELSE IF( INCY.EQ.0 )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZGBMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through the band part of A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + KUP1 = KU + 1 + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + K = KUP1 - J + DO 50, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( I ) = Y( I ) + TEMP*A( K + I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + K = KUP1 - J + DO 70, I = MAX( 1, J - KU ), MIN( M, J + KL ) + Y( IY ) = Y( IY ) + TEMP*A( K + I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + IF( J.GT.KU ) + $ KY = KY + INCY + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y or y := alpha*conjg( A' )*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = ZERO + K = KUP1 - J + IF( NOCONJ )THEN + DO 90, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( I ) + 90 CONTINUE + ELSE + DO 100, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + DCONJG( A( K + I, J ) )*X( I ) + 100 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 110 CONTINUE + ELSE + DO 140, J = 1, N + TEMP = ZERO + IX = KX + K = KUP1 - J + IF( NOCONJ )THEN + DO 120, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + A( K + I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + ELSE + DO 130, I = MAX( 1, J - KU ), MIN( M, J + KL ) + TEMP = TEMP + DCONJG( A( K + I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + IF( J.GT.KU ) + $ KX = KX + INCX + 140 CONTINUE + END IF + END IF +* + RETURN +* +* End of ZGBMV . +* + END diff --git a/dep/blas/zgemm.f b/dep/blas/zgemm.f new file mode 100644 index 00000000..09cd151e --- /dev/null +++ b/dep/blas/zgemm.f @@ -0,0 +1,415 @@ + SUBROUTINE ZGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, + $ BETA, C, LDC ) +* .. Scalar Arguments .. + CHARACTER*1 TRANSA, TRANSB + INTEGER M, N, K, LDA, LDB, LDC + COMPLEX*16 ALPHA, BETA +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), B( LDB, * ), C( LDC, * ) +* .. +* +* Purpose +* ======= +* +* ZGEMM performs one of the matrix-matrix operations +* +* C := alpha*op( A )*op( B ) + beta*C, +* +* where op( X ) is one of +* +* op( X ) = X or op( X ) = X' or op( X ) = conjg( X' ), +* +* alpha and beta are scalars, and A, B and C are matrices, with op( A ) +* an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. +* +* Parameters +* ========== +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n', op( A ) = A. +* +* TRANSA = 'T' or 't', op( A ) = A'. +* +* TRANSA = 'C' or 'c', op( A ) = conjg( A' ). +* +* Unchanged on exit. +* +* TRANSB - CHARACTER*1. +* On entry, TRANSB specifies the form of op( B ) to be used in +* the matrix multiplication as follows: +* +* TRANSB = 'N' or 'n', op( B ) = B. +* +* TRANSB = 'T' or 't', op( B ) = B'. +* +* TRANSB = 'C' or 'c', op( B ) = conjg( B' ). +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix +* op( A ) and of the matrix C. M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix +* op( B ) and the number of columns of the matrix C. N must be +* at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry, K specifies the number of columns of the matrix +* op( A ) and the number of rows of the matrix op( B ). K must +* be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, ka ), where ka is +* k when TRANSA = 'N' or 'n', and is m otherwise. +* Before entry with TRANSA = 'N' or 'n', the leading m by k +* part of the array A must contain the matrix A, otherwise +* the leading k by m part of the array A must contain the +* matrix A. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When TRANSA = 'N' or 'n' then +* LDA must be at least max( 1, m ), otherwise LDA must be at +* least max( 1, k ). +* Unchanged on exit. +* +* B - COMPLEX*16 array of DIMENSION ( LDB, kb ), where kb is +* n when TRANSB = 'N' or 'n', and is k otherwise. +* Before entry with TRANSB = 'N' or 'n', the leading k by n +* part of the array B must contain the matrix B, otherwise +* the leading n by k part of the array B must contain the +* matrix B. +* Unchanged on exit. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. When TRANSB = 'N' or 'n' then +* LDB must be at least max( 1, k ), otherwise LDB must be at +* least max( 1, n ). +* Unchanged on exit. +* +* BETA - COMPLEX*16 . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then C need not be set on input. +* Unchanged on exit. +* +* C - COMPLEX*16 array of DIMENSION ( LDC, n ). +* Before entry, the leading m by n part of the array C must +* contain the matrix C, except when beta is zero, in which +* case C need not be set on entry. +* On exit, the array C is overwritten by the m by n matrix +* ( alpha*op( A )*op( B ) + beta*C ). +* +* LDC - INTEGER. +* On entry, LDC specifies the first dimension of C as declared +* in the calling (sub) program. LDC must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. Local Scalars .. + LOGICAL CONJA, CONJB, NOTA, NOTB + INTEGER I, INFO, J, L, NCOLA, NROWA, NROWB + COMPLEX*16 TEMP +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Executable Statements .. +* +* Set NOTA and NOTB as true if A and B respectively are not +* conjugated or transposed, set CONJA and CONJB as true if A and +* B respectively are to be transposed but not conjugated and set +* NROWA, NCOLA and NROWB as the number of rows and columns of A +* and the number of rows of B respectively. +* + NOTA = LSAME( TRANSA, 'N' ) + NOTB = LSAME( TRANSB, 'N' ) + CONJA = LSAME( TRANSA, 'C' ) + CONJB = LSAME( TRANSB, 'C' ) + IF( NOTA )THEN + NROWA = M + NCOLA = K + ELSE + NROWA = K + NCOLA = M + END IF + IF( NOTB )THEN + NROWB = K + ELSE + NROWB = N + END IF +* +* Test the input parameters. +* + INFO = 0 + IF( ( .NOT.NOTA ).AND. + $ ( .NOT.CONJA ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.NOTB ).AND. + $ ( .NOT.CONJB ).AND. + $ ( .NOT.LSAME( TRANSB, 'T' ) ) )THEN + INFO = 2 + ELSE IF( M .LT.0 )THEN + INFO = 3 + ELSE IF( N .LT.0 )THEN + INFO = 4 + ELSE IF( K .LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 8 + ELSE IF( LDB.LT.MAX( 1, NROWB ) )THEN + INFO = 10 + ELSE IF( LDC.LT.MAX( 1, M ) )THEN + INFO = 13 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZGEMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ( ALPHA.EQ.ZERO ).OR.( K.EQ.0 ) ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + IF( BETA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + C( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40, J = 1, N + DO 30, I = 1, M + C( I, J ) = BETA*C( I, J ) + 30 CONTINUE + 40 CONTINUE + END IF + RETURN + END IF +* +* Start the operations. +* + IF( NOTB )THEN + IF( NOTA )THEN +* +* Form C := alpha*A*B + beta*C. +* + DO 90, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 50, I = 1, M + C( I, J ) = ZERO + 50 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 60, I = 1, M + C( I, J ) = BETA*C( I, J ) + 60 CONTINUE + END IF + DO 80, L = 1, K + IF( B( L, J ).NE.ZERO )THEN + TEMP = ALPHA*B( L, J ) + DO 70, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 70 CONTINUE + END IF + 80 CONTINUE + 90 CONTINUE + ELSE IF( CONJA )THEN +* +* Form C := alpha*conjg( A' )*B + beta*C. +* + DO 120, J = 1, N + DO 110, I = 1, M + TEMP = ZERO + DO 100, L = 1, K + TEMP = TEMP + DCONJG( A( L, I ) )*B( L, J ) + 100 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 110 CONTINUE + 120 CONTINUE + ELSE +* +* Form C := alpha*A'*B + beta*C +* + DO 150, J = 1, N + DO 140, I = 1, M + TEMP = ZERO + DO 130, L = 1, K + TEMP = TEMP + A( L, I )*B( L, J ) + 130 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 140 CONTINUE + 150 CONTINUE + END IF + ELSE IF( NOTA )THEN + IF( CONJB )THEN +* +* Form C := alpha*A*conjg( B' ) + beta*C. +* + DO 200, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 160, I = 1, M + C( I, J ) = ZERO + 160 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 170, I = 1, M + C( I, J ) = BETA*C( I, J ) + 170 CONTINUE + END IF + DO 190, L = 1, K + IF( B( J, L ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( B( J, L ) ) + DO 180, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 180 CONTINUE + END IF + 190 CONTINUE + 200 CONTINUE + ELSE +* +* Form C := alpha*A*B' + beta*C +* + DO 250, J = 1, N + IF( BETA.EQ.ZERO )THEN + DO 210, I = 1, M + C( I, J ) = ZERO + 210 CONTINUE + ELSE IF( BETA.NE.ONE )THEN + DO 220, I = 1, M + C( I, J ) = BETA*C( I, J ) + 220 CONTINUE + END IF + DO 240, L = 1, K + IF( B( J, L ).NE.ZERO )THEN + TEMP = ALPHA*B( J, L ) + DO 230, I = 1, M + C( I, J ) = C( I, J ) + TEMP*A( I, L ) + 230 CONTINUE + END IF + 240 CONTINUE + 250 CONTINUE + END IF + ELSE IF( CONJA )THEN + IF( CONJB )THEN +* +* Form C := alpha*conjg( A' )*conjg( B' ) + beta*C. +* + DO 280, J = 1, N + DO 270, I = 1, M + TEMP = ZERO + DO 260, L = 1, K + TEMP = TEMP + + $ DCONJG( A( L, I ) )*DCONJG( B( J, L ) ) + 260 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 270 CONTINUE + 280 CONTINUE + ELSE +* +* Form C := alpha*conjg( A' )*B' + beta*C +* + DO 310, J = 1, N + DO 300, I = 1, M + TEMP = ZERO + DO 290, L = 1, K + TEMP = TEMP + DCONJG( A( L, I ) )*B( J, L ) + 290 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 300 CONTINUE + 310 CONTINUE + END IF + ELSE + IF( CONJB )THEN +* +* Form C := alpha*A'*conjg( B' ) + beta*C +* + DO 340, J = 1, N + DO 330, I = 1, M + TEMP = ZERO + DO 320, L = 1, K + TEMP = TEMP + A( L, I )*DCONJG( B( J, L ) ) + 320 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 330 CONTINUE + 340 CONTINUE + ELSE +* +* Form C := alpha*A'*B' + beta*C +* + DO 370, J = 1, N + DO 360, I = 1, M + TEMP = ZERO + DO 350, L = 1, K + TEMP = TEMP + A( L, I )*B( J, L ) + 350 CONTINUE + IF( BETA.EQ.ZERO )THEN + C( I, J ) = ALPHA*TEMP + ELSE + C( I, J ) = ALPHA*TEMP + BETA*C( I, J ) + END IF + 360 CONTINUE + 370 CONTINUE + END IF + END IF +* + RETURN +* +* End of ZGEMM . +* + END diff --git a/dep/blas/zgemv.f b/dep/blas/zgemv.f new file mode 100644 index 00000000..014a5e02 --- /dev/null +++ b/dep/blas/zgemv.f @@ -0,0 +1,281 @@ + SUBROUTINE ZGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, + $ BETA, Y, INCY ) +* .. Scalar Arguments .. + COMPLEX*16 ALPHA, BETA + INTEGER INCX, INCY, LDA, M, N + CHARACTER*1 TRANS +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* ZGEMV performs one of the matrix-vector operations +* +* y := alpha*A*x + beta*y, or y := alpha*A'*x + beta*y, or +* +* y := alpha*conjg( A' )*x + beta*y, +* +* where alpha and beta are scalars, x and y are vectors and A is an +* m by n matrix. +* +* Parameters +* ========== +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +* +* TRANS = 'T' or 't' y := alpha*A'*x + beta*y. +* +* TRANS = 'C' or 'c' y := alpha*conjg( A' )*x + beta*y. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* X - COMPLEX*16 array of DIMENSION at least +* ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +* Before entry, the incremented array X must contain the +* vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* BETA - COMPLEX*16 . +* On entry, BETA specifies the scalar beta. When BETA is +* supplied as zero then Y need not be set on input. +* Unchanged on exit. +* +* Y - COMPLEX*16 array of DIMENSION at least +* ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +* and at least +* ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +* Before entry with BETA non-zero, the incremented array Y +* must contain the vector y. On exit, Y is overwritten by the +* updated vector y. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, IY, J, JX, JY, KX, KY, LENX, LENY + LOGICAL NOCONJ +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 1 + ELSE IF( M.LT.0 )THEN + INFO = 2 + ELSE IF( N.LT.0 )THEN + INFO = 3 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 6 + ELSE IF( INCX.EQ.0 )THEN + INFO = 8 + ELSE IF( INCY.EQ.0 )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZGEMV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR. + $ ( ( ALPHA.EQ.ZERO ).AND.( BETA.EQ.ONE ) ) ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF( LSAME( TRANS, 'N' ) )THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( LENX - 1 )*INCX + END IF + IF( INCY.GT.0 )THEN + KY = 1 + ELSE + KY = 1 - ( LENY - 1 )*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* +* First form y := beta*y. +* + IF( BETA.NE.ONE )THEN + IF( INCY.EQ.1 )THEN + IF( BETA.EQ.ZERO )THEN + DO 10, I = 1, LENY + Y( I ) = ZERO + 10 CONTINUE + ELSE + DO 20, I = 1, LENY + Y( I ) = BETA*Y( I ) + 20 CONTINUE + END IF + ELSE + IY = KY + IF( BETA.EQ.ZERO )THEN + DO 30, I = 1, LENY + Y( IY ) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40, I = 1, LENY + Y( IY ) = BETA*Y( IY ) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF( ALPHA.EQ.ZERO ) + $ RETURN + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF( INCY.EQ.1 )THEN + DO 60, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + DO 50, I = 1, M + Y( I ) = Y( I ) + TEMP*A( I, J ) + 50 CONTINUE + END IF + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + TEMP = ALPHA*X( JX ) + IY = KY + DO 70, I = 1, M + Y( IY ) = Y( IY ) + TEMP*A( I, J ) + IY = IY + INCY + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A'*x + y or y := alpha*conjg( A' )*x + y. +* + JY = KY + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = ZERO + IF( NOCONJ )THEN + DO 90, I = 1, M + TEMP = TEMP + A( I, J )*X( I ) + 90 CONTINUE + ELSE + DO 100, I = 1, M + TEMP = TEMP + DCONJG( A( I, J ) )*X( I ) + 100 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 110 CONTINUE + ELSE + DO 140, J = 1, N + TEMP = ZERO + IX = KX + IF( NOCONJ )THEN + DO 120, I = 1, M + TEMP = TEMP + A( I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + ELSE + DO 130, I = 1, M + TEMP = TEMP + DCONJG( A( I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + END IF + Y( JY ) = Y( JY ) + ALPHA*TEMP + JY = JY + INCY + 140 CONTINUE + END IF + END IF +* + RETURN +* +* End of ZGEMV . +* + END diff --git a/dep/blas/zgerc.f b/dep/blas/zgerc.f new file mode 100644 index 00000000..968c5b47 --- /dev/null +++ b/dep/blas/zgerc.f @@ -0,0 +1,157 @@ + SUBROUTINE ZGERC ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + COMPLEX*16 ALPHA + INTEGER INCX, INCY, LDA, M, N +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* ZGERC performs the rank 1 operation +* +* A := alpha*x*conjg( y' ) + A, +* +* where alpha is a scalar, x is an m element vector, y is an n element +* vector and A is an m by n matrix. +* +* Parameters +* ========== +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( m - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the m +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. On exit, A is +* overwritten by the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, J, JY, KX +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( M.LT.0 )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZGERC ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( INCY.GT.0 )THEN + JY = 1 + ELSE + JY = 1 - ( N - 1 )*INCY + END IF + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( Y( JY ) ) + DO 10, I = 1, M + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + END IF + JY = JY + INCY + 20 CONTINUE + ELSE + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( M - 1 )*INCX + END IF + DO 40, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*DCONJG( Y( JY ) ) + IX = KX + DO 30, I = 1, M + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + END IF + JY = JY + INCY + 40 CONTINUE + END IF +* + RETURN +* +* End of ZGERC . +* + END diff --git a/dep/blas/zgeru.f b/dep/blas/zgeru.f new file mode 100644 index 00000000..5283af64 --- /dev/null +++ b/dep/blas/zgeru.f @@ -0,0 +1,157 @@ + SUBROUTINE ZGERU ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) +* .. Scalar Arguments .. + COMPLEX*16 ALPHA + INTEGER INCX, INCY, LDA, M, N +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* ZGERU performs the rank 1 operation +* +* A := alpha*x*y' + A, +* +* where alpha is a scalar, x is an m element vector, y is an n element +* vector and A is an m by n matrix. +* +* Parameters +* ========== +* +* M - INTEGER. +* On entry, M specifies the number of rows of the matrix A. +* M must be at least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( m - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the m +* element vector x. +* Unchanged on exit. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* Y - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCY ) ). +* Before entry, the incremented array Y must contain the n +* element vector y. +* Unchanged on exit. +* +* INCY - INTEGER. +* On entry, INCY specifies the increment for the elements of +* Y. INCY must not be zero. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry, the leading m by n part of the array A must +* contain the matrix of coefficients. On exit, A is +* overwritten by the updated matrix. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, J, JY, KX +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( M.LT.0 )THEN + INFO = 1 + ELSE IF( N.LT.0 )THEN + INFO = 2 + ELSE IF( INCX.EQ.0 )THEN + INFO = 5 + ELSE IF( INCY.EQ.0 )THEN + INFO = 7 + ELSE IF( LDA.LT.MAX( 1, M ) )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZGERU ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( ( M.EQ.0 ).OR.( N.EQ.0 ).OR.( ALPHA.EQ.ZERO ) ) + $ RETURN +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( INCY.GT.0 )THEN + JY = 1 + ELSE + JY = 1 - ( N - 1 )*INCY + END IF + IF( INCX.EQ.1 )THEN + DO 20, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + DO 10, I = 1, M + A( I, J ) = A( I, J ) + X( I )*TEMP + 10 CONTINUE + END IF + JY = JY + INCY + 20 CONTINUE + ELSE + IF( INCX.GT.0 )THEN + KX = 1 + ELSE + KX = 1 - ( M - 1 )*INCX + END IF + DO 40, J = 1, N + IF( Y( JY ).NE.ZERO )THEN + TEMP = ALPHA*Y( JY ) + IX = KX + DO 30, I = 1, M + A( I, J ) = A( I, J ) + X( IX )*TEMP + IX = IX + INCX + 30 CONTINUE + END IF + JY = JY + INCY + 40 CONTINUE + END IF +* + RETURN +* +* End of ZGERU . +* + END diff --git a/dep/blas/zscal.f b/dep/blas/zscal.f new file mode 100644 index 00000000..6fa85763 --- /dev/null +++ b/dep/blas/zscal.f @@ -0,0 +1,29 @@ + subroutine zscal(n,za,zx,incx) +c +c scales a vector by a constant. +c jack dongarra, 3/11/78. +c modified 3/93 to return if incx .le. 0. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex za,zx(*) + integer i,incx,ix,n +c + if( n.le.0 .or. incx.le.0 )return + if(incx.eq.1)go to 20 +c +c code for increment not equal to 1 +c + ix = 1 + do 10 i = 1,n + zx(ix) = za*zx(ix) + ix = ix + incx + 10 continue + return +c +c code for increment equal to 1 +c + 20 do 30 i = 1,n + zx(i) = za*zx(i) + 30 continue + return + end diff --git a/dep/blas/zswap.f b/dep/blas/zswap.f new file mode 100644 index 00000000..f28a4e41 --- /dev/null +++ b/dep/blas/zswap.f @@ -0,0 +1,36 @@ + subroutine zswap (n,zx,incx,zy,incy) +c +c interchanges two vectors. +c jack dongarra, 3/11/78. +c modified 12/3/93, array(1) declarations changed to array(*) +c + double complex zx(*),zy(*),ztemp + integer i,incx,incy,ix,iy,n +c + if(n.le.0)return + if(incx.eq.1.and.incy.eq.1)go to 20 +c +c code for unequal increments or equal increments not equal +c to 1 +c + ix = 1 + iy = 1 + if(incx.lt.0)ix = (-n+1)*incx + 1 + if(incy.lt.0)iy = (-n+1)*incy + 1 + do 10 i = 1,n + ztemp = zx(ix) + zx(ix) = zy(iy) + zy(iy) = ztemp + ix = ix + incx + iy = iy + incy + 10 continue + return +c +c code for both increments equal to 1 + 20 do 30 i = 1,n + ztemp = zx(i) + zx(i) = zy(i) + zy(i) = ztemp + 30 continue + return + end diff --git a/dep/blas/ztbsv.f b/dep/blas/ztbsv.f new file mode 100644 index 00000000..f3ded819 --- /dev/null +++ b/dep/blas/ztbsv.f @@ -0,0 +1,381 @@ + SUBROUTINE ZTBSV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, K, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* ZTBSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, or conjg( A' )*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular band matrix, with ( k + 1 ) +* diagonals. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' conjg( A' )*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* K - INTEGER. +* On entry with UPLO = 'U' or 'u', K specifies the number of +* super-diagonals of the matrix A. +* On entry with UPLO = 'L' or 'l', K specifies the number of +* sub-diagonals of the matrix A. +* K must satisfy 0 .le. K. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading ( k + 1 ) +* by n part of the array A must contain the upper triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row +* ( k + 1 ) of the array, the first super-diagonal starting at +* position 2 in row k, and so on. The top left k by k triangle +* of the array A is not referenced. +* The following program segment will transfer an upper +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = K + 1 - J +* DO 10, I = MAX( 1, J - K ), J +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Before entry with UPLO = 'L' or 'l', the leading ( k + 1 ) +* by n part of the array A must contain the lower triangular +* band part of the matrix of coefficients, supplied column by +* column, with the leading diagonal of the matrix in row 1 of +* the array, the first sub-diagonal starting at position 1 in +* row 2, and so on. The bottom right k by k triangle of the +* array A is not referenced. +* The following program segment will transfer a lower +* triangular band matrix from conventional full matrix storage +* to band storage: +* +* DO 20, J = 1, N +* M = 1 - J +* DO 10, I = J, MIN( N, J + K ) +* A( M + I, J ) = matrix( I, J ) +* 10 CONTINUE +* 20 CONTINUE +* +* Note that when DIAG = 'U' or 'u' the elements of the array A +* corresponding to the diagonal elements of the matrix are not +* referenced, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* ( k + 1 ). +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, J, JX, KPLUS1, KX, L + LOGICAL NOCONJ, NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( K.LT.0 )THEN + INFO = 5 + ELSE IF( LDA.LT.( K + 1 ) )THEN + INFO = 7 + ELSE IF( INCX.EQ.0 )THEN + INFO = 9 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZTBSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed by sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + L = KPLUS1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( KPLUS1, J ) + TEMP = X( J ) + DO 10, I = J - 1, MAX( 1, J - K ), -1 + X( I ) = X( I ) - TEMP*A( L + I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 40, J = N, 1, -1 + KX = KX - INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = KPLUS1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( KPLUS1, J ) + TEMP = X( JX ) + DO 30, I = J - 1, MAX( 1, J - K ), -1 + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX - INCX + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + L = 1 - J + IF( NOUNIT ) + $ X( J ) = X( J )/A( 1, J ) + TEMP = X( J ) + DO 50, I = J + 1, MIN( N, J + K ) + X( I ) = X( I ) - TEMP*A( L + I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + KX = KX + INCX + IF( X( JX ).NE.ZERO )THEN + IX = KX + L = 1 - J + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( 1, J ) + TEMP = X( JX ) + DO 70, I = J + 1, MIN( N, J + K ) + X( IX ) = X( IX ) - TEMP*A( L + I, J ) + IX = IX + INCX + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A' )*x or x := inv( conjg( A') )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + KPLUS1 = K + 1 + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = X( J ) + L = KPLUS1 - J + IF( NOCONJ )THEN + DO 90, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + ELSE + DO 100, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( I ) + 100 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( KPLUS1, J ) ) + END IF + X( J ) = TEMP + 110 CONTINUE + ELSE + JX = KX + DO 140, J = 1, N + TEMP = X( JX ) + IX = KX + L = KPLUS1 - J + IF( NOCONJ )THEN + DO 120, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( KPLUS1, J ) + ELSE + DO 130, I = MAX( 1, J - K ), J - 1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( KPLUS1, J ) ) + END IF + X( JX ) = TEMP + JX = JX + INCX + IF( J.GT.K ) + $ KX = KX + INCX + 140 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 170, J = N, 1, -1 + TEMP = X( J ) + L = 1 - J + IF( NOCONJ )THEN + DO 150, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( I ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + ELSE + DO 160, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( I ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( 1, J ) ) + END IF + X( J ) = TEMP + 170 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 200, J = N, 1, -1 + TEMP = X( JX ) + IX = KX + L = 1 - J + IF( NOCONJ )THEN + DO 180, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - A( L + I, J )*X( IX ) + IX = IX - INCX + 180 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( 1, J ) + ELSE + DO 190, I = MIN( N, J + K ), J + 1, -1 + TEMP = TEMP - DCONJG( A( L + I, J ) )*X( IX ) + IX = IX - INCX + 190 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( 1, J ) ) + END IF + X( JX ) = TEMP + JX = JX - INCX + IF( ( N - J ).GE.K ) + $ KX = KX - INCX + 200 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of ZTBSV . +* + END diff --git a/dep/blas/ztrmm.f b/dep/blas/ztrmm.f new file mode 100644 index 00000000..91a5fde4 --- /dev/null +++ b/dep/blas/ztrmm.f @@ -0,0 +1,392 @@ + SUBROUTINE ZTRMM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + COMPLEX*16 ALPHA +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* ZTRMM performs one of the matrix-matrix operations +* +* B := alpha*op( A )*B, or B := alpha*B*op( A ) +* +* where alpha is a scalar, B is an m by n matrix, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A' or op( A ) = conjg( A' ). +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) multiplies B from +* the left or right as follows: +* +* SIDE = 'L' or 'l' B := alpha*op( A )*B. +* +* SIDE = 'R' or 'r' B := alpha*B*op( A ). +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = conjg( A' ). +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - COMPLEX*16 array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the matrix B, and on exit is overwritten by the +* transformed matrix. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOCONJ, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + COMPLEX*16 TEMP +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOCONJ = LSAME( TRANSA, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZTRMM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*A*B. +* + IF( UPPER )THEN + DO 50, J = 1, N + DO 40, K = 1, M + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + DO 30, I = 1, K - 1 + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 30 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP*A( K, K ) + B( K, J ) = TEMP + END IF + 40 CONTINUE + 50 CONTINUE + ELSE + DO 80, J = 1, N + DO 70 K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + TEMP = ALPHA*B( K, J ) + B( K, J ) = TEMP + IF( NOUNIT ) + $ B( K, J ) = B( K, J )*A( K, K ) + DO 60, I = K + 1, M + B( I, J ) = B( I, J ) + TEMP*A( I, K ) + 60 CONTINUE + END IF + 70 CONTINUE + 80 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A' or B := alpha*B*conjg( A' ). +* + IF( UPPER )THEN + DO 120, J = 1, N + DO 110, I = M, 1, -1 + TEMP = B( I, J ) + IF( NOCONJ )THEN + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 90, K = 1, I - 1 + TEMP = TEMP + A( K, I )*B( K, J ) + 90 CONTINUE + ELSE + IF( NOUNIT ) + $ TEMP = TEMP*DCONJG( A( I, I ) ) + DO 100, K = 1, I - 1 + TEMP = TEMP + DCONJG( A( K, I ) )*B( K, J ) + 100 CONTINUE + END IF + B( I, J ) = ALPHA*TEMP + 110 CONTINUE + 120 CONTINUE + ELSE + DO 160, J = 1, N + DO 150, I = 1, M + TEMP = B( I, J ) + IF( NOCONJ )THEN + IF( NOUNIT ) + $ TEMP = TEMP*A( I, I ) + DO 130, K = I + 1, M + TEMP = TEMP + A( K, I )*B( K, J ) + 130 CONTINUE + ELSE + IF( NOUNIT ) + $ TEMP = TEMP*DCONJG( A( I, I ) ) + DO 140, K = I + 1, M + TEMP = TEMP + DCONJG( A( K, I ) )*B( K, J ) + 140 CONTINUE + END IF + B( I, J ) = ALPHA*TEMP + 150 CONTINUE + 160 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*A. +* + IF( UPPER )THEN + DO 200, J = N, 1, -1 + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 170, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 170 CONTINUE + DO 190, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 180, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 180 CONTINUE + END IF + 190 CONTINUE + 200 CONTINUE + ELSE + DO 240, J = 1, N + TEMP = ALPHA + IF( NOUNIT ) + $ TEMP = TEMP*A( J, J ) + DO 210, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 210 CONTINUE + DO 230, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + TEMP = ALPHA*A( K, J ) + DO 220, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 220 CONTINUE + END IF + 230 CONTINUE + 240 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A' or B := alpha*B*conjg( A' ). +* + IF( UPPER )THEN + DO 280, K = 1, N + DO 260, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = ALPHA*A( J, K ) + ELSE + TEMP = ALPHA*DCONJG( A( J, K ) ) + END IF + DO 250, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 250 CONTINUE + END IF + 260 CONTINUE + TEMP = ALPHA + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = TEMP*A( K, K ) + ELSE + TEMP = TEMP*DCONJG( A( K, K ) ) + END IF + END IF + IF( TEMP.NE.ONE )THEN + DO 270, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 270 CONTINUE + END IF + 280 CONTINUE + ELSE + DO 320, K = N, 1, -1 + DO 300, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = ALPHA*A( J, K ) + ELSE + TEMP = ALPHA*DCONJG( A( J, K ) ) + END IF + DO 290, I = 1, M + B( I, J ) = B( I, J ) + TEMP*B( I, K ) + 290 CONTINUE + END IF + 300 CONTINUE + TEMP = ALPHA + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = TEMP*A( K, K ) + ELSE + TEMP = TEMP*DCONJG( A( K, K ) ) + END IF + END IF + IF( TEMP.NE.ONE )THEN + DO 310, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 310 CONTINUE + END IF + 320 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of ZTRMM . +* + END diff --git a/dep/blas/ztrmv.f b/dep/blas/ztrmv.f new file mode 100644 index 00000000..1c08bc6c --- /dev/null +++ b/dep/blas/ztrmv.f @@ -0,0 +1,309 @@ + SUBROUTINE ZTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +* .. Scalar Arguments .. + INTEGER INCX,LDA,N + CHARACTER DIAG,TRANS,UPLO +* .. +* .. Array Arguments .. + DOUBLE COMPLEX A(LDA,*),X(*) +* .. +* +* Purpose +* ======= +* +* ZTRMV performs one of the matrix-vector operations +* +* x := A*x, or x := A'*x, or x := conjg( A' )*x, +* +* where x is an n element vector and A is an n by n unit, or non-unit, +* upper or lower triangular matrix. +* +* Arguments +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the operation to be performed as +* follows: +* +* TRANS = 'N' or 'n' x := A*x. +* +* TRANS = 'T' or 't' x := A'*x. +* +* TRANS = 'C' or 'c' x := conjg( A' )*x. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element vector x. On exit, X is overwritten with the +* tranformed vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + DOUBLE COMPLEX ZERO + PARAMETER (ZERO= (0.0D+0,0.0D+0)) +* .. +* .. Local Scalars .. + DOUBLE COMPLEX TEMP + INTEGER I,INFO,IX,J,JX,KX + LOGICAL NOCONJ,NOUNIT +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC DCONJG,MAX +* .. +* +* Test the input parameters. +* + INFO = 0 + IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN + INFO = 1 + ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND. + + .NOT.LSAME(TRANS,'C')) THEN + INFO = 2 + ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN + INFO = 3 + ELSE IF (N.LT.0) THEN + INFO = 4 + ELSE IF (LDA.LT.MAX(1,N)) THEN + INFO = 6 + ELSE IF (INCX.EQ.0) THEN + INFO = 8 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('ZTRMV ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF (N.EQ.0) RETURN +* + NOCONJ = LSAME(TRANS,'T') + NOUNIT = LSAME(DIAG,'N') +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF (INCX.LE.0) THEN + KX = 1 - (N-1)*INCX + ELSE IF (INCX.NE.1) THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF (LSAME(TRANS,'N')) THEN +* +* Form x := A*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 20 J = 1,N + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 10 I = 1,J - 1 + X(I) = X(I) + TEMP*A(I,J) + 10 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 20 CONTINUE + ELSE + JX = KX + DO 40 J = 1,N + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 30 I = 1,J - 1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX + INCX + 30 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX + INCX + 40 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 60 J = N,1,-1 + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 50 I = N,J + 1,-1 + X(I) = X(I) + TEMP*A(I,J) + 50 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 60 CONTINUE + ELSE + KX = KX + (N-1)*INCX + JX = KX + DO 80 J = N,1,-1 + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 70 I = N,J + 1,-1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX - INCX + 70 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX - INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := A'*x or x := conjg( A' )*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 110 J = N,1,-1 + TEMP = X(J) + IF (NOCONJ) THEN + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 90 I = J - 1,1,-1 + TEMP = TEMP + A(I,J)*X(I) + 90 CONTINUE + ELSE + IF (NOUNIT) TEMP = TEMP*DCONJG(A(J,J)) + DO 100 I = J - 1,1,-1 + TEMP = TEMP + DCONJG(A(I,J))*X(I) + 100 CONTINUE + END IF + X(J) = TEMP + 110 CONTINUE + ELSE + JX = KX + (N-1)*INCX + DO 140 J = N,1,-1 + TEMP = X(JX) + IX = JX + IF (NOCONJ) THEN + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 120 I = J - 1,1,-1 + IX = IX - INCX + TEMP = TEMP + A(I,J)*X(IX) + 120 CONTINUE + ELSE + IF (NOUNIT) TEMP = TEMP*DCONJG(A(J,J)) + DO 130 I = J - 1,1,-1 + IX = IX - INCX + TEMP = TEMP + DCONJG(A(I,J))*X(IX) + 130 CONTINUE + END IF + X(JX) = TEMP + JX = JX - INCX + 140 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 170 J = 1,N + TEMP = X(J) + IF (NOCONJ) THEN + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 150 I = J + 1,N + TEMP = TEMP + A(I,J)*X(I) + 150 CONTINUE + ELSE + IF (NOUNIT) TEMP = TEMP*DCONJG(A(J,J)) + DO 160 I = J + 1,N + TEMP = TEMP + DCONJG(A(I,J))*X(I) + 160 CONTINUE + END IF + X(J) = TEMP + 170 CONTINUE + ELSE + JX = KX + DO 200 J = 1,N + TEMP = X(JX) + IX = JX + IF (NOCONJ) THEN + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 180 I = J + 1,N + IX = IX + INCX + TEMP = TEMP + A(I,J)*X(IX) + 180 CONTINUE + ELSE + IF (NOUNIT) TEMP = TEMP*DCONJG(A(J,J)) + DO 190 I = J + 1,N + IX = IX + INCX + TEMP = TEMP + DCONJG(A(I,J))*X(IX) + 190 CONTINUE + END IF + X(JX) = TEMP + JX = JX + INCX + 200 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of ZTRMV . +* + END diff --git a/dep/blas/ztrsm.f b/dep/blas/ztrsm.f new file mode 100644 index 00000000..e414ec66 --- /dev/null +++ b/dep/blas/ztrsm.f @@ -0,0 +1,414 @@ + SUBROUTINE ZTRSM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, + $ B, LDB ) +* .. Scalar Arguments .. + CHARACTER*1 SIDE, UPLO, TRANSA, DIAG + INTEGER M, N, LDA, LDB + COMPLEX*16 ALPHA +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* ZTRSM solves one of the matrix equations +* +* op( A )*X = alpha*B, or X*op( A ) = alpha*B, +* +* where alpha is a scalar, X and B are m by n matrices, A is a unit, or +* non-unit, upper or lower triangular matrix and op( A ) is one of +* +* op( A ) = A or op( A ) = A' or op( A ) = conjg( A' ). +* +* The matrix X is overwritten on B. +* +* Parameters +* ========== +* +* SIDE - CHARACTER*1. +* On entry, SIDE specifies whether op( A ) appears on the left +* or right of X as follows: +* +* SIDE = 'L' or 'l' op( A )*X = alpha*B. +* +* SIDE = 'R' or 'r' X*op( A ) = alpha*B. +* +* Unchanged on exit. +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix A is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANSA - CHARACTER*1. +* On entry, TRANSA specifies the form of op( A ) to be used in +* the matrix multiplication as follows: +* +* TRANSA = 'N' or 'n' op( A ) = A. +* +* TRANSA = 'T' or 't' op( A ) = A'. +* +* TRANSA = 'C' or 'c' op( A ) = conjg( A' ). +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit triangular +* as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* M - INTEGER. +* On entry, M specifies the number of rows of B. M must be at +* least zero. +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the number of columns of B. N must be +* at least zero. +* Unchanged on exit. +* +* ALPHA - COMPLEX*16 . +* On entry, ALPHA specifies the scalar alpha. When alpha is +* zero then A is not referenced and B need not be set before +* entry. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, k ), where k is m +* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +* Before entry with UPLO = 'U' or 'u', the leading k by k +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading k by k +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. When SIDE = 'L' or 'l' then +* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +* then LDA must be at least max( 1, n ). +* Unchanged on exit. +* +* B - COMPLEX*16 array of DIMENSION ( LDB, n ). +* Before entry, the leading m by n part of the array B must +* contain the right-hand side matrix B, and on exit is +* overwritten by the solution matrix X. +* +* LDB - INTEGER. +* On entry, LDB specifies the first dimension of B as declared +* in the calling (sub) program. LDB must be at least +* max( 1, m ). +* Unchanged on exit. +* +* +* Level 3 Blas routine. +* +* -- Written on 8-February-1989. +* Jack Dongarra, Argonne National Laboratory. +* Iain Duff, AERE Harwell. +* Jeremy Du Croz, Numerical Algorithms Group Ltd. +* Sven Hammarling, Numerical Algorithms Group Ltd. +* +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. Local Scalars .. + LOGICAL LSIDE, NOCONJ, NOUNIT, UPPER + INTEGER I, INFO, J, K, NROWA + COMPLEX*16 TEMP +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LSIDE = LSAME( SIDE , 'L' ) + IF( LSIDE )THEN + NROWA = M + ELSE + NROWA = N + END IF + NOCONJ = LSAME( TRANSA, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) + UPPER = LSAME( UPLO , 'U' ) +* + INFO = 0 + IF( ( .NOT.LSIDE ).AND. + $ ( .NOT.LSAME( SIDE , 'R' ) ) )THEN + INFO = 1 + ELSE IF( ( .NOT.UPPER ).AND. + $ ( .NOT.LSAME( UPLO , 'L' ) ) )THEN + INFO = 2 + ELSE IF( ( .NOT.LSAME( TRANSA, 'N' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'T' ) ).AND. + $ ( .NOT.LSAME( TRANSA, 'C' ) ) )THEN + INFO = 3 + ELSE IF( ( .NOT.LSAME( DIAG , 'U' ) ).AND. + $ ( .NOT.LSAME( DIAG , 'N' ) ) )THEN + INFO = 4 + ELSE IF( M .LT.0 )THEN + INFO = 5 + ELSE IF( N .LT.0 )THEN + INFO = 6 + ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN + INFO = 9 + ELSE IF( LDB.LT.MAX( 1, M ) )THEN + INFO = 11 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZTRSM ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* And when alpha.eq.zero. +* + IF( ALPHA.EQ.ZERO )THEN + DO 20, J = 1, N + DO 10, I = 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF( LSIDE )THEN + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*inv( A )*B. +* + IF( UPPER )THEN + DO 60, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 30, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 30 CONTINUE + END IF + DO 50, K = M, 1, -1 + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 40, I = 1, K - 1 + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 40 CONTINUE + END IF + 50 CONTINUE + 60 CONTINUE + ELSE + DO 100, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 70, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 70 CONTINUE + END IF + DO 90 K = 1, M + IF( B( K, J ).NE.ZERO )THEN + IF( NOUNIT ) + $ B( K, J ) = B( K, J )/A( K, K ) + DO 80, I = K + 1, M + B( I, J ) = B( I, J ) - B( K, J )*A( I, K ) + 80 CONTINUE + END IF + 90 CONTINUE + 100 CONTINUE + END IF + ELSE +* +* Form B := alpha*inv( A' )*B +* or B := alpha*inv( conjg( A' ) )*B. +* + IF( UPPER )THEN + DO 140, J = 1, N + DO 130, I = 1, M + TEMP = ALPHA*B( I, J ) + IF( NOCONJ )THEN + DO 110, K = 1, I - 1 + TEMP = TEMP - A( K, I )*B( K, J ) + 110 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + ELSE + DO 120, K = 1, I - 1 + TEMP = TEMP - DCONJG( A( K, I ) )*B( K, J ) + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( I, I ) ) + END IF + B( I, J ) = TEMP + 130 CONTINUE + 140 CONTINUE + ELSE + DO 180, J = 1, N + DO 170, I = M, 1, -1 + TEMP = ALPHA*B( I, J ) + IF( NOCONJ )THEN + DO 150, K = I + 1, M + TEMP = TEMP - A( K, I )*B( K, J ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( I, I ) + ELSE + DO 160, K = I + 1, M + TEMP = TEMP - DCONJG( A( K, I ) )*B( K, J ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( I, I ) ) + END IF + B( I, J ) = TEMP + 170 CONTINUE + 180 CONTINUE + END IF + END IF + ELSE + IF( LSAME( TRANSA, 'N' ) )THEN +* +* Form B := alpha*B*inv( A ). +* + IF( UPPER )THEN + DO 230, J = 1, N + IF( ALPHA.NE.ONE )THEN + DO 190, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 190 CONTINUE + END IF + DO 210, K = 1, J - 1 + IF( A( K, J ).NE.ZERO )THEN + DO 200, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 200 CONTINUE + END IF + 210 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 220, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 220 CONTINUE + END IF + 230 CONTINUE + ELSE + DO 280, J = N, 1, -1 + IF( ALPHA.NE.ONE )THEN + DO 240, I = 1, M + B( I, J ) = ALPHA*B( I, J ) + 240 CONTINUE + END IF + DO 260, K = J + 1, N + IF( A( K, J ).NE.ZERO )THEN + DO 250, I = 1, M + B( I, J ) = B( I, J ) - A( K, J )*B( I, K ) + 250 CONTINUE + END IF + 260 CONTINUE + IF( NOUNIT )THEN + TEMP = ONE/A( J, J ) + DO 270, I = 1, M + B( I, J ) = TEMP*B( I, J ) + 270 CONTINUE + END IF + 280 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*inv( A' ) +* or B := alpha*B*inv( conjg( A' ) ). +* + IF( UPPER )THEN + DO 330, K = N, 1, -1 + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = ONE/A( K, K ) + ELSE + TEMP = ONE/DCONJG( A( K, K ) ) + END IF + DO 290, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 290 CONTINUE + END IF + DO 310, J = 1, K - 1 + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = A( J, K ) + ELSE + TEMP = DCONJG( A( J, K ) ) + END IF + DO 300, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 300 CONTINUE + END IF + 310 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 320, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 320 CONTINUE + END IF + 330 CONTINUE + ELSE + DO 380, K = 1, N + IF( NOUNIT )THEN + IF( NOCONJ )THEN + TEMP = ONE/A( K, K ) + ELSE + TEMP = ONE/DCONJG( A( K, K ) ) + END IF + DO 340, I = 1, M + B( I, K ) = TEMP*B( I, K ) + 340 CONTINUE + END IF + DO 360, J = K + 1, N + IF( A( J, K ).NE.ZERO )THEN + IF( NOCONJ )THEN + TEMP = A( J, K ) + ELSE + TEMP = DCONJG( A( J, K ) ) + END IF + DO 350, I = 1, M + B( I, J ) = B( I, J ) - TEMP*B( I, K ) + 350 CONTINUE + END IF + 360 CONTINUE + IF( ALPHA.NE.ONE )THEN + DO 370, I = 1, M + B( I, K ) = ALPHA*B( I, K ) + 370 CONTINUE + END IF + 380 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of ZTRSM . +* + END diff --git a/dep/blas/ztrsv.f b/dep/blas/ztrsv.f new file mode 100644 index 00000000..d0a57c44 --- /dev/null +++ b/dep/blas/ztrsv.f @@ -0,0 +1,324 @@ + SUBROUTINE ZTRSV ( UPLO, TRANS, DIAG, N, A, LDA, X, INCX ) +* .. Scalar Arguments .. + INTEGER INCX, LDA, N + CHARACTER*1 DIAG, TRANS, UPLO +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ), X( * ) +* .. +* +* Purpose +* ======= +* +* ZTRSV solves one of the systems of equations +* +* A*x = b, or A'*x = b, or conjg( A' )*x = b, +* +* where b and x are n element vectors and A is an n by n unit, or +* non-unit, upper or lower triangular matrix. +* +* No test for singularity or near-singularity is included in this +* routine. Such tests must be performed before calling this routine. +* +* Parameters +* ========== +* +* UPLO - CHARACTER*1. +* On entry, UPLO specifies whether the matrix is an upper or +* lower triangular matrix as follows: +* +* UPLO = 'U' or 'u' A is an upper triangular matrix. +* +* UPLO = 'L' or 'l' A is a lower triangular matrix. +* +* Unchanged on exit. +* +* TRANS - CHARACTER*1. +* On entry, TRANS specifies the equations to be solved as +* follows: +* +* TRANS = 'N' or 'n' A*x = b. +* +* TRANS = 'T' or 't' A'*x = b. +* +* TRANS = 'C' or 'c' conjg( A' )*x = b. +* +* Unchanged on exit. +* +* DIAG - CHARACTER*1. +* On entry, DIAG specifies whether or not A is unit +* triangular as follows: +* +* DIAG = 'U' or 'u' A is assumed to be unit triangular. +* +* DIAG = 'N' or 'n' A is not assumed to be unit +* triangular. +* +* Unchanged on exit. +* +* N - INTEGER. +* On entry, N specifies the order of the matrix A. +* N must be at least zero. +* Unchanged on exit. +* +* A - COMPLEX*16 array of DIMENSION ( LDA, n ). +* Before entry with UPLO = 'U' or 'u', the leading n by n +* upper triangular part of the array A must contain the upper +* triangular matrix and the strictly lower triangular part of +* A is not referenced. +* Before entry with UPLO = 'L' or 'l', the leading n by n +* lower triangular part of the array A must contain the lower +* triangular matrix and the strictly upper triangular part of +* A is not referenced. +* Note that when DIAG = 'U' or 'u', the diagonal elements of +* A are not referenced either, but are assumed to be unity. +* Unchanged on exit. +* +* LDA - INTEGER. +* On entry, LDA specifies the first dimension of A as declared +* in the calling (sub) program. LDA must be at least +* max( 1, n ). +* Unchanged on exit. +* +* X - COMPLEX*16 array of dimension at least +* ( 1 + ( n - 1 )*abs( INCX ) ). +* Before entry, the incremented array X must contain the n +* element right-hand side vector b. On exit, X is overwritten +* with the solution vector x. +* +* INCX - INTEGER. +* On entry, INCX specifies the increment for the elements of +* X. INCX must not be zero. +* Unchanged on exit. +* +* +* Level 2 Blas routine. +* +* -- Written on 22-October-1986. +* Jack Dongarra, Argonne National Lab. +* Jeremy Du Croz, Nag Central Office. +* Sven Hammarling, Nag Central Office. +* Richard Hanson, Sandia National Labs. +* +* +* .. Parameters .. + COMPLEX*16 ZERO + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. Local Scalars .. + COMPLEX*16 TEMP + INTEGER I, INFO, IX, J, JX, KX + LOGICAL NOCONJ, NOUNIT +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. External Subroutines .. + EXTERNAL XERBLA +* .. Intrinsic Functions .. + INTRINSIC DCONJG, MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF ( .NOT.LSAME( UPLO , 'U' ).AND. + $ .NOT.LSAME( UPLO , 'L' ) )THEN + INFO = 1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ).AND. + $ .NOT.LSAME( TRANS, 'T' ).AND. + $ .NOT.LSAME( TRANS, 'C' ) )THEN + INFO = 2 + ELSE IF( .NOT.LSAME( DIAG , 'U' ).AND. + $ .NOT.LSAME( DIAG , 'N' ) )THEN + INFO = 3 + ELSE IF( N.LT.0 )THEN + INFO = 4 + ELSE IF( LDA.LT.MAX( 1, N ) )THEN + INFO = 6 + ELSE IF( INCX.EQ.0 )THEN + INFO = 8 + END IF + IF( INFO.NE.0 )THEN + CALL XERBLA( 'ZTRSV ', INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* + NOCONJ = LSAME( TRANS, 'T' ) + NOUNIT = LSAME( DIAG , 'N' ) +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF( INCX.LE.0 )THEN + KX = 1 - ( N - 1 )*INCX + ELSE IF( INCX.NE.1 )THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF( LSAME( TRANS, 'N' ) )THEN +* +* Form x := inv( A )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + IF( INCX.EQ.1 )THEN + DO 20, J = N, 1, -1 + IF( X( J ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( J ) = X( J )/A( J, J ) + TEMP = X( J ) + DO 10, I = J - 1, 1, -1 + X( I ) = X( I ) - TEMP*A( I, J ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE + JX = KX + ( N - 1 )*INCX + DO 40, J = N, 1, -1 + IF( X( JX ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( J, J ) + TEMP = X( JX ) + IX = JX + DO 30, I = J - 1, 1, -1 + IX = IX - INCX + X( IX ) = X( IX ) - TEMP*A( I, J ) + 30 CONTINUE + END IF + JX = JX - INCX + 40 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 60, J = 1, N + IF( X( J ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( J ) = X( J )/A( J, J ) + TEMP = X( J ) + DO 50, I = J + 1, N + X( I ) = X( I ) - TEMP*A( I, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE + JX = KX + DO 80, J = 1, N + IF( X( JX ).NE.ZERO )THEN + IF( NOUNIT ) + $ X( JX ) = X( JX )/A( J, J ) + TEMP = X( JX ) + IX = JX + DO 70, I = J + 1, N + IX = IX + INCX + X( IX ) = X( IX ) - TEMP*A( I, J ) + 70 CONTINUE + END IF + JX = JX + INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := inv( A' )*x or x := inv( conjg( A' ) )*x. +* + IF( LSAME( UPLO, 'U' ) )THEN + IF( INCX.EQ.1 )THEN + DO 110, J = 1, N + TEMP = X( J ) + IF( NOCONJ )THEN + DO 90, I = 1, J - 1 + TEMP = TEMP - A( I, J )*X( I ) + 90 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 100, I = 1, J - 1 + TEMP = TEMP - DCONJG( A( I, J ) )*X( I ) + 100 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( J, J ) ) + END IF + X( J ) = TEMP + 110 CONTINUE + ELSE + JX = KX + DO 140, J = 1, N + IX = KX + TEMP = X( JX ) + IF( NOCONJ )THEN + DO 120, I = 1, J - 1 + TEMP = TEMP - A( I, J )*X( IX ) + IX = IX + INCX + 120 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 130, I = 1, J - 1 + TEMP = TEMP - DCONJG( A( I, J ) )*X( IX ) + IX = IX + INCX + 130 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( J, J ) ) + END IF + X( JX ) = TEMP + JX = JX + INCX + 140 CONTINUE + END IF + ELSE + IF( INCX.EQ.1 )THEN + DO 170, J = N, 1, -1 + TEMP = X( J ) + IF( NOCONJ )THEN + DO 150, I = N, J + 1, -1 + TEMP = TEMP - A( I, J )*X( I ) + 150 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 160, I = N, J + 1, -1 + TEMP = TEMP - DCONJG( A( I, J ) )*X( I ) + 160 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( J, J ) ) + END IF + X( J ) = TEMP + 170 CONTINUE + ELSE + KX = KX + ( N - 1 )*INCX + JX = KX + DO 200, J = N, 1, -1 + IX = KX + TEMP = X( JX ) + IF( NOCONJ )THEN + DO 180, I = N, J + 1, -1 + TEMP = TEMP - A( I, J )*X( IX ) + IX = IX - INCX + 180 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/A( J, J ) + ELSE + DO 190, I = N, J + 1, -1 + TEMP = TEMP - DCONJG( A( I, J ) )*X( IX ) + IX = IX - INCX + 190 CONTINUE + IF( NOUNIT ) + $ TEMP = TEMP/DCONJG( A( J, J ) ) + END IF + X( JX ) = TEMP + JX = JX - INCX + 200 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of ZTRSV . +* + END diff --git a/dep/cvode-2.7.0/CMakeLists.txt b/dep/cvode-2.7.0/CMakeLists.txt new file mode 100644 index 00000000..17e50ebc --- /dev/null +++ b/dep/cvode-2.7.0/CMakeLists.txt @@ -0,0 +1,364 @@ +# --------------------------------------------------------------- +# $Revision: 1.10 $ +# $Date: 2010/12/15 22:28:16 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# Top level CMakeLists.txt for SUNDIALS (for cmake build system) + + +# ------------------------------------------------------------- +# Initial commands +# ------------------------------------------------------------- + +# Require a fairly recent cmake version + +CMAKE_MINIMUM_REQUIRED(VERSION 2.2) + +# Project SUNDIALS (initially only C supported) + +PROJECT(sundials C) + +# Set some variables with info on the SUNDIALS project + +SET(PACKAGE_BUGREPORT "radu@llnl.gov") +SET(PACKAGE_NAME "SUNDIALS") +SET(PACKAGE_STRING "SUNDIALS 2.4.0") +SET(PACKAGE_TARNAME "sundials") +SET(PACKAGE_VERSION "2.4.0") + +# Prohibit in-source build + +IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") + MESSAGE(FATAL_ERROR "In-source build prohibited.") +ENDIF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") + +# Hide/show some cache variables + +MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH) +MARK_AS_ADVANCED(CLEAR + CMAKE_C_COMPILER + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_RELWITHDEB) + +# Specify the VERSION and SOVERSION for shared libraries + +SET(cvodelib_VERSION "1.0.0") +SET(cvodelib_SOVERSION "1") + +SET(nveclib_VERSION "0.0.2") +SET(nveclib_SOVERSION "0") + +# Specify the location of additional CMAKE modules + +SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/config) + +# ------------------------------------------------------------- +# MACRO definitions +# ------------------------------------------------------------- + +# Macros to hide/show cached variables. +# These two macros can be used to "hide" or "show" in the +# list of cached variables various variables and/or options +# that depend on other options. +# Note that once a variable is modified, it will preserve its +# value (hidding it merely makes it internal) + +MACRO(HIDE_VARIABLE var) + IF(DEFINED ${var}) + SET(${var} "${${var}}" CACHE INTERNAL "") + ENDIF(DEFINED ${var}) +ENDMACRO(HIDE_VARIABLE) + +MACRO(SHOW_VARIABLE var type doc default) + IF(DEFINED ${var}) + SET(${var} "${${var}}" CACHE "${type}" "${doc}" FORCE) + ELSE(DEFINED ${var}) + SET(${var} "${default}" CACHE "${type}" "${doc}") + ENDIF(DEFINED ${var}) +ENDMACRO(SHOW_VARIABLE) + +# Macros to append a common suffix or prefix to the elements of a list + +MACRO(ADD_SUFFIX rootlist suffix) + SET(outlist ) + FOREACH(root ${${rootlist}}) + LIST(APPEND outlist ${root}${suffix}) + ENDFOREACH(root) + SET(${rootlist} ${outlist}) +ENDMACRO(ADD_SUFFIX) + +MACRO(ADD_PREFIX prefix rootlist) + SET(outlist ) + FOREACH(root ${${rootlist}}) + LIST(APPEND outlist ${prefix}${root}) + ENDFOREACH(root) + SET(${rootlist} ${outlist}) +ENDMACRO(ADD_PREFIX) + +# Macro to print warning that some features will be disabled +# due to some failure. + +MACRO(PRINT_WARNING message action) + MESSAGE("WARNING: ${message}.\n ${action}.") +ENDMACRO(PRINT_WARNING) + +# Returns an unquoted string. Note that CMake will readily turn such +# strings back into lists, due to the duality of lists and +# semicolon-separated strings. So be careful how you use it. + +MACRO(LIST2STRING alist astring) + FOREACH(elem ${${alist}}) + SET(${astring} "${${astring}} ${elem}") + ENDFOREACH(elem) +ENDMACRO(LIST2STRING) + +# ------------------------------------------------------------- +# Which modules to build? +# ------------------------------------------------------------- +OPTION(BUILD_CVODE "Build the CVODE library" ON) + + +# ------------------------------------------------------------- +# Other configuration options +# ------------------------------------------------------------- + +# Option that allows users to build static and/or shared libraries +# ---------------------------------------------------------------- + +OPTION(BUILD_STATIC_LIBS "Build static libraries" ON) +OPTION(BUILD_SHARED_LIBS "Build shared libraries" OFF) + +# Prepare substitution variable SUNDIALS_EXPORT for sundials_config.h +# When building shared SUNDIALS libraries under Windows, use +# #define SUNDIALS_EXPORT __declspec(dllexport) +# When linking to shared SUNDIALS libraries under Windows, use +# #define SUNDIALS_EXPORT __declspec(dllimport) +# In all other cases (other platforms or static libraries +# under Windows), the SUNDIALS_EXPORT macro is empty + +IF(BUILD_SHARED_LIBS AND WIN32) + SET(SUNDIALS_EXPORT + "#ifdef BUILD_SUNDIALS_LIBRARY +#define SUNDIALS_EXPORT __declspec(dllexport) +#else +#define SUNDIALS_EXPORT __declspec(dllimport) +#endif") +ELSE(BUILD_SHARED_LIBS AND WIN32) + SET(SUNDIALS_EXPORT "#define SUNDIALS_EXPORT") +ENDIF(BUILD_SHARED_LIBS AND WIN32) + +# Make sure we build at least one type of libraries +IF(NOT BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS) + PRINT_WARNING("Both static and shared library generation were disabled" + "Building static libraries was re-enabled") + SET(BUILD_STATIC_LIBS ON CACHE BOOL "Build static libraries" FORCE) +ENDIF(NOT BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS) + +# Option to specify precision +# --------------------------- + +SET(SUNDIALS_PRECISION "double" CACHE STRING "double, single or extended") + +# prepare substitution variable PRECISION_LEVEL for sundials_config.h +STRING(TOUPPER ${SUNDIALS_PRECISION} SUNDIALS_PRECISION) +SET(PRECISION_LEVEL "#define SUNDIALS_${SUNDIALS_PRECISION}_PRECISION 1") + +# Option to use the generic math libraries (UNIX only) +# ---------------------------------------------------- + +IF(UNIX) + OPTION(USE_GENERIC_MATH "Use generic (std-c) math libraries" ON) + IF(USE_GENERIC_MATH) + # executables will be linked against -lm + SET(EXTRA_LINK_LIBS -lm) + # prepare substitution variable GENERIC_MATH_LIB for sundials_config.h + SET(GENERIC_MATH_LIB "#define SUNDIALS_USE_GENERIC_MATH") + ENDIF(USE_GENERIC_MATH) +ENDIF(UNIX) + +# ------------------------------------------------------------- +# Enable Fortran support? +# ------------------------------------------------------------- + +# FCMIX support is an option only if at least one solver that +# provides such an interface is built. + +SHOW_VARIABLE(FCMIX_ENABLE BOOL "Enable Fortran-C support" OFF) + +# ------------------------------------------------------------- +# Enable BLAS/LAPACK support? +# ------------------------------------------------------------- + +OPTION(LAPACK_ENABLE "Enable Lapack support" OFF) + +IF(NOT LAPACK_ENABLE) + HIDE_VARIABLE(SUNDIALS_F77_FUNC_CASE) + HIDE_VARIABLE(SUNDIALS_F77_FUNC_UNDERSCORES) + HIDE_VARIABLE(LAPACK_LIBRARIES) +ENDIF(NOT LAPACK_ENABLE) + +# ------------------------------------------------------------- +# Enable MPI support? +# ------------------------------------------------------------- + +OPTION(MPI_ENABLE "Enable MPI support" OFF) + +HIDE_VARIABLE(MPI_INCLUDE_PATH) +HIDE_VARIABLE(MPI_LIBRARIES) +HIDE_VARIABLE(MPI_EXTRA_LIBRARIES) +HIDE_VARIABLE(MPI_MPICC) +HIDE_VARIABLE(MPI_MPIF77) + +# ------------------------------------------------------------- +# Enable examples? +# ------------------------------------------------------------- + +OPTION(EXAMPLES_ENABLE "Build the SUNDIALS examples" OFF) +HIDE_VARIABLE(EXAMPLES_INSTALL) +HIDE_VARIABLE(EXAMPLES_INSTALL_PATH) + +# ------------------------------------------------------------- +# Add any other necessary compiler flags & definitions +# ------------------------------------------------------------- + +# ------------------------------------------------------------- +# A Fortran compiler is needed if: +# (a) FCMIX is enabled +# (b) LAPACK is enabled (for the name-mangling scheme) +# ------------------------------------------------------------- + +IF(FCMIX_ENABLE OR LAPACK_ENABLE) + INCLUDE(SundialsFortran) + IF(NOT F77_FOUND AND FCMIX_ENABLE) + PRINT_WARNING("Fortran compiler not functional" + "FCMIX support will not be provided") + ENDIF(NOT F77_FOUND AND FCMIX_ENABLE) +ENDIF(FCMIX_ENABLE OR LAPACK_ENABLE) + +# ------------------------------------------------------------- +# If we have a name-mangling scheme (either automatically +# inferred or provided by the user), set the SUNDIALS +# compiler preprocessor macro definitions. +# ------------------------------------------------------------- + +SET(F77_MANGLE_MACRO1 "") +SET(F77_MANGLE_MACRO2 "") + +IF(F77SCHEME_FOUND) + # Symbols WITHOUT underscores + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "mysub") + SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) name") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "mysub") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "mysub_") + SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) name ## _") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "mysub_") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "mysub__") + SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) name ## __") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "mysub__") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB") + SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) NAME") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB_") + SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) NAME ## _") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB_") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB__") + SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) NAME ## __") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB__") + # Symbols with underscores + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub") + SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) name") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub_") + SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) name ## _") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub_") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub__") + SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) name ## __") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub__") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB") + SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) NAME") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB_") + SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) NAME ## _") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB_") + IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB__") + SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) NAME ## __") + ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB__") +ENDIF(F77SCHEME_FOUND) + +# ------------------------------------------------------------- +# Find (and test) the Lapack libraries +# ------------------------------------------------------------- + +# If LAPACK is needed, first try to find the appropriate +# libraries and linker flags needed to link against them. + +# Macro to be inserted in sundials_config.h +SET(BLAS_LAPACK_MACRO "#define SUNDIALS_BLAS_LAPACK 0") + +IF(LAPACK_ENABLE) + + INCLUDE(SundialsLapack) + + IF(LAPACK_FOUND) + SET(BLAS_LAPACK_MACRO "#define SUNDIALS_BLAS_LAPACK 1") + ELSE(LAPACK_FOUND) + SHOW_VARIABLE(LAPACK_LIBRARIES STRING "Lapack libraries" "${LAPACK_LIBRARIES}") + SHOW_VARIABLE(LAPACK_LINKER_FLAGS STRING "Lapack required linker flags" "${LAPACK_LINKER_FLAGS}") + ENDIF(LAPACK_FOUND) + + IF(LAPACK_LIBRARIES AND NOT LAPACK_FOUND) + PRINT_WARNING("LAPACK not functional" + "Blas/Lapack support will not be provided") + ENDIF(LAPACK_LIBRARIES AND NOT LAPACK_FOUND) + +ELSE(LAPACK_ENABLE) + + HIDE_VARIABLE(LAPACK_LIBRARIES) + HIDE_VARIABLE(LAPACK_LINKER_FLAGS) + +ENDIF(LAPACK_ENABLE) + +# ------------------------------------------------------------- +# Configure the header file sundials_config.h +# ------------------------------------------------------------- + +# All required substitution variables should be available at this point. +# Generate the header file and place it in the binary dir. +CONFIGURE_FILE( + ${PROJECT_SOURCE_DIR}/include/sundials/sundials_config.in + ${PROJECT_BINARY_DIR}/include/sundials/sundials_config.h + ) + +# Add the include directory in the source tree and the one in +# the binary tree (for the header file sundials_config.h) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include) + +# ------------------------------------------------------------- +# Add selected modules to the build system +# ------------------------------------------------------------- + +# Shared components + +ADD_SUBDIRECTORY(sundials) +ADD_SUBDIRECTORY(nvec_ser) +ADD_SUBDIRECTORY(cvode) + +#---------------------------------- +# Install configuration header file +#---------------------------------- + +# install configured header file +INSTALL( + FILES ${PROJECT_BINARY_DIR}/include/sundials/sundials_config.h + DESTINATION include/dep/sundials + ) + diff --git a/dep/cvode-2.7.0/INSTALL_NOTES b/dep/cvode-2.7.0/INSTALL_NOTES new file mode 100644 index 00000000..3d9870a3 --- /dev/null +++ b/dep/cvode-2.7.0/INSTALL_NOTES @@ -0,0 +1,559 @@ + SUNDIALS Installation Instructions + Release 2.7.0, March 2011 + + +These are generic installation instructions. For complete installation instructions, +consult the user guide for any of the SUNDIALS solvers. + +Contents: + +[A] Preliminaries + A.1. Libraries and exported headers +[B] autotools-based installation + B.1. Basic Installation + B.2. Installation names + B.3. Compilers and Options + B.3.1. General options + B.3.2. Options for Fortran support + B.3.3. Options for Blas/Lapack support + B.3.4. Options for MPI support + B.3.5. Options for library support + B.3.6. Environment variables + B.4. Configuration examples +[C] CMake-based installation + C.1. Prerequisites + C.2. Configuration and build + +================ +A. Preliminaries +================ + +The SUNDIALS suite (or an individual solver) is distributed as a compressed archive +(.tar.gz). The name of the distribution archive is of the form 'solver'-x.y.z.tar.gz, +where 'solver' is one of: 'sundials', 'cvode', 'cvodes', 'ida', 'idas', or 'kinsol', +and x.y.z represents the version number (of the SUNDIALS suite or of the individual +solver). + +To begin the installation, first uncompress and expand the sources, by issuing + + % tar xzf solver-x.y.z.tar.gz + +This will extract source files under a directory 'solver'-x.y.z. + +In the remainder of this chapter, we make the following distinctions: + +'srcdir' + + is the directory 'solver'-x.y.z created above; i.e., the + directory containing the SUNDIALS sources. + +'builddir' + + is the directory under which SUNDIALS is built; i.e., the directory from within + which the configure or ccmake command is issued. + + NOTE: When using the autoconf configure script, this directory can be the same + as 'srcdir'. However, when using ccmake, insource builds are prohibited. + +'instdir' + + is the directory under which the SUNDIALS exported header files and libraries will + be installed. Typically, header files are exported under a directory 'instdir'/include + while libraries are installed under 'instdir'/lib, with 'instdir' specified with the + --prefix flag to configure. See below for more details on the installation directories, + including the special cases of the SUNDIALS examples. + + NOTE: The installation directory 'instdir' should NOT be the same as the source + directory 'srcdir'. + + +SUNDIALS provides two build alternatives: +1) autotools-based build system. This options, suitable for *nix systems + (Linux, Unix, Mac OS X, cygwin, mingw, etc.) is based on running a 'configure' + shell script which generates all required makefiles. +2) CMake-based build system. This option is available on a variety of platforms + (*nix, Windows, Mac OS, etc) but relies on additional software (freely + available CMake). + + +----------------------------------- +A.1. Libraries and exported headers +----------------------------------- + +By default, 'make install' will install the SUNDIALS libraries under 'libdir' and the public +header files under 'includedir'. The default values for these directories are 'instdir'/lib +and 'instdir'/include, respectively, but can be changed at the configuration stage. + +The SUNDIALS libraries and header files are summarized below (names are relative to 'libdir' +for libraries and to 'includedir' for header files) + +SHARED module + header files: sundials/sundials_types.h sundials/sundials_math.h + sundials/sundials_config.h sundias/sundials_nvector.h + sundials/sundials_smalldense.h sundials/sundials_dense.h + sundials/sundials_iterative.h sundials/sundials_band.h + sundials/sundials_spbcgs.h sundials/sundials_sptfqmr.h + sundials/sundials_spgmr.h sundials/sundials_lapack.h + sundials/sundials_fnvector.h + + +NVECTOR_SERIAL module + libraries: libsundials_nvecserial.{a,so} libsundials_fnvecserial.a + header files: nvector/nvector_serial.h + + +NVECTOR_PARALLEL module + libraries: libsundials_nvecparallel.{a,so} libsundials_fnvecparallel.a + header files: nvector/nvector_parallel.h + + +CVODE module + libraries: libsundials_cvode.{a,so} libsundials_fcvode.a + header files: cvode/cvode.h cvode/cvode_direct.h + cvode/cvode_dense.h cvode/cvode_band.h + cvode/cvode_diag.h cvode/cvode_spils.h + cvode/cvode_bandpre.h cvode/cvode_bbdpre.h + cvode/cvode_spgmr.h cvode/cvode_spbcgs.h + cvode/cvode_sptfqmr.h cvode/cvode_impl.h + cvode/cvode_lapack.h + + +CVODES module + library: libsundials_cvodes.{a,so} + header files: cvodes/cvodes.h cvodes/cvodes_direct.h + cvodes/cvodes_dense.h cvodes/cvodes_band.h + cvodes/cvodes_diag.h cvodes/cvodes_spils.h + cvodes/cvodes_bandpre.h cvodes/cvodes_bbdpre.h + cvodes/cvodes_spgmr.h cvodes/cvodes_spbcgs.h + cvodes/cvodes_sptfqmr.h cvodes/cvodes_impl.h + cvodes/cvodes_lapack.h + + +IDA module + library: libsundials_ida.{a,so} + header files: ida/ida.h ida/ida_direct.h + ida/ida_dense.h ida/ida_band.h + ida/ida_spils.h ida/ida_spgmr.h + ida/ida_spbcgs.h ida/ida_sptfqmr.h + ida/ida_bbdpre.h ida/ida_impl.h + ida/dia_lapack.h + + +IDAS module + library: libsundials_idas.{a,so} + header files: idas/idas.h idas/idas_direct.h + idas/idas_dense.h idas/idas_band.h + idas/idas_spils.h idas/idas_spgmr.h + idas/idas_spbcgs.h idas/idas_sptfqmr.h + idas/idas_bbdpre.h idas/idas_impl.h + idas/dia_lapack.h + + +KINSOL module + libraries: libsundials_kinsol.{a,so} libsundials_fkinsol.a + header files: kinsol/kinsol.h + kinsol/kinsol_dense.h kinsol/kinsol_band.h + kinsol/kinsol_spils.h kinsol/kinsol_spgmr.h + kinsol/kinsol_spbcgs.h kinsol/kinsol_sptfqmr.h + kinsol/kinsol_bbdpre.h kinsol/kinsol_impl.h + + + +=============================== +B. autotools-based installation +=============================== + +----------------------- +B.1. Basic Installation +----------------------- + +The installation procedure outlined below will work on commodity Linux/Unix +systems without modification. However, users are still encouraged to carefully read +the entire chapter before attempting to install the SUNDIALS suite, in case +non-default choices are desired for compilers, compilation options, or the like. +Instead of reading the option list below, the user may invoke the configuration +script with the help flag to view a complete listing of available options, which +may be done by issuing + + % ./configure --help + +from within the 'srcdir' directory created above. + + +The installation steps for SUNDIALS can be as simple as + + % tar xzf solver-x.y.z.tar.gz + % cd solver-x.y.z + % ./configure + % make + % make install + +in which case the SUNDIALS header files and libraries are installed under /usr/local/include +and /usr/local/lib, respectively. Note that, by default, the example programs are not built +and installed. + +If disk space is a priority, then to delete all temporary files created by building SUNDIALS, issue + + % make clean + +To prepare the SUNDIALS distribution for a new install (using, for example, different options and/or +installation destinations), issue + + % make distclean + + +----------------------- +B.2. Installation names +----------------------- + +By default, 'make install' will install the SUNDIALS libraries under 'libdir' and the public +header files under 'includedir'. The default values for these directories are 'instdir'/lib +and 'instdir'/include, respectively, but can be changed using the configure script options +--prefix, --exec-prefix, --includedir, and --libdir (see below). For example, a global +installation of SUNDIALS on a *NIX system could be accomplished using + + % ./configure --prefix=/opt/sundials-2.3.0 + +Although all installed libraries reside under 'libdir', the public header files are further +organized into subdirectories under 'includedir'. + +The installed libraries and exported header files are listed for reference in Section A.1. + +A typical user program need not explicitly include any of the shared SUNDIALS header files +from under the 'includedir'/sundials directory since they are explicitly included by the +appropriate solver header files (e.g., cvode_dense.h includes sundials_dense.h). +However, it is both legal and safe to do so (e.g., the functions declared in +sundials_smalldense.h could be used in building a preconditioner. + + +-------------------------- +B.3. Compilers and Options +-------------------------- + +Some systems require unusual options for compilation or linking that the `configure' +script does not know about. Run `./configure --help' for details on some of the +pertinent environment variables. + +You can give `configure' initial values for these variables by setting them in the +environment. You can do that on the command line like this: + + % ./configure CC=gcc CFLAGS=-O2 F77=g77 FFLAGS=-O + +Here is a detailed description of the configure options that are pertinent to SUNDIALS. +In what follows, 'build_tree' is the directory from where 'configure' was invoked. + + +---------------------- +B.3.1. General options +---------------------- + +--help +-h + + print a summary of the options to `configure', and exit. + +--quiet +--silent +-q + + do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + + +--prefix=PREFIX + + Location for architecture-independent files. + Default: PREFIX=/usr/local + +--exec-prefix=EPREFIX + + Location for architecture-dependent files. + Default: EPREFIX=/usr/local + +--includedir=DIR + + Alternate location for header files. + Default: DIR=PREFIX/include + +--libdir=DIR + + Alternate location for libraries. + Default: DIR=EPREFIX/lib + +--disable-solver + + Although each existing solver module is built by default, support for a + given solver can be explicitly disabled using this option. + The valid values for solver are: cvode, cvodes, + ida, and kinsol. + +--enable-examples + + Available example programs are not built by default. Use this option + to enable compilation of all pertinent example programs. Upon completion of + the 'make' command, the example executables will be created under solver-specific + subdirectories of 'builddir'/examples: + + 'builddir'/examples/'solver'/serial : serial C examples + 'builddir'/examples/'solver'/parallel : parallel C examples + 'builddir'/examples/'solver'/fcmix_serial : serial Fortran examples + 'builddir'/examples/'solver'/fcmix_parallel : parallel Fortran examples + + Note: Some of these subdirectories may not exist depending upon the + solver and/or the configuration options given. + +--with-exinstdir=DIR + + Alternate location for example sources and sample output files (valid only if + examples are enabled). Note that installtion of example files can be completely + disabled by issuing DIR=no (in case building the examples is desired only as a + test of the SUNDIALS libraries). + + Default: DIR=EPREFIX/examples + +--with-cppflags=ARG + + Specify C preprocessor flags (overrides the environment variable CPPFLAGS) + (e.g., ARG=-I if necessary header files are located in nonstandard locations). + +--with-cflags=ARG + + Specify C compilation flags (overrides the environment variable CFLAGS) + +--with-ldflags=ARG + + Specify linker flags (overrides the environment variable LDFLAGS) + (e.g., ARG=-L if required libraries are located in nonstandard locations). + +--with-libs=ARG + + Specify additional libraries to be used + (e.g., ARG=-l to link with the library named libfoo.a or libfoo.so). + +--with-precision=ARG + + By default, sundials will define a real number (internally referred to as + realtype) to be a double-precision floating-point numeric data type (double + C-type); however, this option may be used to build sundials with realtype + alternatively defined as a single-precision floating-point numeric data type + (float C-type) if ARG=single, or as a long double C-type if ARG=extended. + + Default: ARG=double + +---------------------------------- +B.3.2. Options for Fortran support +---------------------------------- + +--disable-fcmix + + Using this option will disable all F77 support. The fcvode, fida, fkinsol and + fnvector modules will not be built regardless of availability. + +--with-fflags=ARG + + Specify F77 compilation flags (overrides the environment variable FFLAGS) + +-------------------------------------- +B.3.3. Options for Blas/Lapack support +-------------------------------------- + +--disable-lapack + + Disable support for the linear solver module based on Blas/Lapack. + +--with-blas=ARG + + Specifies the BLAS library to be used + +--with-lapack=ARG + + Specifies the LAPACK library to be used + +------------------------------ +B.3.4. Options for MPI support +------------------------------ + +The following configuration options are only applicable to the parallel sundials packages: + + +--disable-mpi + + Using this option will completely disable MPI support. + +--with-mpicc=ARG +--with-mpif77=ARG + + By default, the configuration utility script will use the MPI compiler + scripts named mpicc and mpif77 to compile the parallelized + sundials subroutines; however, for reasons of compatibility, different + executable names may be specified via the above options. Also, ARG=no + can be used to disable the use of MPI compiler scripts, thus causing + the serial C and F compilers to be used to compile the parallelized + sundials functions and examples. + +--with-mpi-root=MPIDIR + + This option may be used to specify which MPI implementation should be used. + The sundials configuration script will automatically check under the + subdirectories MPIDIR/include and MPIDIR/lib for the necessary + header files and libraries. The subdirectory MPIDIR/bin will also be + searched for the C and F MPI compiler scripts, unless the user uses + --with-mpicc=no or --with-mpif77=no. + +--with-mpi-incdir=INCDIR +--with-mpi-libdir=LIBDIR +--with-mpi-libs=LIBS + + These options may be used if the user would prefer not to use a preexisting + MPI compiler script, but instead would rather use a serial complier and + provide the flags necessary to compile the MPI-aware subroutines in + sundials. + + Often an MPI implementation will have unique library names and so it may + be necessary to specify the appropriate libraries to use (e.g., LIBS=-lmpich). + + Default: INCDIR=MPIDIR/include, LIBDIR=MPIDIR/lib and LIBS=-lmpi + +--with-mpi-flags=ARG + + Specify additional MPI-specific flags. + +---------------------------------- +B.3.5. Options for library support +---------------------------------- + +By default, only static libraries are built, but the following option +may be used to build shared libraries on supported platforms. + +--enable-shared + + Using this particular option will result in both static and shared versions + of the available sundials libraries being built if the systsupports + shared libraries. To build only shared libraries also specify --disable-static. + + Note: The fcvode and fkinsol libraries can only be built as static + libraries because they contain references to externally defined symbols, namely + user-supplied F77 subroutines. Although the F77 interfaces to the serial and + parallel implementations of the supplied nvector module do not contain any + unresolvable external symbols, the libraries are still built as static libraries + for the purpose of consistency. + +---------------------------- +B.3.6. Environment variables +---------------------------- + +The following environment variables can be locally (re)defined for use during the +configuration of sundials. See the next section for illustrations of these. + +CC + +F77 + + Since the configuration script uses the first C and F77 compilers found in + the current executable search path, then each relevant shell variable (CC + and F77) must be locally (re)defined in order to use a different compiler. + For example, to use xcc (executable name of chosen compiler) as the C + language compiler, use CC=xcc in the configure step. + +CFLAGS + +FFLAGS + + Use these environment variables to override the default C and F77 compilation flags. + + +--------------------------- +B.4. Configuration examples +--------------------------- + +The following examples are meant to help demonstrate proper usage of the configure options. + +To build SUNDIALS using the default C and Fortran compilers, and default mpicc and mpif77 +parallel compilers, enable compilation of examples, and install them under the default +directory /home/myname/sundials/examples, use + + % ./configure --prefix=/home/myname/sundials --enable-examples + +To disable installation of the examples, use: + % ./configure --prefix=/home/myname/sundials \ + --enable-examples --with-examples-instdir=no + +The following example builds SUNDIALS using gcc as the serial C compiler, g77 as the serial +Fortran compiler, mpicc as the parallel C compiler, mpif77 as the parallel Fortran compiler, +and uses the -g3 C compilation flag: + + % ./configure CC=gcc F77=g77 --with-cflags=-g3 --with-fflags=-g3 \ + --with-mpicc=/usr/apps/mpich/1.2.4/bin/mpicc \ + --with-mpif77=/usr/apps/mpich/1.2.4/bin/mpif77 + +The next example again builds SUNDIALS using gcc as the serial C compiler, but the +--with-mpicc=no option explicitly disables the use of the corresponding MPI compiler +script. In addition, since the --with-mpi-root option is given, the compilation flags +-I/usr/apps/mpich/1.2.4/include and -L/usr/apps/mpich/1.2.4/lib are passed to gcc when +compiling the MPI-enabled functions. +The --disable-examples option explicitly disables the examples. +The --with-mpi-libs option is required so that the configure script can check if gcc +can link with the appropriate MPI library. + + % ./configure CC=gcc --disable-examples --with-mpicc=no \ + --with-mpi-root=/usr/apps/mpich/1.2.4 \ + --with-mpi-libs=-lmpich + + + +=========================== +C. CMake-based installation +=========================== + +Using CMake as a build system for the SUNDIALS libraries has the advantage +that GUI based build configuration is possible. Also build files for Windows +development environments can be easily generated. On the Windows platform +compilers such as the Borland C++ compiler or Visual C++ compiler are natively +supported. + +The installation options are very similar to the options mentioned above. +Note, however, that CMake may not support all features and plattforms that +are supported by the autotools build system. + +------------------ +C.1. Prerequisites +------------------ + +You may need to get CMake if it isn't available on your system already. +In order to use the CMake build system, you need a fairly recent CMake version. +You can download it from http://www.cmake.org www.cmake.org. + +---------------------------- +C.2. Configuration and build +---------------------------- + +We assume here a *nix system. For other systems, the required steps are very +similar and are explained in more detail in the SUNDIALS user guides. +The installation steps are as follows: + +- uncompress solver-x.y.z.tar.gz to obtain 'srcdir' +- create the directories 'builddir' and 'instdir' +- change directory to 'builddir' +- run ccmake with 'srcdir' as an argument + +You should now see the ccmake curses interface. Press 'c' to configure your build +with the default options. (If you don't have curses on your system and cannot use +ccmake, you can configure cmake with command line options very similar to ./configure +of the autotools. You can read about this on the cmake webpage.) + +In the dialog you can adjust the build options. For details see the options above +in the autotools section. To adjust advanced options press 't' to show all the options +and settings CMake offers. + +After adjusting some options, for instance enabling the examples by turning +ENABLE_EXAMPLES to ON, you need to press 'c' again. Depending on the options, +you will see new options at the top of the list, marked with a star. After +adjusting the new options, press 'c' again. Once all options have been set, +you can press 'g' to generate the make files. + +Now you can build and install the sundials library: + % make + % make install + + diff --git a/dep/cvode-2.7.0/LICENSE b/dep/cvode-2.7.0/LICENSE new file mode 100644 index 00000000..73faf964 --- /dev/null +++ b/dep/cvode-2.7.0/LICENSE @@ -0,0 +1,64 @@ +Copyright (c) 2002, The Regents of the University of California. +Produced at the Lawrence Livermore National Laboratory. +Written by S.D. Cohen, A.C. Hindmarsh, R. Serban, + D. Shumaker, and A.G. Taylor. +UCRL-CODE-155951 (CVODE) +UCRL-CODE-155950 (CVODES) +UCRL-CODE-155952 (IDA) +UCRL-CODE-237203 (IDAS) +UCRL-CODE-155953 (KINSOL) +All rights reserved. + +This file is part of SUNDIALS. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the disclaimer below. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the disclaimer (as noted below) +in the documentation and/or other materials provided with the +distribution. + +3. Neither the name of the UC/LLNL nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Additional BSD Notice +--------------------- +1. This notice is required to be provided under our contract with +the U.S. Department of Energy (DOE). This work was produced at the +University of California, Lawrence Livermore National Laboratory +under Contract No. W-7405-ENG-48 with the DOE. + +2. Neither the United States Government nor the University of +California nor any of their employees, makes any warranty, express +or implied, or assumes any liability or responsibility for the +accuracy, completeness, or usefulness of any information, apparatus, +product, or process disclosed, or represents that its use would not +infringe privately-owned rights. + +3. Also, reference herein to any specific commercial products, +process, or services by trade name, trademark, manufacturer or +otherwise does not necessarily constitute or imply its endorsement, +recommendation, or favoring by the United States Government or the +University of California. The views and opinions of authors expressed +herein do not necessarily state or reflect those of the United States +Government or the University of California, and shall not be used for +advertising or product endorsement purposes. diff --git a/dep/cvode-2.7.0/README b/dep/cvode-2.7.0/README new file mode 100644 index 00000000..2e4d7e82 --- /dev/null +++ b/dep/cvode-2.7.0/README @@ -0,0 +1,57 @@ + SUNDIALS + SUite of Nonlinear and DIfferential/ALgebraic equation Solvers + Release 2.5.0, March 2012 + Alan Hindmarsh, Radu Serban, Carol Woodward + Center for Applied Scientific Computing, LLNL + + +The family of solvers referred to as SUNDIALS consists of the following solvers: + CVODE - for integration of ordinary differential equation systems (ODEs) + CVODE treats stiff and nonstiff ODE systems of the form + y' = f(t,y), y(t0) = y0 + CVODES - for integration and sensitivity analysis of ODEs + CVODES treats stiff and nonstiff ODE systems of the form + y' = f(t,y,p), y(t0) = y0(p) + IDA - for integration of differential-algebraic equation systems (DAEs) + IDA treats DAE systems of the form + F(t,y,y') = 0, y(t0) = y0, y'(t0) = y0' + IDAS - for integration and sensitivity analysis of DAEs + IDAS treats DAE systems of the form + F(t,y,y',p) = 0, y(t0) = y0(p), y'(t0) = y0'(p) + KINSOL - for solution of nonlinear algebraic systems + KINSOL treats nonlinear systems of the form + F(u) = 0 + +The various solvers of this family share many subordinate modules. +For this reason, it is organized as a family, with a directory structure +that exploits that sharing. Each individual solver includes documentation +on installation, along with full usage documentation. + +Warning to users who receive more than one of these individual solvers +at different times: The mixing of old and new versions SUNDIALS may fail. +To avoid such failures, obtain all desired solvers at the same time. + +For installation directions see the file INSTALL_NOTES. + +For additional information on a particular solver, see the README file +in the solver directory (e.g. src/cvode/README). + + +Release history + ++----------+-----------------------------------------------------------------+ +| | SUNDIALS | Solver version | +| Date | +----------+----------+----------+---------------------+ +| | release | CVODE | CVODES | IDA | IDAS | KINSOL | ++----------+----------+----------+----------+----------+---------------------+ +| Jul 2002 | 1.0 | 2.0 | 1.0 | 2.0 | | 2.0 | +| Dec 2004 | 2.0 | 2.2.0 | 2.1.0 | 2.2.0 | | 2.2.0 | +| Jan 2005 | 2.0.1 | 2.2.1 | 2.1.1 | 2.2.1 | | 2.2.1 | +| Mar 2005 | 2.0.2 | 2.2.2 | 2.1.2 | 2.2.2 | | 2.2.2 | +| Apr 2005 | 2.1.0 | 2.3.0 | 2.2.0 | 2.3.0 | | 2.3.0 | +| May 2005 | 2.1.1 | 2.3.0 | 2.3.0 | 2.3.0 | | 2.3.0 | +| Mar 2006 | 2.2.0 | 2.4.0 | 2.4.0 | 2.4.0 | | 2.4.0 | +| Nov 2006 | 2.3.0 | 2.5.0 | 2.5.0 | 2.5.0 | | 2.5.0 | +| May 2009 | 2.4.0 | 2.6.0 | 2.6.0 | 2.6.0 | 1.0.0 | 2.6.0 | +| Mar 2012 | 2.5.0 | 2.7.0 | 2.7.0 | 2.7.0 | 1.1.0 | 2.7.0 | ++----------+----------+----------+----------+----------+---------------------+ diff --git a/dep/cvode-2.7.0/cvode/CMakeLists.txt b/dep/cvode-2.7.0/cvode/CMakeLists.txt new file mode 100644 index 00000000..4b3225b8 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/CMakeLists.txt @@ -0,0 +1,99 @@ +# --------------------------------------------------------------- +# $Revision: 1.4 $ +# $Date: 2009/02/17 02:58:47 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the CVODE library + +INSTALL(CODE "MESSAGE(\"\nInstall CVODE\n\")") + +# Add variable cvode_SOURCES with the sources for the CVODE library +SET(cvode_SOURCES + cvode.c + cvode_io.c + cvode_direct.c + cvode_band.c + cvode_dense.c + cvode_diag.c + cvode_spils.c + cvode_spbcgs.c + cvode_spgmr.c + cvode_sptfqmr.c + cvode_bandpre.c + cvode_bbdpre.c + ) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the CVODE library +SET(shared_SOURCES + sundials_nvector.c + sundials_math.c + sundials_direct.c + sundials_band.c + sundials_dense.c + sundials_iterative.c + sundials_spbcgs.c + sundials_spgmr.c + sundials_sptfqmr.c + ) + +# Add prefix with complete path to the common SUNDIALS sources +ADD_PREFIX(${sundials_SOURCE_DIR}/sundials/ shared_SOURCES) + +# Add variable cvode_HEADERS with the exported CVODE header files +SET(cvode_HEADERS + cvode_band.h + cvode_bandpre.h + cvode_bbdpre.h + cvode_dense.h + cvode_diag.h + cvode_direct.h + cvode.h + cvode_spbcgs.h + cvode_spgmr.h + cvode_spils.h + cvode_sptfqmr.h + ) + +# Add prefix with complete path to the CVODE header files +ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvode/ cvode_HEADERS) + +# If Blas/Lapack support was enabled, set-up additional file lists +IF(LAPACK_FOUND) + SET(cvode_BL_SOURCES cvode_lapack.c) + SET(cvode_BL_HEADERS cvode_lapack.h) + ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvode/ cvode_BL_HEADERS) +ELSE(LAPACK_FOUND) + SET(cvode_BL_SOURCES "") + SET(cvode_BL_HEADERS "") +ENDIF(LAPACK_FOUND) + +# Add source directories to include directories for access to +# implementation only header files. +INCLUDE_DIRECTORIES(.) +INCLUDE_DIRECTORIES(../sundials) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Add the build target for the static CVODE library +ADD_LIBRARY(depcvode STATIC + ${cvode_SOURCES} ${cvode_BL_SOURCES} ${shared_SOURCES}) + +# Install the CVODE library +INSTALL(TARGETS depcvode DESTINATION lib) + +# Install the CVODE header files +INSTALL(FILES ${cvode_HEADERS} ${cvode_BL_HEADERS} DESTINATION include/dep/cvode) + +# Install the CVODE implementation header file +INSTALL(FILES cvode_impl.h DESTINATION include/dep/cvode) + +# +MESSAGE(STATUS "Added CVODE module") diff --git a/dep/cvode-2.7.0/cvode/LICENSE b/dep/cvode-2.7.0/cvode/LICENSE new file mode 100644 index 00000000..c0933806 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/LICENSE @@ -0,0 +1,59 @@ +Copyright (c) 2002, The Regents of the University of California. +Produced at the Lawrence Livermore National Laboratory. +Written by Scott Cohen, Alan Hindmarsh, Radu Serban, Dan Shumaker. +UCRL-CODE-155951 +All rights reserved. + +This file is part of CVODE. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the disclaimer below. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the disclaimer (as noted below) +in the documentation and/or other materials provided with the +distribution. + +3. Neither the name of the UC/LLNL nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Additional BSD Notice +--------------------- +1. This notice is required to be provided under our contract with +the U.S. Department of Energy (DOE). This work was produced at the +University of California, Lawrence Livermore National Laboratory +under Contract No. W-7405-ENG-48 with the DOE. + +2. Neither the United States Government nor the University of +California nor any of their employees, makes any warranty, express +or implied, or assumes any liability or responsibility for the +accuracy, completeness, or usefulness of any information, apparatus, +product, or process disclosed, or represents that its use would not +infringe privately-owned rights. + +3. Also, reference herein to any specific commercial products, +process, or services by trade name, trademark, manufacturer or +otherwise does not necessarily constitute or imply its endorsement, +recommendation, or favoring by the United States Government or the +University of California. The views and opinions of authors expressed +herein do not necessarily state or reflect those of the United States +Government or the University of California, and shall not be used for +advertising or product endorsement purposes. diff --git a/dep/cvode-2.7.0/cvode/README b/dep/cvode-2.7.0/cvode/README new file mode 100644 index 00000000..fe989699 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/README @@ -0,0 +1,462 @@ + CVODE + Release 2.7.0, March 2012 + Alan C. Hindmarsh and Radu Serban + Center for Applied Scientific Computing, LLNL + +CVODE is a solver for stiff and nonstiff ODE systems (initial value problem) +given in explicit form dy/dt = f(t,y). It is written in ANSI standard C. + +CVODE can be used both on serial and parallel (MPI) computers. The main +difference is in the NVECTOR module of vector kernels. The desired +version is obtained when compiling the example files by linking the +appropriate library of NVECTOR kernels. In the parallel version, +communication between processors is done with the MPI (Message Passage +Interface) system. + +When used with the serial NVECTOR module, CVODE provides both direct (dense +and band) and preconditioned Krylov (iterative) linear solvers. Three different +iterative solvers are available: scaled preconditioned GMRES (SPGMR), scaled +preconditioned BiCGStab (SPBCG), and scaled preconditioned TFQMR (SPTFQMR). +When CVODE is used with the parallel NVECTOR module, only the Krylov linear solvers +are available. (An approximate diagonal Jacobian option is available with both +versions.) For the serial version, there is a banded preconditioner module +called CVBANDPRE available for use with the Krylov solvers, while for the parallel +version there is a preconditioner module called CVBBDPRE which provides a +band-block-diagonal preconditioner. + +CVODE is part of a software family called SUNDIALS: SUite of Nonlinear +and DIfferential/ALgebraic equation Solvers. This suite consists of +CVODE, KINSOL, IDAS, and IDA, and variants of these. The directory +structure of the package supplied reflects this family relationship. + +For use with Fortran applications, a set of Fortran/C interface routines, +called FCVODE, is also supplied. These are written in C, but assume that +the user calling program and all user-supplied routines are in Fortran. + +The notes below provide the location of documentation, directions for the +installation of the CVODE package, and relevant references. Following that +is a brief history of revisions to the package. + + +A. Documentation +---------------- + +/sundials/doc/cvode/ contains PDF files for the CVODE User Guide [1] (cv_guide.pdf) +and the CVODE Examples [2] (cv_examples.pdf) documents. + + +B. Installation +--------------- + +For basic installation instructions see the file /sundials/INSTALL_NOTES. +For complete installation instructions see the "CVODE Installation Procedure" +chapter in the CVODE User Guide. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0," + LLNL technical report UCRL-SM-208108, December 2011. + +[2] A. C. Hindmarsh and R. Serban, "Example Programs for CVODE v2.7.0," + LLNL technical report UCRL-SM-208110, December 2011. + +[3] S.D. Cohen and A.C. Hindmarsh, "CVODE, a Stiff/nonstiff ODE Solver in C," + Computers in Physics, 10(2), pp. 138-143, 1996. + +[4] A. C. Hindmarsh, P. N. Brown, K. E. Grant, S. L. Lee, R. Serban, + D. E. Shumaker, and C. S. Woodward, "SUNDIALS, Suite of Nonlinear and + Differential/Algebraic Equation Solvers," ACM Trans. Math. Softw., + 31(3), pp. 363-396, 2005. + + +D. Releases +----------- + +v. 2.7.0 - Mar. 2012 +v. 2.6.0 - May 2009 +v. 2.5.0 - Nov. 2006 +v. 2.4.0 - Mar. 2006 +v. 2.3.0 - Apr. 2005 +v. 2.2.2 - Mar. 2005 +v. 2.2.1 - Jan. 2005 +v. 2.2.0 - Dec. 2004 +v. 2.0 - Jul. 2002 (first SUNDIALS release) +v. 1.0 - Mar. 2002 (CVODE and PVODE combined) +v. 1.0 (PVODE) - Jul. 1997 (date written) +v. 1.0 (CVODE) - Sep. 1994 (date written) + + +E. Revision History +------------------- + +v. 2.6.0 (May 2009) ---> v. 2.7.0 (Mar. 2012) +--------------------------------------------- + +- Bug fixes + - in CVSetTqBDF, the logic was changed to avoid a divide by zero. + - after the solver memory is created, it is set to zero before being filled. + - in each linear solver interface function, the linear solver memory is + freed on an error return, and the **Free function now includes a line + setting to NULL the main memory pointer to the linear solver memory. + - in rootfinding functions CVRcheck1/CVRcheck2, when an exact zero is found, + the array glo at the left endpoint is adjusted instead of shifting tlo. + +- Changes to user interface + - One significant design change was made with this release: The problem + size and its relatives, bandwidth parameters, related internal indices, + pivot arrays, and the optional output lsflag, have all been + changed from type int to type long int, except for the + problem size and bandwidths in user calls to routines specifying + BLAS/LAPACK routines for the dense/band linear solvers. The function + NewIntArray is replaced by a pair NewIntArray/NewLintArray, + for int and long int arrays, respectively. + - in the installation files, we modified the treatment of the macro + SUNDIALS_USE_GENERIC_MATH, so that the parameter GENERIC_MATH_LIB + is either defined (with no value) or not defined. + +v. 2.5.0 (Nov. 2006) ---> v. 2.6.0 (May 2009) +--------------------------------------------- + +- New features + - added a new linear solver module based on Blas + Lapack for + both dense and banded matrices. + - added optional input to specify which direction of zero-crossing + is to be monitored while performing root-finding. The root information + array iroots (returned by CVodeGetRootInfo) also encodes the + direction of zero-crossing. + +- Bug fixes + - in the rootfinding algorithm, fixed a bug resulting in unnecessary + evaluations of the root functions after reinitialization of the + solver right after a return at a root. + - in the initial step size calculation, restrict h based on tstop. + - modified the setting and use of the tq[] array. Now tq[i] (i = 1,2,3) + are defined to be the reciprocals of what they were before. This + eliminates a rare crash that can occur with xistar_inv = 0. + +- Changes to user interface + - renamed all **Malloc functions to **Init + - tolerances are now specified through separate functions instead of + the initialization functions CVodeInit (former CVodeMalloc) and + CVodeReInit. Depending on the tolerance type, one of 3 functions + must be called before the first call to CVode. + - removed function inputs from argument lists of all re-initialization + functions. + - all user-supplied functions now receive the same pointer to user data + (instead of having different ones for the system evaluation, Jacobian + information functions, etc.). + - removed CV_NORMAL_TSTOP and CV_ONE_STEP_TSTOP named constants for the + itask argument to CVode. A tstop value is now both set and activated + through CVodeSetStopTime. Once tstop is reached it is also deactivated. + A new value can be then specified by calling again CVodeSetStopTime. + - common functionality for all direct linear solvers (dense, band, and + the new Lapack solver) has been collected into the DLS (Direct Linear + Solver) module, similar to the SPILS module for the iterative linear + solvers. All optional input and output functions for these linear + solver now have the prefix 'CVDls'. In addition, in order to include + the new Lapack-based linear solver, all dimensions for these linear + solvers (problem sizes, bandwidths, etc) are now of type 'int' + (instead of 'long int'). + - the initialization functions for the two preconditioner modules, + CVBANDPRE and CVBBDPRE were renamed ***Init (from ***Alloc) and they + do not return a pointer to preconditioner memory anymore. Instead, + all preconditioner module-related functions are now called with + the main solver memory pointer as their first argument. When using + one of these two modules, there is no need to use special functions + to attach one of the SPILS linear solvers (instead use one of + CVSpgmr, CVSpbcg, or CVSptfqmr). Moreover, there is no need to call + a memory deallocation function for the preconditioner module. + - changed names CVSpilsSetDelt and delt to CVSpilsSetEpsLin and eplifac. + - added the error return CV_RTFUNC_FAIL. + - changes corresponding to the above were made to the FCMIX interface. + + +v. 2.4.0 (Mar. 2006) ---> v. 2.5.0 (Nov. 2006) +---------------------------------------------- + +- Bug fixes + - added a roundoff factor when testing whether tn was just returned + (in root finding) to prevent an unnecessary return. + - fixed wrong logic in final stopping tests: now we check if + tout was reached before checking if tstop was reached. + +- Changes related to the build system + - reorganized source tree: header files in ${srcdir}/include/cvode, + source files in ${srcdir}/src/cvode, fcmix source files in + ${srcdir}/src/cvode/fcmix, examples in ${srcdir}/examples/cvode + - exported header files are installed unde ${includedir}/cvode + +- Changes to user interface + - all included header files use relative paths from ${includedir} + +v. 2.3.0 (Apr. 2005) ---> v. 2.4.0 (Mar. 2006) +---------------------------------------------- + +- New features + - added CVSPBCG interface module to allow CVODE to interface with the + shared SPBCG (scaled preconditioned Bi-CGSTAB) linear solver module. + - added CVSPTFQMR interface module to allow CVODE to interface with + the shared SPTFQMR (scaled preconditioned TFQMR) linear solver module. + - added support for SPBCG and SPTFQMR to the CVBBDPRE and CVBANDPRE + preconditioner modules. + - added support for interpreting failures in user-supplied functions. + +- Changes to user interface + - changed argument of CVodeFree, CVBandPrecFree, and CVBBDPrecFree to + be the address of the respective memory block pointer, so that its + NULL value is propagated back to the calling function. + - added CVSPBCG module which defines appropriate CVSpbcg* functions to + allow CVODE to interface with the shared SPBCG linear solver module. + - added CVBBDSpbcg function to CVBBDPRE module and CVBPSpbcg function to + CVBANDPRE module to support SPBCG linear solver module. + - added CVBBDSptfqmr function to CVBBDPRE module and CVBPSptfqmr function to + CVBANDPRE module to support SPTFQMR linear solver module. + - changed function type names (not the actual definition) to accomodate + all the Scaled Preconditioned Iterative Linear Solvers now available: + CVSpgmrJactimesVecFn -> CVSpilsJacTimesVecFn + CVSpgmrPrecSetupFn -> CVSpilsPrecSetupFn + CVSpgmrPrecSolveFn -> CVSpilsPrecSolveFn + - changed function types so that all user-supplied functions return + an integer flag (not all of them currently used). + - changed some names for CVBBDPRE and CVBANDPRE function outputs + - added option for user-supplied error handler function. + - renamed all exported header files (except for cvode.h, all header files + have the prefix 'cvode_') + - changed naming scheme for CVODE examples + +- Changes to the FCVODE module + - added support for CVSPBCG/SPBCG (added FCV*SPBCG* functions). + - added support for CVSPTFQMR/SPTFQMR (added FCV*SPTFQMR* functions). + - optional inputs are now set using routines FCVSETIIN (integer inputs) + and FCVSETRIN (real inputs) through pairs key-value. Optional outputs + are still obtained from two arrays (IOUT and ROUT), owned by the user + and passed as arguments to FCVMALLOC. Note that the argument OPTIN + was removed from FCVMALLOC. + - changed the prototypes of user-supplied functions so that they all + return an error flag as their last argument (not all of them currently used). + - the arguments OPTIN, IOPT, and ROPT were removed from FCVREINIT + +- Changes related to the build system + - updated configure script and Makefiles for Fortran examples to avoid C++ + compiler errors (now use CC and MPICC to link only if necessary) + - the main CVODE header file (cvode.h) is still exported to the install include + directory. However, all other CVODE header files are exported into a 'cvode' + subdirectory of the install include directory. + - the CVODE library now contains all shared object files (there is no separate + libsundials_shared library anymore) + +v. 2.2.2 (Mar. 2005) ---> v. 2.3.0 (Apr. 2005) +---------------------------------------------- + +- New features + - added option for user-provided error weight computation function + (of type CVEwtFn specified through CVodeSetEwtFn). + +- Changes to user interface + - CVODE now stores tolerances through values rather than references + (to resolve potential scoping issues). + - CVODE now passes information back to the user through values rather + than references (error weights, estimated local errors, root info) + - CVodeMalloc, CVodeReInit, CVodeSetTolerances: added option itol=CV_WF + to indicate user-supplied function for computing the error weights; + reltol is now declared as realtype. Note that it is now illegal to call + CVodeSetTolerances before CVodeMalloc. It is now legal to deallocate + the absolute tolerance N_Vector right after its use. + - CVodeGetErrorWeights: the user is now responsible for allocating space + for the N_Vector in which error weights will be copied. + - CVodeGetEstLocalErrors: the user is now responsible for allocating space + for the N_Vector in which estimated local errors will be copied. + - CVodeGetRootInfo: the user is now responsible for allocating space + for the int array in which root information will be copied. + - Passing a value of 0 for the maximum step size, the minimum step + size, or for maxsteps results in the solver using the corresponding + default value (infinity, 0, 500, respectively) + - Several optional input functions were combined into a single one + (CVodeRootInit and CvodeSetGdata, CVDenseSetJacFn and CVDenseSetJacData, + CVBandSetJacFn and CVBandSetJacData, CVSpgmrSetPrecSolveFn and + CVSpgmrSetPrecSetFn and CVSpgmrSetPrecData, CVSpgmrSetJacTimesVecFn and + CVSpgmrSetJacData). + +- Changes to the FCVODE module: + - Added option for user-supplied error weight computation subroutine + (FCVEWT). Use FCVEWTSET to indicate that FCVEWT is provided. + - Due to the changes to the main solver, if FCVPSOL is provided then + FCVPSET must also be defined, even if it is empty. + +v. 2.2.1 (Jan. 2005) ---> v. 2.2.2 (Mar. 2005) +---------------------------------------------- + +- Bug fixes + - fixed bug in CVode function: Initial setting of tretlast = *tret = tn removed + (correcting erroneous behavior at first call to CVRcheck3). + - removed redundant setting of tretlast = *tret = tn at CLOSE_ROOTS return from CVode. + - modified FCMIX files to avoid C++ compiler errors + - changed implicit type conversion to explicit in check_flag() routine in + examples to avoid C++ compiler errors + +- Changes to documentation + - added section with numerical values of all input and output solver constants + - added more detailed notes on the type of absolute tolerances + - added more details on ownership of memory for the array returned by CVodeGetRootInfo + - corrected/added descriptions of error returns. + - added description of --with-mpi-flags option + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.2.0 (Dec. 2004) ---> v. 2.2.1 (Jan. 2005) +---------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 2.0 (Jul. 2002) ---> v. 2.2.0 (Dec. 2004) +-------------------------------------------- + +- New features + - added option to specify a value of the independent variable (time) + past which the integration is never to proceed. + - added rootfinding capabilities. + - added option to disable all error messages. + +- Changes related to the NVECTOR module (see also file sundials/shared/README) + - removed machEnv, redefined table of vector operations (now contained + in the N_Vector structure itself). + - all CVODE functions create new N_Vector variables through cloning, using + an N_Vector passed by the user as a template. + +- Changes to type names and CVODE constants + - removed type 'integertype'; instead use int or long int, as appropriate. + - restructured the list of return values from the various CVODE functions. + - changed all CVODE constants (inputs and return values) to have the + prefix 'CV_' (e.g. CV_SUCCESS). + - renamed various function types to have the prefix 'CV' (e.g. CVRhsFn). + +- Changes to optional input/ouput + - added CVodeSet* and CVodeGet* functions for optional inputs/outputs, + replacing the arrays iopt and ropt. + - added new optional inputs (e.g. maximum number of Newton iterations, + maximum number of convergence failures, etc). + - the value of the last return flag from any function within a linear + solver module can be obtained as an optional output (e.g. CVDenseGetLastFlag). + +- Changes to user-callable functions + - added new function CVodeCreate which initializes the CVODE solver + object and returns a pointer to the CVODE memory block. + - removed N (problem size) from all functions except the initialization + functions for the direct linear solvers (CVDense and CVBand). + - shortened argument lists of most CVODE functions (the arguments that + were dropped can now be specified through CVodeSet* functions). + - removed reinitialization functions for band/dense/SPGMR linear + solvers (same functionality can be obtained using CV*Set* functions). + - in CVBBDPRE, added a new function, CVBBDSpgmr to initialize the + SPGMR linear solver with the BBD preconditioner. + - function names changed in CVBANDPRE and CVBBDPRE for uniformity. + +- Changes to user-supplied functions + - removed N (probem dimension) from argument lists. + - shortened argument lists for user dense/band/SPGMR Jacobian routines. + (Data needed to do difference quotients is accessible in other ways.) + - in CVSPGMR, shortened argument lists for user preconditioner functions. + +- Changes to the FCVODE module + - revised to use underscore and precision flags at compile time (from + configure); example sources are preprocessed accordingly. + - reorganized FCVODE into fewer files. + - added tstop options, and interfaces to CVBANDPRE and rootfinding features. + - use CV*Set* and CV*Get* functions from CVODE (although the optional I/O + is still communicated to the user of FCVODE through arrays IOPT and ROPT). + - added new optional inputs and outputs (e.g.tstop, nlscoef, maxnef, maxcor, + maxncf, etc.) and rearranged locations in IOPT and ROPT for uniformity. + + +Summary of previous revisions (YYYYMMDD) (significant revisions only) +--------------------------------------------------------------------- + +Combined CVODE package (Mar. 2002 - Jul. 2002) +----------------------------------------------- + +20020313 Modified to work with new NVECTOR abstraction. + Changed name PVBBDPRE to CVBBDPRE, etc. +20020321 Revisions throughout to reflect usage changes for NVECTOR modules. + Changed dense/band backsolve argument b type from N_Vector to real*. +20020328 In FCVODE, added interfaces to dense/band linear solvers. +20020626 Changed type names real/integer to realtype/integertype. + +PVODE (Jul. 1995 - Mar. 2002) +----------------------------- + +19950726 DATE WRITTEN; MPI version of VECTOR module written, creating + MPI_PVODE; makefiles written with defs. specific to IBM-SP. +19950929 Formed package directory structure; added Cray-T3D defs. to Makefiles. +19970219 FPVODE package of Fortran/C interfaces written, with examples. +19970724 Wrote preconditioner module BBDPRE and Fortran/C interface. +19970811 Type names changed to LLNL_FLOAT etc. +19970813 Changed first FFUN arg. in FPVODE to local length NLOC. +19971103 Added argc,argv to PVInitMPI call list; removed ICOMM + argument to FPVINITMPI (pass MPI_COMM_WORLD). +19971201 Name changes: PVInitMPI/PVFreeMPI to PVecInitMPI/PVecFreeMPI. +19971208 Added optional argument dqrely to BBDPRE. +19971217 Revised FPVODE to use name mappings via parameters in fcmixpar.h. +19980120 Name changes: VECTOR to NVECTOR etc. +19980206 Name changes: BBDPRE to PVBBDPRE, FFUN to PVFUN, etc. +19980508 Wrappers on header files for C++ use; type bool changed to boole. +19980923 In PVBBDPRE and Fortran interface, added two half-bandwidth arguments. +20000316 SPGMR module modified for correct treatment of scalings. + added new routine CVReInit for re-initialization of CVODE. +20000320 In NVECTOR module: removed comm = NULL option in PVecInitMPI. +20000321 Added interface FPVREINIT, and expanded diagkf example. +20000719 Fixed memory leak bugs in CVReInit and FPVREINIT. +20000808 Fixed bug in N_VMin routine. +20011114 Added option for stability limit detection algorithm STALD. +20011220 Default type 'integer' changed to 'long int' in llnltyps.h. +20011220 Optional input ropt[HMAX] examined on every call to CVode. +20011221 Optional input iopt[MXHNIL] = -1 means no t+h=t messages. +20011228 Added arguments to CVSpgmr: jtimes (user J*v routine), jac_data. + Added optional jtimes to FPVODE. Revised examples accordingly. +20020114 Linear solver modules reorganized: specification routines + CVDiag and CVSpgmr perform malloc operations and return a + completion flag. Re-use of linear solver memory is allowed if + linear solver choice and parameters are unchanged. Fortran + interface routines modified analogously. All examples + modified to receive and test new return flag. +20020301 Added CVReInitSpgmr routine to CVSPGMR module, and added Fortran + interfaces to it. Revised cvdemk and pvdiagkf accordingly. +20020306 Added PVReInitBBD routine to PVBBDPRE, and added Fortran interface + to it. Revised pvkxb and pvidagkbf examples accordingly. + +CVODE (1993 - Mar. 2002) +------------------------ + +1993-94 DATE WRITTEN. First released 2 September 1994. +19970811 Type names changed to LLNL_FLOAT etc. +19980120 Name changes: VECTOR to NVECTOR etc. +19980508 Wrappers on header files for C++ use; type bool changed to boole. +20000316 SPGMR module modified for correct treatment of scalings. + Added CVODE re-initialization routine CVReInit. +20000323 Added band preconditioner module CVBANDPRE. +20000719 Fixed memory leak bugs in CVReInit. +20000808 Fixed bug in N_VMin routine. +20011114 Added option for stability limit detection algorithm STALD. +20011115 Reorganized DENSE module, with smalldense.* files separate. +20011220 Default type 'integer' changed to 'long int' in llnltyps.h. +20011220 Optional input ropt[HMAX] examined on every call to CVode. +20011221 Optional input iopt[MXHNIL] = -1 means no t+h=t messages. +20011228 Added arguments to CVSpgmr: jtimes (user J*v routine), jac_data. +20020114 Linear solver modules reorganized: linear solver specification + routines perform malloc operations and return a completion flag. + Re-use of linear solver memory is allowed if linear solver choice + and parameters are unchanged. All examples modified accordingly. +20020301 Added ReInit routine to CVDENSE, CVBAND, CVSPGMR modules. +20020305 Added CVReInitBandPre routine to CVBANDPRE module. + + diff --git a/dep/cvode-2.7.0/cvode/cvode.c b/dep/cvode-2.7.0/cvode/cvode.c new file mode 100644 index 00000000..466a6fe0 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode.c @@ -0,0 +1,4191 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.24 $ + * $Date: 2012/03/06 21:58:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Dan Shumaker @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the main CVODE integrator. + * It is independent of the CVODE linear solver in use. + * ----------------------------------------------------------------- + */ + +/*=================================================================*/ +/* Import Header Files */ +/*=================================================================*/ + +#include +#include +#include +#include + +#include "cvode_impl.h" +#include +#include + +/*=================================================================*/ +/* Macros */ +/*=================================================================*/ + +/* Macro: loop */ +#define loop for(;;) + +/*=================================================================*/ +/* CVODE Private Constants */ +/*=================================================================*/ + +#define ZERO RCONST(0.0) /* real 0.0 */ +#define TINY RCONST(1.0e-10) /* small number */ +#define TENTH RCONST(0.1) /* real 0.1 */ +#define POINT2 RCONST(0.2) /* real 0.2 */ +#define FOURTH RCONST(0.25) /* real 0.25 */ +#define HALF RCONST(0.5) /* real 0.5 */ +#define ONE RCONST(1.0) /* real 1.0 */ +#define TWO RCONST(2.0) /* real 2.0 */ +#define THREE RCONST(3.0) /* real 3.0 */ +#define FOUR RCONST(4.0) /* real 4.0 */ +#define FIVE RCONST(5.0) /* real 5.0 */ +#define TWELVE RCONST(12.0) /* real 12.0 */ +#define HUN RCONST(100.0) /* real 100.0 */ + +/*=================================================================*/ +/* CVODE Routine-Specific Constants */ +/*=================================================================*/ + +/* + * Control constants for lower-level functions used by CVStep + * ---------------------------------------------------------- + * + * CVHin return values: + * CV_SUCCESS + * CV_RHSFUNC_FAIL + * CV_TOO_CLOSE + * + * CVStep control constants: + * DO_ERROR_TEST + * PREDICT_AGAIN + * + * CVStep return values: + * CV_SUCCESS, + * CV_LSETUP_FAIL, CV_LSOLVE_FAIL, + * CV_RHSFUNC_FAIL, CV_RTFUNC_FAIL + * CV_CONV_FAILURE, CV_ERR_FAILURE, + * CV_FIRST_RHSFUNC_ERR + * + * CVNls input nflag values: + * FIRST_CALL + * PREV_CONV_FAIL + * PREV_ERR_FAIL + * + * CVNls return values: + * CV_SUCCESS, + * CV_LSETUP_FAIL, CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL, + * CONV_FAIL, RHSFUNC_RECVR + * + * CVNewtonIteration return values: + * CV_SUCCESS, + * CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL + * CONV_FAIL, RHSFUNC_RECVR, + * TRY_AGAIN + * + */ + +#define DO_ERROR_TEST +2 +#define PREDICT_AGAIN +3 + +#define CONV_FAIL +4 +#define TRY_AGAIN +5 + +#define FIRST_CALL +6 +#define PREV_CONV_FAIL +7 +#define PREV_ERR_FAIL +8 + +#define RHSFUNC_RECVR +9 + +/* + * Control constants for lower-level rootfinding functions + * ------------------------------------------------------- + * + * CVRcheck1 return values: + * CV_SUCCESS, + * CV_RTFUNC_FAIL, + * CVRcheck2 return values: + * CV_SUCCESS + * CV_RTFUNC_FAIL, + * CLOSERT + * RTFOUND + * CVRcheck3 return values: + * CV_SUCCESS + * CV_RTFUNC_FAIL, + * RTFOUND + * CVRootfind return values: + * CV_SUCCESS + * CV_RTFUNC_FAIL, + * RTFOUND + */ + +#define RTFOUND +1 +#define CLOSERT +3 + +/* + * Control constants for tolerances + * -------------------------------- + */ + +#define CV_NN 0 +#define CV_SS 1 +#define CV_SV 2 +#define CV_WF 3 + +/* + * Algorithmic constants + * --------------------- + * + * CVodeGetDky and CVStep + * + * FUZZ_FACTOR + * + * CVHin + * + * HLB_FACTOR + * HUB_FACTOR + * H_BIAS + * MAX_ITERS + * + * CVodeCreate + * + * CORTES + * + * CVStep + * + * THRESH + * ETAMX1 + * ETAMX2 + * ETAMX3 + * ETAMXF + * ETAMIN + * ETACF + * ADDON + * BIAS1 + * BIAS2 + * BIAS3 + * ONEPSM + * + * SMALL_NST nst > SMALL_NST => use ETAMX3 + * MXNCF max no. of convergence failures during one step try + * MXNEF max no. of error test failures during one step try + * MXNEF1 max no. of error test failures before forcing a reduction of order + * SMALL_NEF if an error failure occurs and SMALL_NEF <= nef <= MXNEF1, then + * reset eta = MIN(eta, ETAMXF) + * LONG_WAIT number of steps to wait before considering an order change when + * q==1 and MXNEF1 error test failures have occurred + * + * CVNls + * + * NLS_MAXCOR maximum no. of corrector iterations for the nonlinear solver + * CRDOWN constant used in the estimation of the convergence rate (crate) + * of the iterates for the nonlinear equation + * DGMAX iter == CV_NEWTON, |gamma/gammap-1| > DGMAX => call lsetup + * RDIV declare divergence if ratio del/delp > RDIV + * MSBP max no. of steps between lsetup calls + * + */ + + +#define FUZZ_FACTOR RCONST(100.0) + +#define HLB_FACTOR RCONST(100.0) +#define HUB_FACTOR RCONST(0.1) +#define H_BIAS HALF +#define MAX_ITERS 4 + +#define CORTES RCONST(0.1) + +#define THRESH RCONST(1.5) +#define ETAMX1 RCONST(10000.0) +#define ETAMX2 RCONST(10.0) +#define ETAMX3 RCONST(10.0) +#define ETAMXF RCONST(0.2) +#define ETAMIN RCONST(0.1) +#define ETACF RCONST(0.25) +#define ADDON RCONST(0.000001) +#define BIAS1 RCONST(6.0) +#define BIAS2 RCONST(6.0) +#define BIAS3 RCONST(10.0) +#define ONEPSM RCONST(1.000001) + +#define SMALL_NST 10 +#define MXNCF 10 +#define MXNEF 7 +#define MXNEF1 3 +#define SMALL_NEF 2 +#define LONG_WAIT 10 + +#define NLS_MAXCOR 3 +#define CRDOWN RCONST(0.3) +#define DGMAX RCONST(0.3) + +#define RDIV TWO +#define MSBP 20 + +/*=================================================================*/ +/* Private Helper Functions Prototypes */ +/*=================================================================*/ + +static booleantype CVCheckNvector(N_Vector tmpl); + +static int CVInitialSetup(CVodeMem cv_mem); + +static booleantype CVAllocVectors(CVodeMem cv_mem, N_Vector tmpl); +static void CVFreeVectors(CVodeMem cv_mem); + +static int CVEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight); +static int CVEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight); + +static int CVHin(CVodeMem cv_mem, realtype tout); +static realtype CVUpperBoundH0(CVodeMem cv_mem, realtype tdist); +static int CVYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm); + +static int CVStep(CVodeMem cv_mem); + +static int CVsldet(CVodeMem cv_mem); + +static void CVAdjustParams(CVodeMem cv_mem); +static void CVAdjustOrder(CVodeMem cv_mem, int deltaq); +static void CVAdjustAdams(CVodeMem cv_mem, int deltaq); +static void CVAdjustBDF(CVodeMem cv_mem, int deltaq); +static void CVIncreaseBDF(CVodeMem cv_mem); +static void CVDecreaseBDF(CVodeMem cv_mem); + +static void CVRescale(CVodeMem cv_mem); + +static void CVPredict(CVodeMem cv_mem); + +static void CVSet(CVodeMem cv_mem); +static void CVSetAdams(CVodeMem cv_mem); +static realtype CVAdamsStart(CVodeMem cv_mem, realtype m[]); +static void CVAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum); +static realtype CVAltSum(int iend, realtype a[], int k); +static void CVSetBDF(CVodeMem cv_mem); +static void CVSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0, + realtype alpha0_hat, realtype xi_inv, realtype xistar_inv); + +static int CVNls(CVodeMem cv_mem, int nflag); +static int CVNlsFunctional(CVodeMem cv_mem); +static int CVNlsNewton(CVodeMem cv_mem, int nflag); +static int CVNewtonIteration(CVodeMem cv_mem); + +static int CVHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t, + int *ncfPtr); + +static void CVRestore(CVodeMem cv_mem, realtype saved_t); + +static int CVDoErrorTest(CVodeMem cv_mem, int *nflagPtr, + realtype saved_t, int *nefPtr, realtype *dsmPtr); + +static void CVCompleteStep(CVodeMem cv_mem); + +static void CVPrepareNextStep(CVodeMem cv_mem, realtype dsm); +static void CVSetEta(CVodeMem cv_mem); +static realtype CVComputeEtaqm1(CVodeMem cv_mem); +static realtype CVComputeEtaqp1(CVodeMem cv_mem); +static void CVChooseEta(CVodeMem cv_mem); +static void CVBDFStab(CVodeMem cv_mem); + +static int CVHandleFailure(CVodeMem cv_mem,int flag); + +static int CVRcheck1(CVodeMem cv_mem); +static int CVRcheck2(CVodeMem cv_mem); +static int CVRcheck3(CVodeMem cv_mem); +static int CVRootfind(CVodeMem cv_mem); + +/* + * ================================================================= + * EXPORTED FUNCTIONS IMPLEMENTATION + * ================================================================= + */ + +/* + * CVodeCreate + * + * CVodeCreate creates an internal memory block for a problem to + * be solved by CVODE. + * If successful, CVodeCreate returns a pointer to the problem memory. + * This pointer should be passed to CVodeInit. + * If an initialization error occurs, CVodeCreate prints an error + * message to standard err and returns NULL. + */ + +void *CVodeCreate(int lmm, int iter) +{ + int maxord; + CVodeMem cv_mem; + + /* Test inputs */ + + if ((lmm != CV_ADAMS) && (lmm != CV_BDF)) { + CVProcessError(NULL, 0, "CVODE", "CVodeCreate", MSGCV_BAD_LMM); + return(NULL); + } + + if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) { + CVProcessError(NULL, 0, "CVODE", "CVodeCreate", MSGCV_BAD_ITER); + return(NULL); + } + + cv_mem = NULL; + cv_mem = (CVodeMem) malloc(sizeof(struct CVodeMemRec)); + if (cv_mem == NULL) { + CVProcessError(NULL, 0, "CVODE", "CVodeCreate", MSGCV_CVMEM_FAIL); + return(NULL); + } + + /* Zero out cv_mem */ + memset(cv_mem, 0, sizeof(struct CVodeMemRec)); + + maxord = (lmm == CV_ADAMS) ? ADAMS_Q_MAX : BDF_Q_MAX; + + /* copy input parameters into cv_mem */ + cv_mem->cv_lmm = lmm; + cv_mem->cv_iter = iter; + + /* Set uround */ + cv_mem->cv_uround = UNIT_ROUNDOFF; + + /* Set default values for integrator optional inputs */ + cv_mem->cv_f = NULL; + cv_mem->cv_user_data = NULL; + cv_mem->cv_itol = CV_NN; + cv_mem->cv_user_efun = FALSE; + cv_mem->cv_efun = NULL; + cv_mem->cv_e_data = NULL; + cv_mem->cv_ehfun = CVErrHandler; + cv_mem->cv_eh_data = cv_mem; + cv_mem->cv_errfp = stderr; + cv_mem->cv_qmax = maxord; + cv_mem->cv_mxstep = MXSTEP_DEFAULT; + cv_mem->cv_mxhnil = MXHNIL_DEFAULT; + cv_mem->cv_sldeton = FALSE; + cv_mem->cv_hin = ZERO; + cv_mem->cv_hmin = HMIN_DEFAULT; + cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT; + cv_mem->cv_tstopset = FALSE; + cv_mem->cv_maxcor = NLS_MAXCOR; + cv_mem->cv_maxnef = MXNEF; + cv_mem->cv_maxncf = MXNCF; + cv_mem->cv_nlscoef = CORTES; + + /* Initialize root finding variables */ + + cv_mem->cv_glo = NULL; + cv_mem->cv_ghi = NULL; + cv_mem->cv_grout = NULL; + cv_mem->cv_iroots = NULL; + cv_mem->cv_rootdir = NULL; + cv_mem->cv_gfun = NULL; + cv_mem->cv_nrtfn = 0; + cv_mem->cv_gactive = NULL; + cv_mem->cv_mxgnull = 1; + + /* Set the saved value qmax_alloc */ + + cv_mem->cv_qmax_alloc = maxord; + + /* Initialize lrw and liw */ + + cv_mem->cv_lrw = 58 + 2*L_MAX + NUM_TESTS; + cv_mem->cv_liw = 40; + + /* No mallocs have been done yet */ + + cv_mem->cv_VabstolMallocDone = FALSE; + cv_mem->cv_MallocDone = FALSE; + + /* Return pointer to CVODE memory block */ + + return((void *)cv_mem); +} + +/*-----------------------------------------------------------------*/ + +#define iter (cv_mem->cv_iter) +#define lmm (cv_mem->cv_lmm) +#define lrw (cv_mem->cv_lrw) +#define liw (cv_mem->cv_liw) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeInit + * + * CVodeInit allocates and initializes memory for a problem. All + * problem inputs are checked for errors. If any error occurs during + * initialization, it is reported to the file whose file pointer is + * errfp and an error flag is returned. Otherwise, it returns CV_SUCCESS + */ + +int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0) +{ + CVodeMem cv_mem; + booleantype nvectorOK, allocOK; + long int lrw1, liw1; + int i,k; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check for legal input parameters */ + + if (y0==NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeInit", MSGCV_NULL_Y0); + return(CV_ILL_INPUT); + } + + if (f == NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeInit", MSGCV_NULL_F); + return(CV_ILL_INPUT); + } + + /* Test if all required vector operations are implemented */ + + nvectorOK = CVCheckNvector(y0); + if(!nvectorOK) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeInit", MSGCV_BAD_NVECTOR); + return(CV_ILL_INPUT); + } + + /* Set space requirements for one N_Vector */ + + if (y0->ops->nvspace != NULL) { + N_VSpace(y0, &lrw1, &liw1); + } else { + lrw1 = 0; + liw1 = 0; + } + cv_mem->cv_lrw1 = lrw1; + cv_mem->cv_liw1 = liw1; + + /* Allocate the vectors (using y0 as a template) */ + + allocOK = CVAllocVectors(cv_mem, y0); + if (!allocOK) { + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* All error checking is complete at this point */ + + /* Copy the input parameters into CVODE state */ + + cv_mem->cv_f = f; + cv_mem->cv_tn = t0; + + /* Set step parameters */ + + cv_mem->cv_q = 1; + cv_mem->cv_L = 2; + cv_mem->cv_qwait = cv_mem->cv_L; + cv_mem->cv_etamax = ETAMX1; + + cv_mem->cv_qu = 0; + cv_mem->cv_hu = ZERO; + cv_mem->cv_tolsf = ONE; + + /* Set the linear solver addresses to NULL. + (We check != NULL later, in CVode, if using CV_NEWTON.) */ + + cv_mem->cv_linit = NULL; + cv_mem->cv_lsetup = NULL; + cv_mem->cv_lsolve = NULL; + cv_mem->cv_lfree = NULL; + cv_mem->cv_lmem = NULL; + + /* Initialize zn[0] in the history array */ + + N_VScale(ONE, y0, cv_mem->cv_zn[0]); + + /* Initialize all the counters */ + + cv_mem->cv_nst = 0; + cv_mem->cv_nfe = 0; + cv_mem->cv_ncfn = 0; + cv_mem->cv_netf = 0; + cv_mem->cv_nni = 0; + cv_mem->cv_nsetups = 0; + cv_mem->cv_nhnil = 0; + cv_mem->cv_nstlp = 0; + cv_mem->cv_nscon = 0; + cv_mem->cv_nge = 0; + + cv_mem->cv_irfnd = 0; + + /* Initialize other integrator optional outputs */ + + cv_mem->cv_h0u = ZERO; + cv_mem->cv_next_h = ZERO; + cv_mem->cv_next_q = 0; + + /* Initialize Stablilty Limit Detection data */ + /* NOTE: We do this even if stab lim det was not + turned on yet. This way, the user can turn it + on at any time */ + + cv_mem->cv_nor = 0; + for (i = 1; i <= 5; i++) + for (k = 1; k <= 3; k++) + cv_mem->cv_ssdat[i-1][k-1] = ZERO; + + /* Problem has been successfully initialized */ + + cv_mem->cv_MallocDone = TRUE; + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeReInit + * + * CVodeReInit re-initializes CVODE's memory for a problem, assuming + * it has already been allocated in a prior CVodeInit call. + * All problem specification inputs are checked for errors. + * If any error occurs during initialization, it is reported to the + * file whose file pointer is errfp. + * The return value is CV_SUCCESS = 0 if no errors occurred, or + * a negative value otherwise. + */ + +int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0) +{ + CVodeMem cv_mem; + int i,k; + + /* Check cvode_mem */ + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeReInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if cvode_mem was allocated */ + + if (cv_mem->cv_MallocDone == FALSE) { + CVProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeReInit", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check for legal input parameters */ + + if (y0 == NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeReInit", MSGCV_NULL_Y0); + return(CV_ILL_INPUT); + } + + /* Copy the input parameters into CVODE state */ + + cv_mem->cv_tn = t0; + + /* Set step parameters */ + + cv_mem->cv_q = 1; + cv_mem->cv_L = 2; + cv_mem->cv_qwait = cv_mem->cv_L; + cv_mem->cv_etamax = ETAMX1; + + cv_mem->cv_qu = 0; + cv_mem->cv_hu = ZERO; + cv_mem->cv_tolsf = ONE; + + /* Initialize zn[0] in the history array */ + + N_VScale(ONE, y0, cv_mem->cv_zn[0]); + + /* Initialize all the counters */ + + cv_mem->cv_nst = 0; + cv_mem->cv_nfe = 0; + cv_mem->cv_ncfn = 0; + cv_mem->cv_netf = 0; + cv_mem->cv_nni = 0; + cv_mem->cv_nsetups = 0; + cv_mem->cv_nhnil = 0; + cv_mem->cv_nstlp = 0; + cv_mem->cv_nscon = 0; + cv_mem->cv_nge = 0; + + cv_mem->cv_irfnd = 0; + + /* Initialize other integrator optional outputs */ + + cv_mem->cv_h0u = ZERO; + cv_mem->cv_next_h = ZERO; + cv_mem->cv_next_q = 0; + + /* Initialize Stablilty Limit Detection data */ + + cv_mem->cv_nor = 0; + for (i = 1; i <= 5; i++) + for (k = 1; k <= 3; k++) + cv_mem->cv_ssdat[i-1][k-1] = ZERO; + + /* Problem has been successfully re-initialized */ + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeSStolerances + * CVodeSVtolerances + * CVodeWFtolerances + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to CVode. + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn) + * which will be called to set the error weight vector. + */ + +int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSStolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_MallocDone == FALSE) { + CVProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeSStolerances", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check inputs */ + + if (reltol < ZERO) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSStolerances", MSGCV_BAD_RELTOL); + return(CV_ILL_INPUT); + } + + if (abstol < ZERO) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSStolerances", MSGCV_BAD_ABSTOL); + return(CV_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + cv_mem->cv_reltol = reltol; + cv_mem->cv_Sabstol = abstol; + + cv_mem->cv_itol = CV_SS; + + cv_mem->cv_user_efun = FALSE; + cv_mem->cv_efun = CVEwtSet; + cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */ + + return(CV_SUCCESS); +} + + +int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSVtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_MallocDone == FALSE) { + CVProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeSVtolerances", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check inputs */ + + if (reltol < ZERO) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSVtolerances", MSGCV_BAD_RELTOL); + return(CV_ILL_INPUT); + } + + if (N_VMin(abstol) < ZERO) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSVtolerances", MSGCV_BAD_ABSTOL); + return(CV_ILL_INPUT); + } + + /* Copy tolerances into memory */ + + if ( !(cv_mem->cv_VabstolMallocDone) ) { + cv_mem->cv_Vabstol = N_VClone(cv_mem->cv_ewt); + lrw += lrw1; + liw += liw1; + cv_mem->cv_VabstolMallocDone = TRUE; + } + + cv_mem->cv_reltol = reltol; + N_VScale(ONE, abstol, cv_mem->cv_Vabstol); + + cv_mem->cv_itol = CV_SV; + + cv_mem->cv_user_efun = FALSE; + cv_mem->cv_efun = CVEwtSet; + cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */ + + return(CV_SUCCESS); +} + + +int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeWFtolerances", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_MallocDone == FALSE) { + CVProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeWFtolerances", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + cv_mem->cv_itol = CV_WF; + + cv_mem->cv_user_efun = TRUE; + cv_mem->cv_efun = efun; + cv_mem->cv_e_data = NULL; /* will be set to user_data in InitialSetup */ + + return(CV_SUCCESS); +} + +/*-----------------------------------------------------------------*/ + +#define gfun (cv_mem->cv_gfun) +#define glo (cv_mem->cv_glo) +#define ghi (cv_mem->cv_ghi) +#define grout (cv_mem->cv_grout) +#define iroots (cv_mem->cv_iroots) +#define rootdir (cv_mem->cv_rootdir) +#define gactive (cv_mem->cv_gactive) + +/*-----------------------------------------------------------------*/ + +/* + * CVodeRootInit + * + * CVodeRootInit initializes a rootfinding problem to be solved + * during the integration of the ODE system. It loads the root + * function pointer and the number of root functions, and allocates + * workspace memory. The return value is CV_SUCCESS = 0 if no errors + * occurred, or a negative value otherwise. + */ + +int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g) +{ + CVodeMem cv_mem; + int i, nrt; + + /* Check cvode_mem pointer */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeRootInit", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + nrt = (nrtfn < 0) ? 0 : nrtfn; + + /* If rerunning CVodeRootInit() with a different number of root + functions (changing number of gfun components), then free + currently held memory resources */ + if ((nrt != cv_mem->cv_nrtfn) && (cv_mem->cv_nrtfn > 0)) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + + lrw -= 3 * (cv_mem->cv_nrtfn); + liw -= 3 * (cv_mem->cv_nrtfn); + } + + /* If CVodeRootInit() was called with nrtfn == 0, then set cv_nrtfn to + zero and cv_gfun to NULL before returning */ + if (nrt == 0) { + cv_mem->cv_nrtfn = nrt; + gfun = NULL; + return(CV_SUCCESS); + } + + /* If rerunning CVodeRootInit() with the same number of root functions + (not changing number of gfun components), then check if the root + function argument has changed */ + /* If g != NULL then return as currently reserved memory resources + will suffice */ + if (nrt == cv_mem->cv_nrtfn) { + if (g != gfun) { + if (g == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + + lrw -= 3*nrt; + liw -= 3*nrt; + + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeRootInit", MSGCV_NULL_G); + return(CV_ILL_INPUT); + } + else { + gfun = g; + return(CV_SUCCESS); + } + } + else return(CV_SUCCESS); + } + + /* Set variable values in CVode memory block */ + cv_mem->cv_nrtfn = nrt; + if (g == NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeRootInit", MSGCV_NULL_G); + return(CV_ILL_INPUT); + } + else gfun = g; + + /* Allocate necessary memory and return */ + glo = NULL; + glo = (realtype *) malloc(nrt*sizeof(realtype)); + if (glo == NULL) { + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + ghi = NULL; + ghi = (realtype *) malloc(nrt*sizeof(realtype)); + if (ghi == NULL) { + free(glo); glo = NULL; + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + grout = NULL; + grout = (realtype *) malloc(nrt*sizeof(realtype)); + if (grout == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + iroots = NULL; + iroots = (int *) malloc(nrt*sizeof(int)); + if (iroots == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + rootdir = NULL; + rootdir = (int *) malloc(nrt*sizeof(int)); + if (rootdir == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + gactive = NULL; + gactive = (booleantype *) malloc(nrt*sizeof(booleantype)); + if (gactive == NULL) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + CVProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL); + return(CV_MEM_FAIL); + } + + /* Set default values for rootdir (both directions) */ + for(i=0; icv_f) +#define user_data (cv_mem->cv_user_data) +#define efun (cv_mem->cv_efun) +#define e_data (cv_mem->cv_e_data) +#define qmax (cv_mem->cv_qmax) +#define mxstep (cv_mem->cv_mxstep) +#define mxhnil (cv_mem->cv_mxhnil) +#define sldeton (cv_mem->cv_sldeton) +#define hin (cv_mem->cv_hin) +#define hmin (cv_mem->cv_hmin) +#define hmax_inv (cv_mem->cv_hmax_inv) +#define tstop (cv_mem->cv_tstop) +#define tstopset (cv_mem->cv_tstopset) +#define maxnef (cv_mem->cv_maxnef) +#define maxncf (cv_mem->cv_maxncf) +#define maxcor (cv_mem->cv_maxcor) +#define nlscoef (cv_mem->cv_nlscoef) +#define itol (cv_mem->cv_itol) +#define reltol (cv_mem->cv_reltol) +#define Sabstol (cv_mem->cv_Sabstol) +#define Vabstol (cv_mem->cv_Vabstol) + +#define uround (cv_mem->cv_uround) +#define zn (cv_mem->cv_zn) +#define ewt (cv_mem->cv_ewt) +#define y (cv_mem->cv_y) +#define acor (cv_mem->cv_acor) +#define tempv (cv_mem->cv_tempv) +#define ftemp (cv_mem->cv_ftemp) +#define q (cv_mem->cv_q) +#define qprime (cv_mem->cv_qprime) +#define next_q (cv_mem->cv_next_q) +#define qwait (cv_mem->cv_qwait) +#define L (cv_mem->cv_L) +#define h (cv_mem->cv_h) +#define hprime (cv_mem->cv_hprime) +#define next_h (cv_mem->cv_next_h) +#define eta (cv_mem->cv_eta) +#define etaqm1 (cv_mem->cv_etaqm1) +#define etaq (cv_mem->cv_etaq) +#define etaqp1 (cv_mem->cv_etaqp1) +#define nscon (cv_mem->cv_nscon) +#define hscale (cv_mem->cv_hscale) +#define tn (cv_mem->cv_tn) +#define tau (cv_mem->cv_tau) +#define tq (cv_mem->cv_tq) +#define l (cv_mem->cv_l) +#define rl1 (cv_mem->cv_rl1) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define crate (cv_mem->cv_crate) +#define acnrm (cv_mem->cv_acnrm) +#define mnewt (cv_mem->cv_mnewt) +#define etamax (cv_mem->cv_etamax) +#define nst (cv_mem->cv_nst) +#define nfe (cv_mem->cv_nfe) +#define ncfn (cv_mem->cv_ncfn) +#define netf (cv_mem->cv_netf) +#define nni (cv_mem->cv_nni) +#define nsetups (cv_mem->cv_nsetups) +#define nhnil (cv_mem->cv_nhnil) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define qu (cv_mem->cv_qu) +#define nstlp (cv_mem->cv_nstlp) +#define h0u (cv_mem->cv_h0u) +#define hu (cv_mem->cv_hu) +#define saved_tq5 (cv_mem->cv_saved_tq5) +#define indx_acor (cv_mem->cv_indx_acor) +#define jcur (cv_mem->cv_jcur) +#define tolsf (cv_mem->cv_tolsf) +#define setupNonNull (cv_mem->cv_setupNonNull) +#define nor (cv_mem->cv_nor) +#define ssdat (cv_mem->cv_ssdat) + +#define nrtfn (cv_mem->cv_nrtfn) +#define tlo (cv_mem->cv_tlo) +#define thi (cv_mem->cv_thi) +#define tretlast (cv_mem->cv_tretlast) +#define toutc (cv_mem->cv_toutc) +#define trout (cv_mem->cv_trout) +#define ttol (cv_mem->cv_ttol) +#define taskc (cv_mem->cv_taskc) +#define irfnd (cv_mem->cv_irfnd) +#define nge (cv_mem->cv_nge) + + +/*-----------------------------------------------------------------*/ + +/* + * CVode + * + * This routine is the main driver of the CVODE package. + * + * It integrates over a time interval defined by the user, by calling + * CVStep to do internal time steps. + * + * The first time that CVode is called for a successfully initialized + * problem, it computes a tentative initial step size h. + * + * CVode supports two modes, specified by itask: CV_NORMAL, CV_ONE_STEP. + * In the CV_NORMAL mode, the solver steps until it reaches or passes tout + * and then interpolates to obtain y(tout). + * In the CV_ONE_STEP mode, it takes one internal step and returns. + */ + +int CVode(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask) +{ + CVodeMem cv_mem; + long int nstloc; + int retval, hflag, kflag, istate, ir, ier, irfndp; + int ewtsetOK; + realtype troundoff, tout_hin, rh, nrm; + booleantype inactive_roots; + + /* + * ------------------------------------- + * 1. Check and process inputs + * ------------------------------------- + */ + + /* Check if cvode_mem exists */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVode", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if cvode_mem was allocated */ + if (cv_mem->cv_MallocDone == FALSE) { + CVProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVode", MSGCV_NO_MALLOC); + return(CV_NO_MALLOC); + } + + /* Check for yout != NULL */ + if ((y = yout) == NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_YOUT_NULL); + return(CV_ILL_INPUT); + } + + /* Check for tret != NULL */ + if (tret == NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_TRET_NULL); + return(CV_ILL_INPUT); + } + + /* Check for valid itask */ + if ( (itask != CV_NORMAL) && (itask != CV_ONE_STEP) ) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_ITASK); + return(CV_ILL_INPUT); + } + + if (itask == CV_NORMAL) toutc = tout; + taskc = itask; + + /* + * ---------------------------------------- + * 2. Initializations performed only at + * the first step (nst=0): + * - initial setup + * - initialize Nordsieck history array + * - compute initial step size + * - check for approach to tstop + * - check for approach to a root + * ---------------------------------------- + */ + + if (nst == 0) { + + ier = CVInitialSetup(cv_mem); + if (ier!= CV_SUCCESS) return(ier); + + /* Call f at (t0,y0), set zn[1] = y'(t0), + set initial h (from H0 or CVHin), and scale zn[1] by h. + Also check for zeros of root function g at and near t0. */ + + retval = f(tn, zn[0], zn[1], user_data); + nfe++; + if (retval < 0) { + CVProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED, tn); + return(CV_RHSFUNC_FAIL); + } + if (retval > 0) { + CVProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_FIRST); + return(CV_FIRST_RHSFUNC_ERR); + } + + /* Set initial h (from H0 or CVHin). */ + + h = hin; + if ( (h != ZERO) && ((tout-tn)*h < ZERO) ) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_H0); + return(CV_ILL_INPUT); + } + if (h == ZERO) { + tout_hin = tout; + if ( tstopset && (tout-tn)*(tout-tstop) > 0 ) tout_hin = tstop; + hflag = CVHin(cv_mem, tout_hin); + if (hflag != CV_SUCCESS) { + istate = CVHandleFailure(cv_mem, hflag); + return(istate); + } + } + rh = ABS(h)*hmax_inv; + if (rh > ONE) h /= rh; + if (ABS(h) < hmin) h *= hmin/ABS(h); + + /* Check for approach to tstop */ + + if (tstopset) { + if ( (tstop - tn)*h < ZERO ) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TSTOP, tstop, tn); + return(CV_ILL_INPUT); + } + if ( (tn + h - tstop)*h > ZERO ) + h = (tstop - tn)*(ONE-FOUR*uround); + } + + /* Scale zn[1] by h.*/ + + hscale = h; + h0u = h; + hprime = h; + + N_VScale(h, zn[1], zn[1]); + + /* Check for zeros of root function g at and near t0. */ + + if (nrtfn > 0) { + + retval = CVRcheck1(cv_mem); + + if (retval == CV_RTFUNC_FAIL) { + CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck1", MSGCV_RTFUNC_FAILED, tn); + return(CV_RTFUNC_FAIL); + } + + } + + } /* end of first call block */ + + /* + * ------------------------------------------------------ + * 3. At following steps, perform stop tests: + * - check for root in last step + * - check if we passed tstop + * - check if we passed tout (NORMAL mode) + * - check if current tn was returned (ONE_STEP mode) + * - check if we are close to tstop + * (adjust step size if needed) + * ------------------------------------------------------- + */ + + if (nst > 0) { + + /* Estimate an infinitesimal time interval to be used as + a roundoff for time quantities (based on current time + and step size) */ + troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h)); + + /* First, check for a root in the last step taken, other than the + last root found, if any. If itask = CV_ONE_STEP and y(tn) was not + returned because of an intervening root, return y(tn) now. */ + if (nrtfn > 0) { + + irfndp = irfnd; + + retval = CVRcheck2(cv_mem); + + if (retval == CLOSERT) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVRcheck2", MSGCV_CLOSE_ROOTS, tlo); + return(CV_ILL_INPUT); + } else if (retval == CV_RTFUNC_FAIL) { + CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck2", MSGCV_RTFUNC_FAILED, tlo); + return(CV_RTFUNC_FAIL); + } else if (retval == RTFOUND) { + tretlast = *tret = tlo; + return(CV_ROOT_RETURN); + } + + /* If tn is distinct from tretlast (within roundoff), + check remaining interval for roots */ + if ( ABS(tn - tretlast) > troundoff ) { + + retval = CVRcheck3(cv_mem); + + if (retval == CV_SUCCESS) { /* no root found */ + irfnd = 0; + if ((irfndp == 1) && (itask == CV_ONE_STEP)) { + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + return(CV_SUCCESS); + } + } else if (retval == RTFOUND) { /* a new root was found */ + irfnd = 1; + tretlast = *tret = tlo; + return(CV_ROOT_RETURN); + } else if (retval == CV_RTFUNC_FAIL) { /* g failed */ + CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck3", MSGCV_RTFUNC_FAILED, tlo); + return(CV_RTFUNC_FAIL); + } + + } + + } /* end of root stop check */ + + /* In CV_NORMAL mode, test if tout was reached */ + if ( (itask == CV_NORMAL) && ((tn-tout)*h >= ZERO) ) { + tretlast = *tret = tout; + ier = CVodeGetDky(cv_mem, tout, 0, yout); + if (ier != CV_SUCCESS) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TOUT, tout); + return(CV_ILL_INPUT); + } + return(CV_SUCCESS); + } + + /* In CV_ONE_STEP mode, test if tn was returned */ + if ( itask == CV_ONE_STEP && ABS(tn - tretlast) > troundoff ) { + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + return(CV_SUCCESS); + } + + /* Test for tn at tstop or near tstop */ + if ( tstopset ) { + + if ( ABS(tn - tstop) <= troundoff) { + ier = CVodeGetDky(cv_mem, tstop, 0, yout); + if (ier != CV_SUCCESS) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TSTOP, tstop, tn); + return(CV_ILL_INPUT); + } + tretlast = *tret = tstop; + tstopset = FALSE; + return(CV_TSTOP_RETURN); + } + + /* If next step would overtake tstop, adjust stepsize */ + if ( (tn + hprime - tstop)*h > ZERO ) { + hprime = (tstop - tn)*(ONE-FOUR*uround); + eta = hprime/h; + } + + } + + } /* end stopping tests block */ + + /* + * -------------------------------------------------- + * 4. Looping point for internal steps + * + * 4.1. check for errors (too many steps, too much + * accuracy requested, step size too small) + * 4.2. take a new step (call CVStep) + * 4.3. stop on error + * 4.4. perform stop tests: + * - check for root in last step + * - check if tout was passed + * - check if close to tstop + * - check if in ONE_STEP mode (must return) + * -------------------------------------------------- + */ + + nstloc = 0; + loop { + + next_h = h; + next_q = q; + + /* Reset and check ewt */ + if (nst > 0) { + + ewtsetOK = efun(zn[0], ewt, e_data); + + if (ewtsetOK != 0) { + + if (itol == CV_WF) + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_EWT_NOW_FAIL, tn); + else + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_EWT_NOW_BAD, tn); + + istate = CV_ILL_INPUT; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + + } + } + + /* Check for too many steps */ + if ( (mxstep>0) && (nstloc >= mxstep) ) { + CVProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODE", "CVode", MSGCV_MAX_STEPS, tn); + istate = CV_TOO_MUCH_WORK; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + + /* Check for too much accuracy requested */ + nrm = N_VWrmsNorm(zn[0], ewt); + tolsf = uround * nrm; + if (tolsf > ONE) { + CVProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODE", "CVode", MSGCV_TOO_MUCH_ACC, tn); + istate = CV_TOO_MUCH_ACC; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + tolsf *= TWO; + break; + } else { + tolsf = ONE; + } + + /* Check for h below roundoff level in tn */ + if (tn + h == tn) { + nhnil++; + if (nhnil <= mxhnil) + CVProcessError(cv_mem, CV_WARNING, "CVODE", "CVode", MSGCV_HNIL, tn, h); + if (nhnil == mxhnil) + CVProcessError(cv_mem, CV_WARNING, "CVODE", "CVode", MSGCV_HNIL_DONE); + } + + /* Call CVStep to take a step */ + kflag = CVStep(cv_mem); + + /* Process failed step cases, and exit loop */ + if (kflag != CV_SUCCESS) { + istate = CVHandleFailure(cv_mem, kflag); + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + break; + } + + nstloc++; + + /* Check for root in last step taken. */ + if (nrtfn > 0) { + + retval = CVRcheck3(cv_mem); + + if (retval == RTFOUND) { /* A new root was found */ + irfnd = 1; + istate = CV_ROOT_RETURN; + tretlast = *tret = tlo; + break; + } else if (retval == CV_RTFUNC_FAIL) { /* g failed */ + CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVRcheck3", MSGCV_RTFUNC_FAILED, tlo); + istate = CV_RTFUNC_FAIL; + break; + } + + /* If we are at the end of the first step and we still have + * some event functions that are inactive, issue a warning + * as this may indicate a user error in the implementation + * of the root function. */ + + if (nst==1) { + inactive_roots = FALSE; + for (ir=0; ircv_mxgnull > 0) && inactive_roots) { + CVProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_INACTIVE_ROOTS); + } + } + + } + + /* In NORMAL mode, check if tout reached */ + if ( (itask == CV_NORMAL) && (tn-tout)*h >= ZERO ) { + istate = CV_SUCCESS; + tretlast = *tret = tout; + (void) CVodeGetDky(cv_mem, tout, 0, yout); + next_q = qprime; + next_h = hprime; + break; + } + + /* Check if tn is at tstop or near tstop */ + if ( tstopset ) { + + troundoff = FUZZ_FACTOR*uround*(ABS(tn) + ABS(h)); + if ( ABS(tn - tstop) <= troundoff) { + (void) CVodeGetDky(cv_mem, tstop, 0, yout); + tretlast = *tret = tstop; + tstopset = FALSE; + istate = CV_TSTOP_RETURN; + break; + } + + if ( (tn + hprime - tstop)*h > ZERO ) { + hprime = (tstop - tn)*(ONE-FOUR*uround); + eta = hprime/h; + } + + } + + /* In ONE_STEP mode, copy y and exit loop */ + if (itask == CV_ONE_STEP) { + istate = CV_SUCCESS; + tretlast = *tret = tn; + N_VScale(ONE, zn[0], yout); + next_q = qprime; + next_h = hprime; + break; + } + + } /* end looping for internal steps */ + + return(istate); +} + +/*-----------------------------------------------------------------*/ + +/* + * CVodeGetDky + * + * This routine computes the k-th derivative of the interpolating + * polynomial at the time t and stores the result in the vector dky. + * The formula is: + * q + * dky = SUM c(j,k) * (t - tn)^(j-k) * h^(-j) * zn[j] , + * j=k + * where c(j,k) = j*(j-1)*...*(j-k+1), q is the current order, and + * zn[j] is the j-th column of the Nordsieck history array. + * + * This function is called by CVode with k = 0 and t = tout, but + * may also be called directly by the user. + */ + +int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky) +{ + realtype s, c, r; + realtype tfuzz, tp, tn1; + int i, j; + CVodeMem cv_mem; + + /* Check all inputs for legality */ + + if (cvode_mem == NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetDky", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (dky == NULL) { + CVProcessError(cv_mem, CV_BAD_DKY, "CVODE", "CVodeGetDky", MSGCV_NULL_DKY); + return(CV_BAD_DKY); + } + + if ((k < 0) || (k > q)) { + CVProcessError(cv_mem, CV_BAD_K, "CVODE", "CVodeGetDky", MSGCV_BAD_K); + return(CV_BAD_K); + } + + /* Allow for some slack */ + tfuzz = FUZZ_FACTOR * uround * (ABS(tn) + ABS(hu)); + if (hu < ZERO) tfuzz = -tfuzz; + tp = tn - hu - tfuzz; + tn1 = tn + tfuzz; + if ((t-tp)*(t-tn1) > ZERO) { + CVProcessError(cv_mem, CV_BAD_T, "CVODE", "CVodeGetDky", MSGCV_BAD_T, t, tn-hu, tn); + return(CV_BAD_T); + } + + /* Sum the differentiated interpolating polynomial */ + + s = (t - tn) / h; + for (j=q; j >= k; j--) { + c = ONE; + for (i=j; i >= j-k+1; i--) c *= i; + if (j == q) { + N_VScale(c, zn[q], dky); + } else { + N_VLinearSum(c, zn[j], s, dky, dky); + } + } + if (k == 0) return(CV_SUCCESS); + r = RPowerI(h,-k); + N_VScale(r, dky, dky); + return(CV_SUCCESS); +} + +/* + * CVodeFree + * + * This routine frees the problem memory allocated by CVodeInit. + * Such memory includes all the vectors allocated by CVAllocVectors, + * and the memory lmem for the linear solver (deallocated by a call + * to lfree). + */ + +void CVodeFree(void **cvode_mem) +{ + CVodeMem cv_mem; + + if (*cvode_mem == NULL) return; + + cv_mem = (CVodeMem) (*cvode_mem); + + CVFreeVectors(cv_mem); + + if (iter == CV_NEWTON && lfree != NULL) lfree(cv_mem); + + if (nrtfn > 0) { + free(glo); glo = NULL; + free(ghi); ghi = NULL; + free(grout); grout = NULL; + free(iroots); iroots = NULL; + free(rootdir); rootdir = NULL; + free(gactive); gactive = NULL; + } + + free(*cvode_mem); + *cvode_mem = NULL; +} + +/* + * ================================================================= + * Private Functions Implementation + * ================================================================= + */ + +/* + * CVCheckNvector + * This routine checks if all required vector operations are present. + * If any of them is missing it returns FALSE. + */ + +static booleantype CVCheckNvector(N_Vector tmpl) +{ + if((tmpl->ops->nvclone == NULL) || + (tmpl->ops->nvdestroy == NULL) || + (tmpl->ops->nvlinearsum == NULL) || + (tmpl->ops->nvconst == NULL) || + (tmpl->ops->nvprod == NULL) || + (tmpl->ops->nvdiv == NULL) || + (tmpl->ops->nvscale == NULL) || + (tmpl->ops->nvabs == NULL) || + (tmpl->ops->nvinv == NULL) || + (tmpl->ops->nvaddconst == NULL) || + (tmpl->ops->nvmaxnorm == NULL) || + (tmpl->ops->nvwrmsnorm == NULL) || + (tmpl->ops->nvmin == NULL)) + return(FALSE); + else + return(TRUE); +} + +/* + * CVAllocVectors + * + * This routine allocates the CVODE vectors ewt, acor, tempv, ftemp, and + * zn[0], ..., zn[maxord]. + * If all memory allocations are successful, CVAllocVectors returns TRUE. + * Otherwise all allocated memory is freed and CVAllocVectors returns FALSE. + * This routine also sets the optional outputs lrw and liw, which are + * (respectively) the lengths of the real and integer work spaces + * allocated here. + */ + +static booleantype CVAllocVectors(CVodeMem cv_mem, N_Vector tmpl) +{ + int i, j; + + /* Allocate ewt, acor, tempv, ftemp */ + + ewt = N_VClone(tmpl); + if (ewt == NULL) return(FALSE); + + acor = N_VClone(tmpl); + if (acor == NULL) { + N_VDestroy(ewt); + return(FALSE); + } + + tempv = N_VClone(tmpl); + if (tempv == NULL) { + N_VDestroy(ewt); + N_VDestroy(acor); + return(FALSE); + } + + ftemp = N_VClone(tmpl); + if (ftemp == NULL) { + N_VDestroy(tempv); + N_VDestroy(ewt); + N_VDestroy(acor); + return(FALSE); + } + + /* Allocate zn[0] ... zn[qmax] */ + + for (j=0; j <= qmax; j++) { + zn[j] = N_VClone(tmpl); + if (zn[j] == NULL) { + N_VDestroy(ewt); + N_VDestroy(acor); + N_VDestroy(tempv); + N_VDestroy(ftemp); + for (i=0; i < j; i++) N_VDestroy(zn[i]); + return(FALSE); + } + } + + /* Update solver workspace lengths */ + lrw += (qmax + 5)*lrw1; + liw += (qmax + 5)*liw1; + + /* Store the value of qmax used here */ + cv_mem->cv_qmax_alloc = qmax; + + return(TRUE); +} + +/* + * CVFreeVectors + * + * This routine frees the CVODE vectors allocated in CVAllocVectors. + */ + +static void CVFreeVectors(CVodeMem cv_mem) +{ + int j, maxord; + + maxord = cv_mem->cv_qmax_alloc; + + N_VDestroy(ewt); + N_VDestroy(acor); + N_VDestroy(tempv); + N_VDestroy(ftemp); + for(j=0; j <= maxord; j++) N_VDestroy(zn[j]); + + lrw -= (maxord + 5)*lrw1; + liw -= (maxord + 5)*liw1; + + if (cv_mem->cv_VabstolMallocDone) { + N_VDestroy(Vabstol); + lrw -= lrw1; + liw -= liw1; + } +} + +/* + * CVInitialSetup + * + * This routine performs input consistency checks at the first step. + * If needed, it also checks the linear solver module and calls the + * linear solver initialization routine. + */ + +static int CVInitialSetup(CVodeMem cv_mem) +{ + int ier; + + /* Did the user specify tolerances? */ + if (itol == CV_NN) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVInitialSetup", MSGCV_NO_TOLS); + return(CV_ILL_INPUT); + } + + /* Set data for efun */ + if (cv_mem->cv_user_efun) e_data = user_data; + else e_data = cv_mem; + + /* Load initial error weights */ + ier = efun(zn[0], ewt, e_data); + if (ier != 0) { + if (itol == CV_WF) + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVInitialSetup", MSGCV_EWT_FAIL); + else + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVInitialSetup", MSGCV_BAD_EWT); + return(CV_ILL_INPUT); + } + + /* Check if lsolve function exists (if needed) and call linit function (if it exists) */ + if (iter == CV_NEWTON) { + if (lsolve == NULL) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVInitialSetup", MSGCV_LSOLVE_NULL); + return(CV_ILL_INPUT); + } + if (linit != NULL) { + ier = linit(cv_mem); + if (ier != 0) { + CVProcessError(cv_mem, CV_LINIT_FAIL, "CVODE", "CVInitialSetup", MSGCV_LINIT_FAIL); + return(CV_LINIT_FAIL); + } + } + } + + return(CV_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * PRIVATE FUNCTIONS FOR CVODE + * ----------------------------------------------------------------- + */ + +/* + * CVHin + * + * This routine computes a tentative initial step size h0. + * If tout is too close to tn (= t0), then CVHin returns CV_TOO_CLOSE + * and h remains uninitialized. Note that here tout is either the value + * passed to CVode at the first call or the value of tstop (if tstop is + * enabled and it is closer to t0=tn than tout). + * If the RHS function fails unrecoverably, CVHin returns CV_RHSFUNC_FAIL. + * If the RHS function fails recoverably too many times and recovery is + * not possible, CVHin returns CV_REPTD_RHSFUNC_ERR. + * Otherwise, CVHin sets h to the chosen value h0 and returns CV_SUCCESS. + * + * The algorithm used seeks to find h0 as a solution of + * (WRMS norm of (h0^2 ydd / 2)) = 1, + * where ydd = estimated second derivative of y. + * + * We start with an initial estimate equal to the geometric mean of the + * lower and upper bounds on the step size. + * + * Loop up to MAX_ITERS times to find h0. + * Stop if new and previous values differ by a factor < 2. + * Stop if hnew/hg > 2 after one iteration, as this probably means + * that the ydd value is bad because of cancellation error. + * + * For each new proposed hg, we allow MAX_ITERS attempts to + * resolve a possible recoverable failure from f() by reducing + * the proposed stepsize by a factor of 0.2. If a legal stepsize + * still cannot be found, fall back on a previous value if possible, + * or else return CV_REPTD_RHSFUNC_ERR. + * + * Finally, we apply a bias (0.5) and verify that h0 is within bounds. + */ + +static int CVHin(CVodeMem cv_mem, realtype tout) +{ + int retval, sign, count1, count2; + realtype tdiff, tdist, tround, hlb, hub; + realtype hg, hgs, hs, hnew, hrat, h0, yddnrm; + booleantype hgOK, hnewOK; + + /* If tout is too close to tn, give up */ + + if ((tdiff = tout-tn) == ZERO) return(CV_TOO_CLOSE); + + sign = (tdiff > ZERO) ? 1 : -1; + tdist = ABS(tdiff); + tround = uround * MAX(ABS(tn), ABS(tout)); + + if (tdist < TWO*tround) return(CV_TOO_CLOSE); + + /* + Set lower and upper bounds on h0, and take geometric mean + as first trial value. + Exit with this value if the bounds cross each other. + */ + + hlb = HLB_FACTOR * tround; + hub = CVUpperBoundH0(cv_mem, tdist); + + hg = RSqrt(hlb*hub); + + if (hub < hlb) { + if (sign == -1) h = -hg; + else h = hg; + return(CV_SUCCESS); + } + + /* Outer loop */ + + hnewOK = FALSE; + hs = hg; /* safeguard against 'uninitialized variable' warning */ + + for(count1 = 1; count1 <= MAX_ITERS; count1++) { + + /* Attempts to estimate ydd */ + + hgOK = FALSE; + + for (count2 = 1; count2 <= MAX_ITERS; count2++) { + hgs = hg*sign; + retval = CVYddNorm(cv_mem, hgs, &yddnrm); + /* If f() failed unrecoverably, give up */ + if (retval < 0) return(CV_RHSFUNC_FAIL); + /* If successful, we can use ydd */ + if (retval == CV_SUCCESS) {hgOK = TRUE; break;} + /* f() failed recoverably; cut step size and test it again */ + hg *= POINT2; + } + + /* If f() failed recoverably MAX_ITERS times */ + + if (!hgOK) { + /* Exit if this is the first or second pass. No recovery possible */ + if (count1 <= 2) return(CV_REPTD_RHSFUNC_ERR); + /* We have a fall-back option. The value hs is a previous hnew which + passed through f(). Use it and break */ + hnew = hs; + break; + } + + /* The proposed step size is feasible. Save it. */ + hs = hg; + + /* If the stopping criteria was met, or if this is the last pass, stop */ + if ( (hnewOK) || (count1 == MAX_ITERS)) {hnew = hg; break;} + + /* Propose new step size */ + hnew = (yddnrm*hub*hub > TWO) ? RSqrt(TWO/yddnrm) : RSqrt(hg*hub); + hrat = hnew/hg; + + /* Accept hnew if it does not differ from hg by more than a factor of 2 */ + if ((hrat > HALF) && (hrat < TWO)) { + hnewOK = TRUE; + } + + /* After one pass, if ydd seems to be bad, use fall-back value. */ + if ((count1 > 1) && (hrat > TWO)) { + hnew = hg; + hnewOK = TRUE; + } + + /* Send this value back through f() */ + hg = hnew; + + } + + /* Apply bounds, bias factor, and attach sign */ + + h0 = H_BIAS*hnew; + if (h0 < hlb) h0 = hlb; + if (h0 > hub) h0 = hub; + if (sign == -1) h0 = -h0; + h = h0; + + return(CV_SUCCESS); +} + +/* + * CVUpperBoundH0 + * + * This routine sets an upper bound on abs(h0) based on + * tdist = tn - t0 and the values of y[i]/y'[i]. + */ + +static realtype CVUpperBoundH0(CVodeMem cv_mem, realtype tdist) +{ + realtype hub_inv, hub; + N_Vector temp1, temp2; + + /* + * Bound based on |y0|/|y0'| -- allow at most an increase of + * HUB_FACTOR in y0 (based on a forward Euler step). The weight + * factor is used as a safeguard against zero components in y0. + */ + + temp1 = tempv; + temp2 = acor; + + N_VAbs(zn[0], temp2); + efun(zn[0], temp1, e_data); + N_VInv(temp1, temp1); + N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1); + + N_VAbs(zn[1], temp2); + + N_VDiv(temp2, temp1, temp1); + hub_inv = N_VMaxNorm(temp1); + + /* + * bound based on tdist -- allow at most a step of magnitude + * HUB_FACTOR * tdist + */ + + hub = HUB_FACTOR*tdist; + + /* Use the smaler of the two */ + + if (hub*hub_inv > ONE) hub = ONE/hub_inv; + + return(hub); +} + +/* + * CVYddNorm + * + * This routine computes an estimate of the second derivative of y + * using a difference quotient, and returns its WRMS norm. + */ + +static int CVYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm) +{ + int retval; + + N_VLinearSum(hg, zn[1], ONE, zn[0], y); + retval = f(tn+hg, y, tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + N_VLinearSum(ONE, tempv, -ONE, zn[1], tempv); + N_VScale(ONE/hg, tempv, tempv); + + *yddnrm = N_VWrmsNorm(tempv, ewt); + + return(CV_SUCCESS); +} + +/* + * CVStep + * + * This routine performs one internal cvode step, from tn to tn + h. + * It calls other routines to do all the work. + * + * The main operations done here are as follows: + * - preliminary adjustments if a new step size was chosen; + * - prediction of the Nordsieck history array zn at tn + h; + * - setting of multistep method coefficients and test quantities; + * - solution of the nonlinear system; + * - testing the local error; + * - updating zn and other state data if successful; + * - resetting stepsize and order for the next step. + * - if SLDET is on, check for stability, reduce order if necessary. + * On a failure in the nonlinear system solution or error test, the + * step may be reattempted, depending on the nature of the failure. + */ + +static int CVStep(CVodeMem cv_mem) +{ + realtype saved_t, dsm; + int ncf, nef; + int nflag, kflag, eflag; + + saved_t = tn; + ncf = nef = 0; + nflag = FIRST_CALL; + + if ((nst > 0) && (hprime != h)) CVAdjustParams(cv_mem); + + /* Looping point for attempts to take a step */ + loop { + + CVPredict(cv_mem); + CVSet(cv_mem); + + nflag = CVNls(cv_mem, nflag); + kflag = CVHandleNFlag(cv_mem, &nflag, saved_t, &ncf); + + /* Go back in loop if we need to predict again (nflag=PREV_CONV_FAIL)*/ + if (kflag == PREDICT_AGAIN) continue; + + /* Return if nonlinear solve failed and recovery not possible. */ + if (kflag != DO_ERROR_TEST) return(kflag); + + /* Perform error test (nflag=CV_SUCCESS) */ + eflag = CVDoErrorTest(cv_mem, &nflag, saved_t, &nef, &dsm); + + /* Go back in loop if we need to predict again (nflag=PREV_ERR_FAIL) */ + if (eflag == TRY_AGAIN) continue; + + /* Return if error test failed and recovery not possible. */ + if (eflag != CV_SUCCESS) return(eflag); + + /* Error test passed (eflag=CV_SUCCESS), break from loop */ + break; + + } + + /* Nonlinear system solve and error test were both successful. + Update data, and consider change of step and/or order. */ + + CVCompleteStep(cv_mem); + + CVPrepareNextStep(cv_mem, dsm); + + /* If Stablilty Limit Detection is turned on, call stability limit + detection routine for possible order reduction. */ + + if (sldeton) CVBDFStab(cv_mem); + + etamax = (nst <= SMALL_NST) ? ETAMX2 : ETAMX3; + + /* Finally, we rescale the acor array to be the + estimated local error vector. */ + + N_VScale(tq[2], acor, acor); + return(CV_SUCCESS); + +} + +/* + * CVAdjustParams + * + * This routine is called when a change in step size was decided upon, + * and it handles the required adjustments to the history array zn. + * If there is to be a change in order, we call CVAdjustOrder and reset + * q, L = q+1, and qwait. Then in any case, we call CVRescale, which + * resets h and rescales the Nordsieck array. + */ + +static void CVAdjustParams(CVodeMem cv_mem) +{ + if (qprime != q) { + CVAdjustOrder(cv_mem, qprime-q); + q = qprime; + L = q+1; + qwait = L; + } + CVRescale(cv_mem); +} + +/* + * CVAdjustOrder + * + * This routine is a high level routine which handles an order + * change by an amount deltaq (= +1 or -1). If a decrease in order + * is requested and q==2, then the routine returns immediately. + * Otherwise CVAdjustAdams or CVAdjustBDF is called to handle the + * order change (depending on the value of lmm). + */ + +static void CVAdjustOrder(CVodeMem cv_mem, int deltaq) +{ + if ((q==2) && (deltaq != 1)) return; + + switch(lmm){ + case CV_ADAMS: + CVAdjustAdams(cv_mem, deltaq); + break; + case CV_BDF: + CVAdjustBDF(cv_mem, deltaq); + break; + } +} + +/* + * CVAdjustAdams + * + * This routine adjusts the history array on a change of order q by + * deltaq, in the case that lmm == CV_ADAMS. + */ + +static void CVAdjustAdams(CVodeMem cv_mem, int deltaq) +{ + int i, j; + realtype xi, hsum; + + /* On an order increase, set new column of zn to zero and return */ + + if (deltaq==1) { + N_VConst(ZERO, zn[L]); + return; + } + + /* + * On an order decrease, each zn[j] is adjusted by a multiple of zn[q]. + * The coeffs. in the adjustment are the coeffs. of the polynomial: + * x + * q * INT { u * ( u + xi_1 ) * ... * ( u + xi_{q-2} ) } du + * 0 + * where xi_j = [t_n - t_(n-j)]/h => xi_0 = 0 + */ + + for (i=0; i <= qmax; i++) l[i] = ZERO; + l[1] = ONE; + hsum = ZERO; + for (j=1; j <= q-2; j++) { + hsum += tau[j]; + xi = hsum / hscale; + for (i=j+1; i >= 1; i--) l[i] = l[i]*xi + l[i-1]; + } + + for (j=1; j <= q-2; j++) l[j+1] = q * (l[j] / (j+1)); + + for (j=2; j < q; j++) + N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]); +} + +/* + * CVAdjustBDF + * + * This is a high level routine which handles adjustments to the + * history array on a change of order by deltaq in the case that + * lmm == CV_BDF. CVAdjustBDF calls CVIncreaseBDF if deltaq = +1 and + * CVDecreaseBDF if deltaq = -1 to do the actual work. + */ + +static void CVAdjustBDF(CVodeMem cv_mem, int deltaq) +{ + switch(deltaq) { + case 1 : + CVIncreaseBDF(cv_mem); + return; + case -1: + CVDecreaseBDF(cv_mem); + return; + } +} + +/* + * CVIncreaseBDF + * + * This routine adjusts the history array on an increase in the + * order q in the case that lmm == CV_BDF. + * A new column zn[q+1] is set equal to a multiple of the saved + * vector (= acor) in zn[indx_acor]. Then each zn[j] is adjusted by + * a multiple of zn[q+1]. The coefficients in the adjustment are the + * coefficients of the polynomial x*x*(x+xi_1)*...*(x+xi_j), + * where xi_j = [t_n - t_(n-j)]/h. + */ + +static void CVIncreaseBDF(CVodeMem cv_mem) +{ + realtype alpha0, alpha1, prod, xi, xiold, hsum, A1; + int i, j; + + for (i=0; i <= qmax; i++) l[i] = ZERO; + l[2] = alpha1 = prod = xiold = ONE; + alpha0 = -ONE; + hsum = hscale; + if (q > 1) { + for (j=1; j < q; j++) { + hsum += tau[j+1]; + xi = hsum / hscale; + prod *= xi; + alpha0 -= ONE / (j+1); + alpha1 += ONE / xi; + for (i=j+2; i >= 2; i--) l[i] = l[i]*xiold + l[i-1]; + xiold = xi; + } + } + A1 = (-alpha0 - alpha1) / prod; + N_VScale(A1, zn[indx_acor], zn[L]); + for (j=2; j <= q; j++) { + N_VLinearSum(l[j], zn[L], ONE, zn[j], zn[j]); + } +} + +/* + * CVDecreaseBDF + * + * This routine adjusts the history array on a decrease in the + * order q in the case that lmm == CV_BDF. + * Each zn[j] is adjusted by a multiple of zn[q]. The coefficients + * in the adjustment are the coefficients of the polynomial + * x*x*(x+xi_1)*...*(x+xi_j), where xi_j = [t_n - t_(n-j)]/h. + */ + +static void CVDecreaseBDF(CVodeMem cv_mem) +{ + realtype hsum, xi; + int i, j; + + for (i=0; i <= qmax; i++) l[i] = ZERO; + l[2] = ONE; + hsum = ZERO; + for(j=1; j <= q-2; j++) { + hsum += tau[j]; + xi = hsum /hscale; + for (i=j+2; i >= 2; i--) l[i] = l[i]*xi + l[i-1]; + } + + for(j=2; j < q; j++) + N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]); +} + +/* + * CVRescale + * + * This routine rescales the Nordsieck array by multiplying the + * jth column zn[j] by eta^j, j = 1, ..., q. Then the value of + * h is rescaled by eta, and hscale is reset to h. + */ + +static void CVRescale(CVodeMem cv_mem) +{ + int j; + realtype factor; + + factor = eta; + for (j=1; j <= q; j++) { + N_VScale(factor, zn[j], zn[j]); + factor *= eta; + } + h = hscale * eta; + next_h = h; + hscale = h; + nscon = 0; +} + +/* + * CVPredict + * + * This routine advances tn by the tentative step size h, and computes + * the predicted array z_n(0), which is overwritten on zn. The + * prediction of zn is done by repeated additions. + * If tstop is enabled, it is possible for tn + h to be past tstop by roundoff, + * and in that case, we reset tn (after incrementing by h) to tstop. + */ + +static void CVPredict(CVodeMem cv_mem) +{ + int j, k; + + tn += h; + if (tstopset) { + if ((tn - tstop)*h > ZERO) tn = tstop; + } + for (k = 1; k <= q; k++) + for (j = q; j >= k; j--) + N_VLinearSum(ONE, zn[j-1], ONE, zn[j], zn[j-1]); +} + +/* + * CVSet + * + * This routine is a high level routine which calls CVSetAdams or + * CVSetBDF to set the polynomial l, the test quantity array tq, + * and the related variables rl1, gamma, and gamrat. + * + * The array tq is loaded with constants used in the control of estimated + * local errors and in the nonlinear convergence test. Specifically, while + * running at order q, the components of tq are as follows: + * tq[1] = a coefficient used to get the est. local error at order q-1 + * tq[2] = a coefficient used to get the est. local error at order q + * tq[3] = a coefficient used to get the est. local error at order q+1 + * tq[4] = constant used in nonlinear iteration convergence test + * tq[5] = coefficient used to get the order q+2 derivative vector used in + * the est. local error at order q+1 + */ + +static void CVSet(CVodeMem cv_mem) +{ + switch(lmm) { + case CV_ADAMS: + CVSetAdams(cv_mem); + break; + case CV_BDF: + CVSetBDF(cv_mem); + break; + } + rl1 = ONE / l[1]; + gamma = h * rl1; + if (nst == 0) gammap = gamma; + gamrat = (nst > 0) ? gamma / gammap : ONE; /* protect x / x != 1.0 */ +} + +/* + * CVSetAdams + * + * This routine handles the computation of l and tq for the + * case lmm == CV_ADAMS. + * + * The components of the array l are the coefficients of a + * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by + * q-1 + * (d/dx) Lambda(x) = c * PRODUCT (1 + x / xi_i) , where + * i=1 + * Lambda(-1) = 0, Lambda(0) = 1, and c is a normalization factor. + * Here xi_i = [t_n - t_(n-i)] / h. + * + * The array tq is set to test quantities used in the convergence + * test, the error test, and the selection of h at a new order. + */ + +static void CVSetAdams(CVodeMem cv_mem) +{ + realtype m[L_MAX], M[3], hsum; + + if (q == 1) { + l[0] = l[1] = tq[1] = tq[5] = ONE; + tq[2] = HALF; + tq[3] = ONE/TWELVE; + tq[4] = nlscoef / tq[2]; /* = 0.1 / tq[2] */ + return; + } + + hsum = CVAdamsStart(cv_mem, m); + + M[0] = CVAltSum(q-1, m, 1); + M[1] = CVAltSum(q-1, m, 2); + + CVAdamsFinish(cv_mem, m, M, hsum); +} + +/* + * CVAdamsStart + * + * This routine generates in m[] the coefficients of the product + * polynomial needed for the Adams l and tq coefficients for q > 1. + */ + +static realtype CVAdamsStart(CVodeMem cv_mem, realtype m[]) +{ + realtype hsum, xi_inv, sum; + int i, j; + + hsum = h; + m[0] = ONE; + for (i=1; i <= q; i++) m[i] = ZERO; + for (j=1; j < q; j++) { + if ((j==q-1) && (qwait == 1)) { + sum = CVAltSum(q-2, m, 2); + tq[1] = q * sum / m[q-2]; + } + xi_inv = h / hsum; + for (i=j; i >= 1; i--) m[i] += m[i-1] * xi_inv; + hsum += tau[j]; + /* The m[i] are coefficients of product(1 to j) (1 + x/xi_i) */ + } + return(hsum); +} + +/* + * CVAdamsFinish + * + * This routine completes the calculation of the Adams l and tq. + */ + +static void CVAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype hsum) +{ + int i; + realtype M0_inv, xi, xi_inv; + + M0_inv = ONE / M[0]; + + l[0] = ONE; + for (i=1; i <= q; i++) l[i] = M0_inv * (m[i-1] / i); + xi = hsum / h; + xi_inv = ONE / xi; + + tq[2] = M[1] * M0_inv / xi; + tq[5] = xi / l[q]; + + if (qwait == 1) { + for (i=q; i >= 1; i--) m[i] += m[i-1] * xi_inv; + M[2] = CVAltSum(q, m, 2); + tq[3] = M[2] * M0_inv / L; + } + + tq[4] = nlscoef / tq[2]; +} + +/* + * CVAltSum + * + * CVAltSum returns the value of the alternating sum + * sum (i= 0 ... iend) [ (-1)^i * (a[i] / (i + k)) ]. + * If iend < 0 then CVAltSum returns 0. + * This operation is needed to compute the integral, from -1 to 0, + * of a polynomial x^(k-1) M(x) given the coefficients of M(x). + */ + +static realtype CVAltSum(int iend, realtype a[], int k) +{ + int i, sign; + realtype sum; + + if (iend < 0) return(ZERO); + + sum = ZERO; + sign = 1; + for (i=0; i <= iend; i++) { + sum += sign * (a[i] / (i+k)); + sign = -sign; + } + return(sum); +} + +/* + * CVSetBDF + * + * This routine computes the coefficients l and tq in the case + * lmm == CV_BDF. CVSetBDF calls CVSetTqBDF to set the test + * quantity array tq. + * + * The components of the array l are the coefficients of a + * polynomial Lambda(x) = l_0 + l_1 x + ... + l_q x^q, given by + * q-1 + * Lambda(x) = (1 + x / xi*_q) * PRODUCT (1 + x / xi_i) , where + * i=1 + * xi_i = [t_n - t_(n-i)] / h. + * + * The array tq is set to test quantities used in the convergence + * test, the error test, and the selection of h at a new order. + */ + +static void CVSetBDF(CVodeMem cv_mem) +{ + realtype alpha0, alpha0_hat, xi_inv, xistar_inv, hsum; + int i,j; + + l[0] = l[1] = xi_inv = xistar_inv = ONE; + for (i=2; i <= q; i++) l[i] = ZERO; + alpha0 = alpha0_hat = -ONE; + hsum = h; + if (q > 1) { + for (j=2; j < q; j++) { + hsum += tau[j-1]; + xi_inv = h / hsum; + alpha0 -= ONE / j; + for(i=j; i >= 1; i--) l[i] += l[i-1]*xi_inv; + /* The l[i] are coefficients of product(1 to j) (1 + x/xi_i) */ + } + + /* j = q */ + alpha0 -= ONE / q; + xistar_inv = -l[1] - alpha0; + hsum += tau[q-1]; + xi_inv = h / hsum; + alpha0_hat = -l[1] - xi_inv; + for (i=q; i >= 1; i--) l[i] += l[i-1]*xistar_inv; + } + + CVSetTqBDF(cv_mem, hsum, alpha0, alpha0_hat, xi_inv, xistar_inv); +} + +/* + * CVSetTqBDF + * + * This routine sets the test quantity array tq in the case + * lmm == CV_BDF. + */ + +static void CVSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0, + realtype alpha0_hat, realtype xi_inv, realtype xistar_inv) +{ + realtype A1, A2, A3, A4, A5, A6; + realtype C, Cpinv, Cppinv; + + A1 = ONE - alpha0_hat + alpha0; + A2 = ONE + q * A1; + tq[2] = ABS(A1 / (alpha0 * A2)); + tq[5] = ABS(A2 * xistar_inv / (l[q] * xi_inv)); + if (qwait == 1) { + if (q > 1) { + C = xistar_inv / l[q]; + A3 = alpha0 + ONE / q; + A4 = alpha0_hat + xi_inv; + Cpinv = (ONE - A4 + A3) / A3; + tq[1] = ABS(C * Cpinv); + } + else tq[1] = ONE; + hsum += tau[q]; + xi_inv = h / hsum; + A5 = alpha0 - (ONE / (q+1)); + A6 = alpha0_hat - xi_inv; + Cppinv = (ONE - A6 + A5) / A2; + tq[3] = ABS(Cppinv / (xi_inv * (q+2) * A5)); + } + tq[4] = nlscoef / tq[2]; +} + +/* + * CVNls + * + * This routine attempts to solve the nonlinear system associated + * with a single implicit step of the linear multistep method. + * Depending on iter, it calls CVNlsFunctional or CVNlsNewton + * to do the work. + */ + +static int CVNls(CVodeMem cv_mem, int nflag) +{ + int flag = CV_SUCCESS; + + switch(iter) { + case CV_FUNCTIONAL: + flag = CVNlsFunctional(cv_mem); + break; + case CV_NEWTON: + flag = CVNlsNewton(cv_mem, nflag); + break; + } + + return(flag); +} + +/* + * CVNlsFunctional + * + * This routine attempts to solve the nonlinear system using + * functional iteration (no matrices involved). + * + * Possible return values are: + * + * CV_SUCCESS ---> continue with error test + * + * CV_RHSFUNC_FAIL ---> halt the integration + * + * CONV_FAIL -+ + * RHSFUNC_RECVR -+-> predict again or stop if too many + * + */ + +static int CVNlsFunctional(CVodeMem cv_mem) +{ + int retval, m; + realtype del, delp, dcon; + + /* Initialize counter and evaluate f at predicted y */ + + crate = ONE; + m = 0; + + retval = f(tn, zn[0], tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + N_VConst(ZERO, acor); + + /* Initialize delp to avoid compiler warning message */ + del = delp = ZERO; + + /* Loop until convergence; accumulate corrections in acor */ + + loop { + + nni++; + + /* Correct y directly from the last f value */ + N_VLinearSum(h, tempv, -ONE, zn[1], tempv); + N_VScale(rl1, tempv, tempv); + N_VLinearSum(ONE, zn[0], ONE, tempv, y); + /* Get WRMS norm of current correction to use in convergence test */ + N_VLinearSum(ONE, tempv, -ONE, acor, acor); + del = N_VWrmsNorm(acor, ewt); + N_VScale(ONE, tempv, acor); + + /* Test for convergence. If m > 0, an estimate of the convergence + rate constant is stored in crate, and used in the test. */ + if (m > 0) crate = MAX(CRDOWN * crate, del / delp); + dcon = del * MIN(ONE, crate) / tq[4]; + if (dcon <= ONE) { + acnrm = (m == 0) ? del : N_VWrmsNorm(acor, ewt); + return(CV_SUCCESS); /* Convergence achieved */ + } + + /* Stop at maxcor iterations or if iter. seems to be diverging */ + m++; + if ((m==maxcor) || ((m >= 2) && (del > RDIV * delp))) return(CONV_FAIL); + + /* Save norm of correction, evaluate f, and loop again */ + delp = del; + + retval = f(tn, y, tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + } +} + +/* + * CVNlsNewton + * + * This routine handles the Newton iteration. It calls lsetup if + * indicated, calls CVNewtonIteration to perform the iteration, and + * retries a failed attempt at Newton iteration if that is indicated. + * + * Possible return values: + * + * CV_SUCCESS ---> continue with error test + * + * CV_RHSFUNC_FAIL -+ + * CV_LSETUP_FAIL |-> halt the integration + * CV_LSOLVE_FAIL -+ + * + * CONV_FAIL -+ + * RHSFUNC_RECVR -+-> predict again or stop if too many + * + */ + +static int CVNlsNewton(CVodeMem cv_mem, int nflag) +{ + N_Vector vtemp1, vtemp2, vtemp3; + int convfail, retval, ier; + booleantype callSetup; + + vtemp1 = acor; /* rename acor as vtemp1 for readability */ + vtemp2 = y; /* rename y as vtemp2 for readability */ + vtemp3 = tempv; /* rename tempv as vtemp3 for readability */ + + /* Set flag convfail, input to lsetup for its evaluation decision */ + convfail = ((nflag == FIRST_CALL) || (nflag == PREV_ERR_FAIL)) ? + CV_NO_FAILURES : CV_FAIL_OTHER; + + /* Decide whether or not to call setup routine (if one exists) */ + if (setupNonNull) { + callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) || + (nst == 0) || (nst >= nstlp + MSBP) || (ABS(gamrat-ONE) > DGMAX); + } else { + crate = ONE; + callSetup = FALSE; + } + + /* Looping point for the solution of the nonlinear system. + Evaluate f at the predicted y, call lsetup if indicated, and + call CVNewtonIteration for the Newton iteration itself. */ + + loop { + + retval = f(tn, zn[0], ftemp, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(RHSFUNC_RECVR); + + if (callSetup) { + ier = lsetup(cv_mem, convfail, zn[0], ftemp, &jcur, + vtemp1, vtemp2, vtemp3); + nsetups++; + callSetup = FALSE; + gamrat = crate = ONE; + gammap = gamma; + nstlp = nst; + /* Return if lsetup failed */ + if (ier < 0) return(CV_LSETUP_FAIL); + if (ier > 0) return(CONV_FAIL); + } + + /* Set acor to zero and load prediction into y vector */ + N_VConst(ZERO, acor); + N_VScale(ONE, zn[0], y); + + /* Do the Newton iteration */ + ier = CVNewtonIteration(cv_mem); + + /* If there is a convergence failure and the Jacobian-related + data appears not to be current, loop again with a call to lsetup + in which convfail=CV_FAIL_BAD_J. Otherwise return. */ + if (ier != TRY_AGAIN) return(ier); + + callSetup = TRUE; + convfail = CV_FAIL_BAD_J; + } +} + +/* + * CVNewtonIteration + * + * This routine performs the Newton iteration. If the iteration succeeds, + * it returns the value CV_SUCCESS. If not, it may signal the CVNlsNewton + * routine to call lsetup again and reattempt the iteration, by + * returning the value TRY_AGAIN. (In this case, CVNlsNewton must set + * convfail to CV_FAIL_BAD_J before calling setup again). + * Otherwise, this routine returns one of the appropriate values + * CV_LSOLVE_FAIL, CV_RHSFUNC_FAIL, CONV_FAIL, or RHSFUNC_RECVR back + * to CVNlsNewton. + */ + +static int CVNewtonIteration(CVodeMem cv_mem) +{ + int m, retval; + realtype del, delp, dcon; + N_Vector b; + + mnewt = m = 0; + + /* Initialize delp to avoid compiler warning message */ + del = delp = ZERO; + + /* Looping point for Newton iteration */ + loop { + + /* Evaluate the residual of the nonlinear system*/ + N_VLinearSum(rl1, zn[1], ONE, acor, tempv); + N_VLinearSum(gamma, ftemp, -ONE, tempv, tempv); + + /* Call the lsolve function */ + b = tempv; + retval = lsolve(cv_mem, b, ewt, y, ftemp); + nni++; + + if (retval < 0) return(CV_LSOLVE_FAIL); + + /* If lsolve had a recoverable failure and Jacobian data is + not current, signal to try the solution again */ + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Get WRMS norm of correction; add correction to acor and y */ + del = N_VWrmsNorm(b, ewt); + N_VLinearSum(ONE, acor, ONE, b, acor); + N_VLinearSum(ONE, zn[0], ONE, acor, y); + + /* Test for convergence. If m > 0, an estimate of the convergence + rate constant is stored in crate, and used in the test. */ + if (m > 0) { + crate = MAX(CRDOWN * crate, del/delp); + } + dcon = del * MIN(ONE, crate) / tq[4]; + + if (dcon <= ONE) { + acnrm = (m==0) ? del : N_VWrmsNorm(acor, ewt); + jcur = FALSE; + return(CV_SUCCESS); /* Nonlinear system was solved successfully */ + } + + mnewt = ++m; + + /* Stop at maxcor iterations or if iter. seems to be diverging. + If still not converged and Jacobian data is not current, + signal to try the solution again */ + if ((m == maxcor) || ((m >= 2) && (del > RDIV*delp))) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(CONV_FAIL); + } + + /* Save norm of correction, evaluate f, and loop again */ + delp = del; + retval = f(tn, y, ftemp, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) { + if ((!jcur) && (setupNonNull)) return(TRY_AGAIN); + else return(RHSFUNC_RECVR); + } + + } /* end loop */ +} + +/* + * CVHandleFlag + * + * This routine takes action on the return value nflag = *nflagPtr + * returned by CVNls, as follows: + * + * If CVNls succeeded in solving the nonlinear system, then + * CVHandleNFlag returns the constant DO_ERROR_TEST, which tells CVStep + * to perform the error test. + * + * If the nonlinear system was not solved successfully, then ncfn and + * ncf = *ncfPtr are incremented and Nordsieck array zn is restored. + * + * If the solution of the nonlinear system failed due to an + * unrecoverable failure by setup, we return the value CV_LSETUP_FAIL. + * + * If it failed due to an unrecoverable failure in solve, then we return + * the value CV_LSOLVE_FAIL. + * + * If it failed due to an unrecoverable failure in rhs, then we return + * the value CV_RHSFUNC_FAIL. + * + * Otherwise, a recoverable failure occurred when solving the + * nonlinear system (CVNls returned nflag == CONV_FAIL or RHSFUNC_RECVR). + * In this case, if ncf is now equal to maxncf or |h| = hmin, + * we return the value CV_CONV_FAILURE (if nflag=CONV_FAIL) or + * CV_REPTD_RHSFUNC_ERR (if nflag=RHSFUNC_RECVR). + * If not, we set *nflagPtr = PREV_CONV_FAIL and return the value + * PREDICT_AGAIN, telling CVStep to reattempt the step. + * + */ + +static int CVHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t, + int *ncfPtr) +{ + int nflag; + + nflag = *nflagPtr; + + if (nflag == CV_SUCCESS) return(DO_ERROR_TEST); + + /* The nonlinear soln. failed; increment ncfn and restore zn */ + ncfn++; + CVRestore(cv_mem, saved_t); + + /* Return if lsetup, lsolve, or rhs failed unrecoverably */ + if (nflag == CV_LSETUP_FAIL) return(CV_LSETUP_FAIL); + if (nflag == CV_LSOLVE_FAIL) return(CV_LSOLVE_FAIL); + if (nflag == CV_RHSFUNC_FAIL) return(CV_RHSFUNC_FAIL); + + /* At this point, nflag = CONV_FAIL or RHSFUNC_RECVR; increment ncf */ + + (*ncfPtr)++; + etamax = ONE; + + /* If we had maxncf failures or |h| = hmin, + return CV_CONV_FAILURE or CV_REPTD_RHSFUNC_ERR. */ + + if ((ABS(h) <= hmin*ONEPSM) || (*ncfPtr == maxncf)) { + if (nflag == CONV_FAIL) return(CV_CONV_FAILURE); + if (nflag == RHSFUNC_RECVR) return(CV_REPTD_RHSFUNC_ERR); + } + + /* Reduce step size; return to reattempt the step */ + + eta = MAX(ETACF, hmin / ABS(h)); + *nflagPtr = PREV_CONV_FAIL; + CVRescale(cv_mem); + + return(PREDICT_AGAIN); +} + +/* + * CVRestore + * + * This routine restores the value of tn to saved_t and undoes the + * prediction. After execution of CVRestore, the Nordsieck array zn has + * the same values as before the call to CVPredict. + */ + +static void CVRestore(CVodeMem cv_mem, realtype saved_t) +{ + int j, k; + + tn = saved_t; + for (k = 1; k <= q; k++) + for (j = q; j >= k; j--) + N_VLinearSum(ONE, zn[j-1], -ONE, zn[j], zn[j-1]); +} + +/* + * CVDoErrorTest + * + * This routine performs the local error test. + * The weighted local error norm dsm is loaded into *dsmPtr, and + * the test dsm ?<= 1 is made. + * + * If the test passes, CVDoErrorTest returns CV_SUCCESS. + * + * If the test fails, we undo the step just taken (call CVRestore) and + * + * - if maxnef error test failures have occurred or if ABS(h) = hmin, + * we return CV_ERR_FAILURE. + * + * - if more than MXNEF1 error test failures have occurred, an order + * reduction is forced. If already at order 1, restart by reloading + * zn from scratch. If f() fails we return either CV_RHSFUNC_FAIL + * or CV_UNREC_RHSFUNC_ERR (no recovery is possible at this stage). + * + * - otherwise, set *nflagPtr to PREV_ERR_FAIL, and return TRY_AGAIN. + * + */ + +static booleantype CVDoErrorTest(CVodeMem cv_mem, int *nflagPtr, + realtype saved_t, int *nefPtr, realtype *dsmPtr) +{ + realtype dsm; + int retval; + + dsm = acnrm * tq[2]; + + /* If est. local error norm dsm passes test, return CV_SUCCESS */ + *dsmPtr = dsm; + if (dsm <= ONE) return(CV_SUCCESS); + + /* Test failed; increment counters, set nflag, and restore zn array */ + (*nefPtr)++; + netf++; + *nflagPtr = PREV_ERR_FAIL; + CVRestore(cv_mem, saved_t); + + /* At maxnef failures or |h| = hmin, return CV_ERR_FAILURE */ + if ((ABS(h) <= hmin*ONEPSM) || (*nefPtr == maxnef)) return(CV_ERR_FAILURE); + + /* Set etamax = 1 to prevent step size increase at end of this step */ + etamax = ONE; + + /* Set h ratio eta from dsm, rescale, and return for retry of step */ + if (*nefPtr <= MXNEF1) { + eta = ONE / (RPowerR(BIAS2*dsm,ONE/L) + ADDON); + eta = MAX(ETAMIN, MAX(eta, hmin / ABS(h))); + if (*nefPtr >= SMALL_NEF) eta = MIN(eta, ETAMXF); + CVRescale(cv_mem); + return(TRY_AGAIN); + } + + /* After MXNEF1 failures, force an order reduction and retry step */ + if (q > 1) { + eta = MAX(ETAMIN, hmin / ABS(h)); + CVAdjustOrder(cv_mem,-1); + L = q; + q--; + qwait = L; + CVRescale(cv_mem); + return(TRY_AGAIN); + } + + /* If already at order 1, restart: reload zn from scratch */ + + eta = MAX(ETAMIN, hmin / ABS(h)); + h *= eta; + next_h = h; + hscale = h; + qwait = LONG_WAIT; + nscon = 0; + + retval = f(tn, zn[0], tempv, user_data); + nfe++; + if (retval < 0) return(CV_RHSFUNC_FAIL); + if (retval > 0) return(CV_UNREC_RHSFUNC_ERR); + + N_VScale(h, tempv, zn[1]); + + return(TRY_AGAIN); +} + +/* + * ================================================================= + * Private Functions Implementation after succesful step + * ================================================================= + */ + +/* + * CVCompleteStep + * + * This routine performs various update operations when the solution + * to the nonlinear system has passed the local error test. + * We increment the step counter nst, record the values hu and qu, + * update the tau array, and apply the corrections to the zn array. + * The tau[i] are the last q values of h, with tau[1] the most recent. + * The counter qwait is decremented, and if qwait == 1 (and q < qmax) + * we save acor and tq[5] for a possible order increase. + */ + +static void CVCompleteStep(CVodeMem cv_mem) +{ + int i, j; + + nst++; + nscon++; + hu = h; + qu = q; + + for (i=q; i >= 2; i--) tau[i] = tau[i-1]; + if ((q==1) && (nst > 1)) tau[2] = tau[1]; + tau[1] = h; + + for (j=0; j <= q; j++) + N_VLinearSum(l[j], acor, ONE, zn[j], zn[j]); + qwait--; + if ((qwait == 1) && (q != qmax)) { + N_VScale(ONE, acor, zn[qmax]); + saved_tq5 = tq[5]; + indx_acor = qmax; + } +} + +/* + * CVprepareNextStep + * + * This routine handles the setting of stepsize and order for the + * next step -- hprime and qprime. Along with hprime, it sets the + * ratio eta = hprime/h. It also updates other state variables + * related to a change of step size or order. + */ + + static void CVPrepareNextStep(CVodeMem cv_mem, realtype dsm) +{ + /* If etamax = 1, defer step size or order changes */ + if (etamax == ONE) { + qwait = MAX(qwait, 2); + qprime = q; + hprime = h; + eta = ONE; + return; + } + + /* etaq is the ratio of new to old h at the current order */ + etaq = ONE /(RPowerR(BIAS2*dsm,ONE/L) + ADDON); + + /* If no order change, adjust eta and acor in CVSetEta and return */ + if (qwait != 0) { + eta = etaq; + qprime = q; + CVSetEta(cv_mem); + return; + } + + /* If qwait = 0, consider an order change. etaqm1 and etaqp1 are + the ratios of new to old h at orders q-1 and q+1, respectively. + CVChooseEta selects the largest; CVSetEta adjusts eta and acor */ + qwait = 2; + etaqm1 = CVComputeEtaqm1(cv_mem); + etaqp1 = CVComputeEtaqp1(cv_mem); + CVChooseEta(cv_mem); + CVSetEta(cv_mem); +} + +/* + * CVsetEta + * + * This routine adjusts the value of eta according to the various + * heuristic limits and the optional input hmax. It also resets + * etamax to be the estimated local error vector. + */ + +static void CVSetEta(CVodeMem cv_mem) +{ + + /* If eta below the threshhold THRESH, reject a change of step size */ + if (eta < THRESH) { + eta = ONE; + hprime = h; + } else { + /* Limit eta by etamax and hmax, then set hprime */ + eta = MIN(eta, etamax); + eta /= MAX(ONE, ABS(h)*hmax_inv*eta); + hprime = h * eta; + if (qprime < q) nscon = 0; + } + + /* Reset etamax for the next step size change, and scale acor */ +} + +/* + * CVComputeEtaqm1 + * + * This routine computes and returns the value of etaqm1 for a + * possible decrease in order by 1. + */ + +static realtype CVComputeEtaqm1(CVodeMem cv_mem) +{ + realtype ddn; + + etaqm1 = ZERO; + if (q > 1) { + ddn = N_VWrmsNorm(zn[q], ewt) * tq[1]; + etaqm1 = ONE/(RPowerR(BIAS1*ddn, ONE/q) + ADDON); + } + return(etaqm1); +} + +/* + * CVComputeEtaqp1 + * + * This routine computes and returns the value of etaqp1 for a + * possible increase in order by 1. + */ + +static realtype CVComputeEtaqp1(CVodeMem cv_mem) +{ + realtype dup, cquot; + + etaqp1 = ZERO; + if (q != qmax) { + if (saved_tq5 == ZERO) return(etaqp1); + cquot = (tq[5] / saved_tq5) * RPowerI(h/tau[2], L); + N_VLinearSum(-cquot, zn[qmax], ONE, acor, tempv); + dup = N_VWrmsNorm(tempv, ewt) * tq[3]; + etaqp1 = ONE / (RPowerR(BIAS3*dup, ONE/(L+1)) + ADDON); + } + return(etaqp1); +} + +/* + * CVChooseEta + * Given etaqm1, etaq, etaqp1 (the values of eta for qprime = + * q - 1, q, or q + 1, respectively), this routine chooses the + * maximum eta value, sets eta to that value, and sets qprime to the + * corresponding value of q. If there is a tie, the preference + * order is to (1) keep the same order, then (2) decrease the order, + * and finally (3) increase the order. If the maximum eta value + * is below the threshhold THRESH, the order is kept unchanged and + * eta is set to 1. + */ + +static void CVChooseEta(CVodeMem cv_mem) +{ + realtype etam; + + etam = MAX(etaqm1, MAX(etaq, etaqp1)); + + if (etam < THRESH) { + eta = ONE; + qprime = q; + return; + } + + if (etam == etaq) { + + eta = etaq; + qprime = q; + + } else if (etam == etaqm1) { + + eta = etaqm1; + qprime = q - 1; + + } else { + + eta = etaqp1; + qprime = q + 1; + + if (lmm == CV_BDF) { + + /* + * Store Delta_n in zn[qmax] to be used in order increase + * + * This happens at the last step of order q before an increase + * to order q+1, so it represents Delta_n in the ELTE at q+1 + */ + + N_VScale(ONE, acor, zn[qmax]); + + } + + } + +} + +/* + * CVHandleFailure + * + * This routine prints error messages for all cases of failure by + * CVHin and CVStep. It returns to CVode the value that CVode is + * to return to the user. + */ + +static int CVHandleFailure(CVodeMem cv_mem, int flag) +{ + + /* Set vector of absolute weighted local errors */ + /* + N_VProd(acor, ewt, tempv); + N_VAbs(tempv, tempv); + */ + + /* Depending on flag, print error message and return error flag */ + switch (flag) { + case CV_ERR_FAILURE: + CVProcessError(cv_mem, CV_ERR_FAILURE, "CVODE", "CVode", MSGCV_ERR_FAILS, tn, h); + break; + case CV_CONV_FAILURE: + CVProcessError(cv_mem, CV_CONV_FAILURE, "CVODE", "CVode", MSGCV_CONV_FAILS, tn, h); + break; + case CV_LSETUP_FAIL: + CVProcessError(cv_mem, CV_LSETUP_FAIL, "CVODE", "CVode", MSGCV_SETUP_FAILED, tn); + break; + case CV_LSOLVE_FAIL: + CVProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODE", "CVode", MSGCV_SOLVE_FAILED, tn); + break; + case CV_RHSFUNC_FAIL: + CVProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED, tn); + break; + case CV_UNREC_RHSFUNC_ERR: + CVProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_UNREC, tn); + break; + case CV_REPTD_RHSFUNC_ERR: + CVProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_REPTD, tn); + break; + case CV_RTFUNC_FAIL: + CVProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVode", MSGCV_RTFUNC_FAILED, tn); + break; + case CV_TOO_CLOSE: + CVProcessError(cv_mem, CV_TOO_CLOSE, "CVODE", "CVode", MSGCV_TOO_CLOSE); + break; + default: + return(CV_SUCCESS); + } + + return(flag); + +} + +/* + * ================================================================= + * BDF Stability Limit Detection + * ================================================================= + */ + +/* + * CVBDFStab + * + * This routine handles the BDF Stability Limit Detection Algorithm + * STALD. It is called if lmm = CV_BDF and the SLDET option is on. + * If the order is 3 or more, the required norm data is saved. + * If a decision to reduce order has not already been made, and + * enough data has been saved, CVsldet is called. If it signals + * a stability limit violation, the order is reduced, and the step + * size is reset accordingly. + */ + +void CVBDFStab(CVodeMem cv_mem) +{ + int i,k, ldflag, factorial; + realtype sq, sqm1, sqm2; + + /* If order is 3 or greater, then save scaled derivative data, + push old data down in i, then add current values to top. */ + + if (q >= 3) { + for (k = 1; k <= 3; k++) + { for (i = 5; i >= 2; i--) ssdat[i][k] = ssdat[i-1][k]; } + factorial = 1; + for (i = 1; i <= q-1; i++) factorial *= i; + sq = factorial*q*(q+1)*acnrm/MAX(tq[5],TINY); + sqm1 = factorial*q*N_VWrmsNorm(zn[q], ewt); + sqm2 = factorial*N_VWrmsNorm(zn[q-1], ewt); + ssdat[1][1] = sqm2*sqm2; + ssdat[1][2] = sqm1*sqm1; + ssdat[1][3] = sq*sq; + } + + if (qprime >= q) { + + /* If order is 3 or greater, and enough ssdat has been saved, + nscon >= q+5, then call stability limit detection routine. */ + + if ( (q >= 3) && (nscon >= q+5) ) { + ldflag = CVsldet(cv_mem); + if (ldflag > 3) { + /* A stability limit violation is indicated by + a return flag of 4, 5, or 6. + Reduce new order. */ + qprime = q-1; + eta = etaqm1; + eta = MIN(eta,etamax); + eta = eta/MAX(ONE,ABS(h)*hmax_inv*eta); + hprime = h*eta; + nor = nor + 1; + } + } + } + else { + /* Otherwise, let order increase happen, and + reset stability limit counter, nscon. */ + nscon = 0; + } +} + +/* + * CVsldet + * + * This routine detects stability limitation using stored scaled + * derivatives data. CVsldet returns the magnitude of the + * dominate characteristic root, rr. The presents of a stability + * limit is indicated by rr > "something a little less then 1.0", + * and a positive kflag. This routine should only be called if + * order is greater than or equal to 3, and data has been collected + * for 5 time steps. + * + * Returned values: + * kflag = 1 -> Found stable characteristic root, normal matrix case + * kflag = 2 -> Found stable characteristic root, quartic solution + * kflag = 3 -> Found stable characteristic root, quartic solution, + * with Newton correction + * kflag = 4 -> Found stability violation, normal matrix case + * kflag = 5 -> Found stability violation, quartic solution + * kflag = 6 -> Found stability violation, quartic solution, + * with Newton correction + * + * kflag < 0 -> No stability limitation, + * or could not compute limitation. + * + * kflag = -1 -> Min/max ratio of ssdat too small. + * kflag = -2 -> For normal matrix case, vmax > vrrt2*vrrt2 + * kflag = -3 -> For normal matrix case, The three ratios + * are inconsistent. + * kflag = -4 -> Small coefficient prevents elimination of quartics. + * kflag = -5 -> R value from quartics not consistent. + * kflag = -6 -> No corrected root passes test on qk values + * kflag = -7 -> Trouble solving for sigsq. + * kflag = -8 -> Trouble solving for B, or R via B. + * kflag = -9 -> R via sigsq[k] disagrees with R from data. + */ + +static int CVsldet(CVodeMem cv_mem) +{ + int i, k, j, it, kmin, kflag = 0; + realtype rat[5][4], rav[4], qkr[4], sigsq[4], smax[4], ssmax[4]; + realtype drr[4], rrc[4],sqmx[4], qjk[4][4], vrat[5], qc[6][4], qco[6][4]; + realtype rr, rrcut, vrrtol, vrrt2, sqtol, rrtol; + realtype smink, smaxk, sumrat, sumrsq, vmin, vmax, drrmax, adrr; + realtype tem, sqmax, saqk, qp, s, sqmaxk, saqj, sqmin; + realtype rsa, rsb, rsc, rsd, rd1a, rd1b, rd1c; + realtype rd2a, rd2b, rd3a, cest1, corr1; + realtype ratp, ratm, qfac1, qfac2, bb, rrb; + + /* The following are cutoffs and tolerances used by this routine */ + + rrcut = RCONST(0.98); + vrrtol = RCONST(1.0e-4); + vrrt2 = RCONST(5.0e-4); + sqtol = RCONST(1.0e-3); + rrtol = RCONST(1.0e-2); + + rr = ZERO; + + /* Index k corresponds to the degree of the interpolating polynomial. */ + /* k = 1 -> q-1 */ + /* k = 2 -> q */ + /* k = 3 -> q+1 */ + + /* Index i is a backward-in-time index, i = 1 -> current time, */ + /* i = 2 -> previous step, etc */ + + /* get maxima, minima, and variances, and form quartic coefficients */ + + for (k=1; k<=3; k++) { + smink = ssdat[1][k]; + smaxk = ZERO; + + for (i=1; i<=5; i++) { + smink = MIN(smink,ssdat[i][k]); + smaxk = MAX(smaxk,ssdat[i][k]); + } + + if (smink < TINY*smaxk) { + kflag = -1; + return(kflag); + } + smax[k] = smaxk; + ssmax[k] = smaxk*smaxk; + + sumrat = ZERO; + sumrsq = ZERO; + for (i=1; i<=4; i++) { + rat[i][k] = ssdat[i][k]/ssdat[i+1][k]; + sumrat = sumrat + rat[i][k]; + sumrsq = sumrsq + rat[i][k]*rat[i][k]; + } + rav[k] = FOURTH*sumrat; + vrat[k] = ABS(FOURTH*sumrsq - rav[k]*rav[k]); + + qc[5][k] = ssdat[1][k]*ssdat[3][k] - ssdat[2][k]*ssdat[2][k]; + qc[4][k] = ssdat[2][k]*ssdat[3][k] - ssdat[1][k]*ssdat[4][k]; + qc[3][k] = ZERO; + qc[2][k] = ssdat[2][k]*ssdat[5][k] - ssdat[3][k]*ssdat[4][k]; + qc[1][k] = ssdat[4][k]*ssdat[4][k] - ssdat[3][k]*ssdat[5][k]; + + for (i=1; i<=5; i++) { + qco[i][k] = qc[i][k]; + } + } /* End of k loop */ + + /* Isolate normal or nearly-normal matrix case. Three quartic will + have common or nearly-common roots in this case. + Return a kflag = 1 if this procedure works. If three root + differ more than vrrt2, return error kflag = -3. */ + + vmin = MIN(vrat[1],MIN(vrat[2],vrat[3])); + vmax = MAX(vrat[1],MAX(vrat[2],vrat[3])); + + if(vmin < vrrtol*vrrtol) { + if (vmax > vrrt2*vrrt2) { + kflag = -2; + return(kflag); + } else { + rr = (rav[1] + rav[2] + rav[3])/THREE; + + drrmax = ZERO; + for(k = 1;k<=3;k++) { + adrr = ABS(rav[k] - rr); + drrmax = MAX(drrmax, adrr); + } + if (drrmax > vrrt2) { + kflag = -3; + } + + kflag = 1; + + /* can compute charactistic root, drop to next section */ + + } + } else { + + /* use the quartics to get rr. */ + + if (ABS(qco[1][1]) < TINY*ssmax[1]) { + kflag = -4; + return(kflag); + } + + tem = qco[1][2]/qco[1][1]; + for(i=2; i<=5; i++) { + qco[i][2] = qco[i][2] - tem*qco[i][1]; + } + + qco[1][2] = ZERO; + tem = qco[1][3]/qco[1][1]; + for(i=2; i<=5; i++) { + qco[i][3] = qco[i][3] - tem*qco[i][1]; + } + qco[1][3] = ZERO; + + if (ABS(qco[2][2]) < TINY*ssmax[2]) { + kflag = -4; + return(kflag); + } + + tem = qco[2][3]/qco[2][2]; + for(i=3; i<=5; i++) { + qco[i][3] = qco[i][3] - tem*qco[i][2]; + } + + if (ABS(qco[4][3]) < TINY*ssmax[3]) { + kflag = -4; + return(kflag); + } + + rr = -qco[5][3]/qco[4][3]; + + if (rr < TINY || rr > HUN) { + kflag = -5; + return(kflag); + } + + for(k=1; k<=3; k++) { + qkr[k] = qc[5][k] + rr*(qc[4][k] + rr*rr*(qc[2][k] + rr*qc[1][k])); + } + + sqmax = ZERO; + for(k=1; k<=3; k++) { + saqk = ABS(qkr[k])/ssmax[k]; + if (saqk > sqmax) sqmax = saqk; + } + + if (sqmax < sqtol) { + kflag = 2; + + /* can compute charactistic root, drop to "given rr,etc" */ + + } else { + + /* do Newton corrections to improve rr. */ + + for(it=1; it<=3; it++) { + for(k=1; k<=3; k++) { + qp = qc[4][k] + rr*rr*(THREE*qc[2][k] + rr*FOUR*qc[1][k]); + drr[k] = ZERO; + if (ABS(qp) > TINY*ssmax[k]) drr[k] = -qkr[k]/qp; + rrc[k] = rr + drr[k]; + } + + for(k=1; k<=3; k++) { + s = rrc[k]; + sqmaxk = ZERO; + for(j=1; j<=3; j++) { + qjk[j][k] = qc[5][j] + s*(qc[4][j] + + s*s*(qc[2][j] + s*qc[1][j])); + saqj = ABS(qjk[j][k])/ssmax[j]; + if (saqj > sqmaxk) sqmaxk = saqj; + } + sqmx[k] = sqmaxk; + } + + sqmin = sqmx[1]; kmin = 1; + for(k=2; k<=3; k++) { + if (sqmx[k] < sqmin) { + kmin = k; + sqmin = sqmx[k]; + } + } + rr = rrc[kmin]; + + if (sqmin < sqtol) { + kflag = 3; + /* can compute charactistic root */ + /* break out of Newton correction loop and drop to "given rr,etc" */ + break; + } else { + for(j=1; j<=3; j++) { + qkr[j] = qjk[j][kmin]; + } + } + } /* end of Newton correction loop */ + + if (sqmin > sqtol) { + kflag = -6; + return(kflag); + } + } /* end of if (sqmax < sqtol) else */ + } /* end of if(vmin < vrrtol*vrrtol) else, quartics to get rr. */ + + /* given rr, find sigsq[k] and verify rr. */ + /* All positive kflag drop to this section */ + + for(k=1; k<=3; k++) { + rsa = ssdat[1][k]; + rsb = ssdat[2][k]*rr; + rsc = ssdat[3][k]*rr*rr; + rsd = ssdat[4][k]*rr*rr*rr; + rd1a = rsa - rsb; + rd1b = rsb - rsc; + rd1c = rsc - rsd; + rd2a = rd1a - rd1b; + rd2b = rd1b - rd1c; + rd3a = rd2a - rd2b; + + if (ABS(rd1b) < TINY*smax[k]) { + kflag = -7; + return(kflag); + } + + cest1 = -rd3a/rd1b; + if (cest1 < TINY || cest1 > FOUR) { + kflag = -7; + return(kflag); + } + corr1 = (rd2b/cest1)/(rr*rr); + sigsq[k] = ssdat[3][k] + corr1; + } + + if (sigsq[2] < TINY) { + kflag = -8; + return(kflag); + } + + ratp = sigsq[3]/sigsq[2]; + ratm = sigsq[1]/sigsq[2]; + qfac1 = FOURTH*(q*q - ONE); + qfac2 = TWO/(q - ONE); + bb = ratp*ratm - ONE - qfac1*ratp; + tem = ONE - qfac2*bb; + + if (ABS(tem) < TINY) { + kflag = -8; + return(kflag); + } + + rrb = ONE/tem; + + if (ABS(rrb - rr) > rrtol) { + kflag = -9; + return(kflag); + } + + /* Check to see if rr is above cutoff rrcut */ + if (rr > rrcut) { + if (kflag == 1) kflag = 4; + if (kflag == 2) kflag = 5; + if (kflag == 3) kflag = 6; + } + + /* All positive kflag returned at this point */ + + return(kflag); + +} + +/* + * ================================================================= + * Root finding + * ================================================================= + */ + +/*-----------------------------------------------------------------*/ + +/* + * CVRcheck1 + * + * This routine completes the initialization of rootfinding memory + * information, and checks whether g has a zero both at and very near + * the initial point of the IVP. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * CV_SUCCESS = 0 otherwise. + */ + +static int CVRcheck1(CVodeMem cv_mem) +{ + int i, retval; + realtype smallh, hratio, tplus; + booleantype zroot; + + for (i = 0; i < nrtfn; i++) iroots[i] = 0; + tlo = tn; + ttol = (ABS(tn) + ABS(h))*uround*HUN; + + /* Evaluate g at initial t and check for zero values. */ + retval = gfun(tlo, zn[0], glo, user_data); + nge = 1; + if (retval != 0) return(CV_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) { + if (ABS(glo[i]) == ZERO) { + zroot = TRUE; + gactive[i] = FALSE; + } + } + if (!zroot) return(CV_SUCCESS); + + /* Some g_i is zero at t0; look at g at t0+(small increment). */ + hratio = MAX(ttol/ABS(h), TENTH); + smallh = hratio*h; + tplus = tlo + smallh; + N_VLinearSum(ONE, zn[0], hratio, zn[1], y); + retval = gfun(tplus, y, ghi, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + /* We check now only the components of g which were exactly 0.0 at t0 + * to see if we can 'activate' them. */ + for (i = 0; i < nrtfn; i++) { + if (!gactive[i] && ABS(ghi[i]) != ZERO) { + gactive[i] = TRUE; + glo[i] = ghi[i]; + } + } + return(CV_SUCCESS); +} + +/* + * CVRcheck2 + * + * This routine checks for exact zeros of g at the last root found, + * if the last return was a root. It then checks for a close pair of + * zeros (an error condition), and for a new root at a nearby point. + * The array glo = g(tlo) at the left endpoint of the search interval + * is adjusted if necessary to assure that all g_i are nonzero + * there, before returning to do a root search in the interval. + * + * On entry, tlo = tretlast is the last value of tret returned by + * CVode. This may be the previous tn, the previous tout value, or + * the last root location. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * CLOSERT = 3 if a close pair of zeros was found, or + * RTFOUND = 1 if a new zero of g was found near tlo, or + * CV_SUCCESS = 0 otherwise. + */ + +static int CVRcheck2(CVodeMem cv_mem) +{ + int i, retval; + realtype smallh, hratio, tplus; + booleantype zroot; + + if (irfnd == 0) return(CV_SUCCESS); + + (void) CVodeGetDky(cv_mem, tlo, 0, y); + retval = gfun(tlo, y, glo, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + zroot = FALSE; + for (i = 0; i < nrtfn; i++) iroots[i] = 0; + for (i = 0; i < nrtfn; i++) { + if (!gactive[i]) continue; + if (ABS(glo[i]) == ZERO) { + zroot = TRUE; + iroots[i] = 1; + } + } + if (!zroot) return(CV_SUCCESS); + + /* One or more g_i has a zero at tlo. Check g at tlo+smallh. */ + ttol = (ABS(tn) + ABS(h))*uround*HUN; + smallh = (h > ZERO) ? ttol : -ttol; + tplus = tlo + smallh; + if ( (tplus - tn)*h >= ZERO) { + hratio = smallh/h; + N_VLinearSum(ONE, y, hratio, zn[1], y); + } else { + (void) CVodeGetDky(cv_mem, tplus, 0, y); + } + retval = gfun(tplus, y, ghi, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + /* Check for close roots (error return), for a new zero at tlo+smallh, + and for a g_i that changed from zero to nonzero. */ + zroot = FALSE; + for (i = 0; i < nrtfn; i++) { + if (ABS(ghi[i]) == ZERO) { + if (!gactive[i]) continue; + if (iroots[i] == 1) return(CLOSERT); + zroot = TRUE; + iroots[i] = 1; + } else { + if (iroots[i] == 1) glo[i] = ghi[i]; + } + } + if (zroot) return(RTFOUND); + return(CV_SUCCESS); +} + +/* + * CVRcheck3 + * + * This routine interfaces to CVRootfind to look for a root of g + * between tlo and either tn or tout, whichever comes first. + * Only roots beyond tlo in the direction of integration are sought. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * RTFOUND = 1 if a root of g was found, or + * CV_SUCCESS = 0 otherwise. + */ + +static int CVRcheck3(CVodeMem cv_mem) +{ + int i, retval, ier; + + /* Set thi = tn or tout, whichever comes first; set y = y(thi). */ + if (taskc == CV_ONE_STEP) { + thi = tn; + N_VScale(ONE, zn[0], y); + } + if (taskc == CV_NORMAL) { + if ( (toutc - tn)*h >= ZERO) { + thi = tn; + N_VScale(ONE, zn[0], y); + } else { + thi = toutc; + (void) CVodeGetDky(cv_mem, thi, 0, y); + } + } + + /* Set ghi = g(thi) and call CVRootfind to search (tlo,thi) for roots. */ + retval = gfun(thi, y, ghi, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + ttol = (ABS(tn) + ABS(h))*uround*HUN; + ier = CVRootfind(cv_mem); + if (ier == CV_RTFUNC_FAIL) return(CV_RTFUNC_FAIL); + for(i=0; i 0, search for roots of g_i only if + * g_i is increasing; if rootdir[i] < 0, search for + * roots of g_i only if g_i is decreasing; otherwise + * always search for roots of g_i. + * + * gactive = array specifying whether a component of g should + * or should not be monitored. gactive[i] is initially + * set to TRUE for all i=0,...,nrtfn-1, but it may be + * reset to FALSE if at the first step g[i] is 0.0 + * both at the I.C. and at a small perturbation of them. + * gactive[i] is then set back on TRUE only after the + * corresponding g function moves away from 0.0. + * + * nge = cumulative counter for gfun calls. + * + * ttol = a convergence tolerance for trout. Input only. + * When a root at trout is found, it is located only to + * within a tolerance of ttol. Typically, ttol should + * be set to a value on the order of + * 100 * UROUND * max (ABS(tlo), ABS(thi)) + * where UROUND is the unit roundoff of the machine. + * + * tlo, thi = endpoints of the interval in which roots are sought. + * On input, and must be distinct, but tlo - thi may + * be of either sign. The direction of integration is + * assumed to be from tlo to thi. On return, tlo and thi + * are the endpoints of the final relevant interval. + * + * glo, ghi = arrays of length nrtfn containing the vectors g(tlo) + * and g(thi) respectively. Input and output. On input, + * none of the glo[i] should be zero. + * + * trout = root location, if a root was found, or thi if not. + * Output only. If a root was found other than an exact + * zero of g, trout is the endpoint thi of the final + * interval bracketing the root, with size at most ttol. + * + * grout = array of length nrtfn containing g(trout) on return. + * + * iroots = int array of length nrtfn with root information. + * Output only. If a root was found, iroots indicates + * which components g_i have a root at trout. For + * i = 0, ..., nrtfn-1, iroots[i] = 1 if g_i has a root + * and g_i is increasing, iroots[i] = -1 if g_i has a + * root and g_i is decreasing, and iroots[i] = 0 if g_i + * has no roots or g_i varies in the direction opposite + * to that indicated by rootdir[i]. + * + * This routine returns an int equal to: + * CV_RTFUNC_FAIL = -12 if the g function failed, or + * RTFOUND = 1 if a root of g was found, or + * CV_SUCCESS = 0 otherwise. + */ + +static int CVRootfind(CVodeMem cv_mem) +{ + realtype alpha, tmid, gfrac, maxfrac, fracint, fracsub; + int i, retval, imax, side, sideprev; + booleantype zroot, sgnchg; + + imax = 0; + + /* First check for change in sign in ghi or for a zero in ghi. */ + maxfrac = ZERO; + zroot = FALSE; + sgnchg = FALSE; + for (i = 0; i < nrtfn; i++) { + if(!gactive[i]) continue; + if (ABS(ghi[i]) == ZERO) { + if(rootdir[i]*glo[i] <= ZERO) { + zroot = TRUE; + } + } else { + if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) { + gfrac = ABS(ghi[i]/(ghi[i] - glo[i])); + if (gfrac > maxfrac) { + sgnchg = TRUE; + maxfrac = gfrac; + imax = i; + } + } + } + } + + /* If no sign change was found, reset trout and grout. Then return + CV_SUCCESS if no zero was found, or set iroots and return RTFOUND. */ + if (!sgnchg) { + trout = thi; + for (i = 0; i < nrtfn; i++) grout[i] = ghi[i]; + if (!zroot) return(CV_SUCCESS); + for (i = 0; i < nrtfn; i++) { + iroots[i] = 0; + if(!gactive[i]) continue; + if (ABS(ghi[i]) == ZERO) iroots[i] = glo[i] > 0 ? -1:1; + } + return(RTFOUND); + } + + /* Initialize alpha to avoid compiler warning */ + alpha = ONE; + + /* A sign change was found. Loop to locate nearest root. */ + + side = 0; sideprev = -1; + loop { /* Looping point */ + + /* Set weight alpha. + On the first two passes, set alpha = 1. Thereafter, reset alpha + according to the side (low vs high) of the subinterval in which + the sign change was found in the previous two passes. + If the sides were opposite, set alpha = 1. + If the sides were the same, then double alpha (if high side), + or halve alpha (if low side). + The next guess tmid is the secant method value if alpha = 1, but + is closer to tlo if alpha < 1, and closer to thi if alpha > 1. */ + + if (sideprev == side) { + alpha = (side == 2) ? alpha*TWO : alpha*HALF; + } else { + alpha = ONE; + } + + /* Set next root approximation tmid and get g(tmid). + If tmid is too close to tlo or thi, adjust it inward, + by a fractional distance that is between 0.1 and 0.5. */ + tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alpha*glo[imax]); + if (ABS(tmid - tlo) < HALF*ttol) { + fracint = ABS(thi - tlo)/ttol; + fracsub = (fracint > FIVE) ? TENTH : HALF/fracint; + tmid = tlo + fracsub*(thi - tlo); + } + if (ABS(thi - tmid) < HALF*ttol) { + fracint = ABS(thi - tlo)/ttol; + fracsub = (fracint > FIVE) ? TENTH : HALF/fracint; + tmid = thi - fracsub*(thi - tlo); + } + + (void) CVodeGetDky(cv_mem, tmid, 0, y); + retval = gfun(tmid, y, grout, user_data); + nge++; + if (retval != 0) return(CV_RTFUNC_FAIL); + + /* Check to see in which subinterval g changes sign, and reset imax. + Set side = 1 if sign change is on low side, or 2 if on high side. */ + maxfrac = ZERO; + zroot = FALSE; + sgnchg = FALSE; + sideprev = side; + for (i = 0; i < nrtfn; i++) { + if(!gactive[i]) continue; + if (ABS(grout[i]) == ZERO) { + if(rootdir[i]*glo[i] <= ZERO) { + zroot = TRUE; + } + } else { + if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) { + gfrac = ABS(grout[i]/(grout[i] - glo[i])); + if (gfrac > maxfrac) { + sgnchg = TRUE; + maxfrac = gfrac; + imax = i; + } + } + } + } + if (sgnchg) { + /* Sign change found in (tlo,tmid); replace thi with tmid. */ + thi = tmid; + for (i = 0; i < nrtfn; i++) ghi[i] = grout[i]; + side = 1; + /* Stop at root thi if converged; otherwise loop. */ + if (ABS(thi - tlo) <= ttol) break; + continue; /* Return to looping point. */ + } + + if (zroot) { + /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */ + thi = tmid; + for (i = 0; i < nrtfn; i++) ghi[i] = grout[i]; + break; + } + + /* No sign change in (tlo,tmid), and no zero at tmid. + Sign change must be in (tmid,thi). Replace tlo with tmid. */ + tlo = tmid; + for (i = 0; i < nrtfn; i++) glo[i] = grout[i]; + side = 2; + /* Stop at root thi if converged; otherwise loop back. */ + if (ABS(thi - tlo) <= ttol) break; + + } /* End of root-search loop */ + + /* Reset trout and grout, set iroots, and return RTFOUND. */ + trout = thi; + for (i = 0; i < nrtfn; i++) { + grout[i] = ghi[i]; + iroots[i] = 0; + if(!gactive[i]) continue; + if ( (ABS(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) ) + iroots[i] = glo[i] > 0 ? -1:1; + if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) + iroots[i] = glo[i] > 0 ? -1:1; + } + return(RTFOUND); +} + +/* + * ================================================================= + * Internal EWT function + * ================================================================= + */ + +/* + * CVEwtSet + * + * This routine is responsible for setting the error weight vector ewt, + * according to tol_type, as follows: + * + * (1) ewt[i] = 1 / (reltol * ABS(ycur[i]) + *abstol), i=0,...,neq-1 + * if tol_type = CV_SS + * (2) ewt[i] = 1 / (reltol * ABS(ycur[i]) + abstol[i]), i=0,...,neq-1 + * if tol_type = CV_SV + * + * CVEwtSet returns 0 if ewt is successfully set as above to a + * positive vector and -1 otherwise. In the latter case, ewt is + * considered undefined. + * + * All the real work is done in the routines CVEwtSetSS, CVEwtSetSV. + */ + +int CVEwtSet(N_Vector ycur, N_Vector weight, void *data) +{ + CVodeMem cv_mem; + int flag = 0; + + /* data points to cv_mem here */ + + cv_mem = (CVodeMem) data; + + switch(itol) { + case CV_SS: + flag = CVEwtSetSS(cv_mem, ycur, weight); + break; + case CV_SV: + flag = CVEwtSetSV(cv_mem, ycur, weight); + break; + } + + return(flag); +} + +/* + * CVEwtSetSS + * + * This routine sets ewt as decribed above in the case tol_type = CV_SS. + * It tests for non-positive components before inverting. CVEwtSetSS + * returns 0 if ewt is successfully set to a positive vector + * and -1 otherwise. In the latter case, ewt is considered undefined. + */ + +static int CVEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight) +{ + N_VAbs(ycur, tempv); + N_VScale(reltol, tempv, tempv); + N_VAddConst(tempv, Sabstol, tempv); + if (N_VMin(tempv) <= ZERO) return(-1); + N_VInv(tempv, weight); + return(0); +} + +/* + * CVEwtSetSV + * + * This routine sets ewt as decribed above in the case tol_type = CV_SV. + * It tests for non-positive components before inverting. CVEwtSetSV + * returns 0 if ewt is successfully set to a positive vector + * and -1 otherwise. In the latter case, ewt is considered undefined. + */ + +static int CVEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight) +{ + N_VAbs(ycur, tempv); + N_VLinearSum(reltol, tempv, ONE, Vabstol, tempv); + if (N_VMin(tempv) <= ZERO) return(-1); + N_VInv(tempv, weight); + return(0); +} + +/* + * ================================================================= + * CVODE Error Handling function + * ================================================================= + */ + +/* + * CVProcessError is a high level error handling function + * - if cv_mem==NULL it prints the error message to stderr + * - otherwise, it sets-up and calls the error hadling function + * pointed to by cv_ehfun + */ + +#define ehfun (cv_mem->cv_ehfun) +#define eh_data (cv_mem->cv_eh_data) + +void CVProcessError(CVodeMem cv_mem, + int error_code, const char *module, const char *fname, + const char *msgfmt, ...) +{ + va_list ap; + char msg[256]; + + /* Initialize the argument pointer variable + (msgfmt is the last required argument to CVProcessError) */ + + va_start(ap, msgfmt); + + if (cv_mem == NULL) { /* We write to stderr */ + +#ifndef NO_FPRINTF_OUTPUT + fprintf(stderr, "\n[%s ERROR] %s\n ", module, fname); + fprintf(stderr, msgfmt); + fprintf(stderr, "\n\n"); +#endif + + } else { /* We can call ehfun */ + + /* Compose the message */ + + vsprintf(msg, msgfmt, ap); + + /* Call ehfun */ + + ehfun(error_code, module, fname, msg, eh_data); + + } + + /* Finalize argument processing */ + + va_end(ap); + + return; + +} + +/* CVErrHandler is the default error handling function. + It sends the error message to the stream pointed to by cv_errfp */ + +#define errfp (cv_mem->cv_errfp) + +void CVErrHandler(int error_code, const char *module, + const char *function, char *msg, void *data) +{ + CVodeMem cv_mem; + char err_type[10]; + + /* data points to cv_mem here */ + + cv_mem = (CVodeMem) data; + + if (error_code == CV_WARNING) + sprintf(err_type,"WARNING"); + else + sprintf(err_type,"ERROR"); + +#ifndef NO_FPRINTF_OUTPUT + if (errfp!=NULL) { + fprintf(errfp,"\n[%s %s] %s\n",module,err_type,function); + fprintf(errfp," %s\n\n",msg); + } +#endif + + return; +} diff --git a/dep/cvode-2.7.0/cvode/cvode_band.c b/dep/cvode-2.7.0/cvode/cvode_band.c new file mode 100644 index 00000000..9ea0b4a8 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_band.c @@ -0,0 +1,361 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.13 $ + * $Date: 2011/03/23 22:27:43 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVBAND linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvode_direct_impl.h" +#include "cvode_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* CVBAND linit, lsetup, lsolve, and lfree routines */ + +static int cvBandInit(CVodeMem cv_mem); + +static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); + +static void cvBandFree(CVodeMem cv_mem); + +/* Readability Replacements */ + +#define lmm (cv_mem->cv_lmm) +#define f (cv_mem->cv_f) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) +#define nfe (cv_mem->cv_nfe) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define jacDQ (cvdls_mem->d_jacDQ) +#define jac (cvdls_mem->d_bjac) +#define M (cvdls_mem->d_M) +#define mu (cvdls_mem->d_mu) +#define ml (cvdls_mem->d_ml) +#define smu (cvdls_mem->d_smu) +#define lpivots (cvdls_mem->d_lpivots) +#define savedJ (cvdls_mem->d_savedJ) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define J_data (cvdls_mem->d_J_data) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * CVBand + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the band linear solver module. CVBand first calls + * the existing lfree routine if this is not NULL. It then sets the + * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem) + * to be cvBandInit, cvBandSetup, cvBandSolve, and cvBandFree, + * respectively. It allocates memory for a structure of type + * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem) to be + * TRUE, d_mu to be mupper, d_ml to be mlower, and the d_jac field to be + * cvDlsBandDQJac. + * Finally, it allocates memory for M, savedJ, and pivot. The CVBand + * return value is SUCCESS = 0, LMEM_FAIL = -1, or LIN_ILL_INPUT = -2. + * + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVBand will first + * test for compatible a compatible N_Vector internal + * representation by checking that the function + * N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ + +int CVBand(void *cvode_mem, long int N, long int mupper, long int mlower) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVBAND", "CVBand", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the BAND solver */ + if (vec_tmpl->ops->nvgetarraypointer == NULL) { + CVProcessError(cv_mem, CVDLS_ILL_INPUT, "CVBAND", "CVBand", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvBandInit; + lsetup = cvBandSetup; + lsolve = cvBandSolve; + lfree = cvBandFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_BAND; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + jac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + + setupNonNull = TRUE; + + /* Load problem dimension */ + n = N; + + /* Load half-bandwiths in cvdls_mem */ + ml = mlower; + mu = mupper; + + /* Test ml and mu for legality */ + if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) { + CVProcessError(cv_mem, CVDLS_ILL_INPUT, "CVBAND", "CVBand", MSGD_BAD_SIZES); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_ILL_INPUT); + } + + /* Set extended upper half-bandwith for M (required for pivoting) */ + smu = MIN(N-1, mu + ml); + + /* Allocate memory for M, savedJ, and pivot arrays */ + M = NULL; + M = NewBandMat(N, mu, ml, smu); + if (M == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + savedJ = NULL; + savedJ = NewBandMat(N, mu, ml, mu); + if (savedJ == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + lpivots = NULL; + lpivots = NewLintArray(N); + if (lpivots == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyMat(savedJ); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * cvBandInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the band + * linear solver. + * ----------------------------------------------------------------- + */ + +static int cvBandInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + jac = cvDlsBandDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the band linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix + * M = I - gamma*J, updates counters, and calls the band LU + * factorization routine. + * ----------------------------------------------------------------- + */ + +static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + long int ier; + CVDlsMem cvdls_mem; + int retval; + + cvdls_mem = (CVDlsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + BandCopy(savedJ, M, mu, ml); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = jac(n, mu, ml, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3); + if (retval < 0) { + CVProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVBAND", "cvBandSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + BandCopy(M, savedJ, mu, ml); + + } + + /* Scale and add I to get M = I - gamma*J */ + BandScale(-gamma, M); + AddIdentity(M); + + /* Do LU factorization of M */ + ier = BandGBTRF(M, lpivots); + + /* Return 0 if the LU was complete; otherwise return 1 */ + if (ier > 0) { + last_flag = ier; + return(1); + } + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandSolve + * ----------------------------------------------------------------- + * This routine handles the solve operation for the band linear solver + * by calling the band backsolve routine. The return value is 0. + * ----------------------------------------------------------------- + */ + +static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur) +{ + CVDlsMem cvdls_mem; + realtype *bd; + + cvdls_mem = (CVDlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + BandGBTRS(M, lpivots, bd); + + /* If CV_BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + N_VScale(TWO/(ONE + gamrat), b, b); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvBandFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the band linear solver. + * ----------------------------------------------------------------- + */ + +static void cvBandFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyMat(savedJ); + DestroyArray(lpivots); + free(cvdls_mem); + cv_mem->cv_lmem = NULL; +} + diff --git a/dep/cvode-2.7.0/cvode/cvode_bandpre.c b/dep/cvode-2.7.0/cvode/cvode_bandpre.c new file mode 100644 index 00000000..6892ba62 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_bandpre.c @@ -0,0 +1,478 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2010/12/01 22:21:04 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file contains implementations of the banded difference + * quotient Jacobian-based preconditioner and solver routines for + * use with the CVSPILS linear solvers.. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvode_impl.h" +#include "cvode_bandpre_impl.h" +#include "cvode_spils_impl.h" + +#include +#include +#include + +#include + +#define MIN_INC_MULT RCONST(1000.0) + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* Prototypes of CVBandPrecSetup and CVBandPrecSolve */ + +static int CVBandPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bp_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int CVBandPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bp_data, N_Vector tmp); + +/* Prototype for CVBandPrecFree */ + +static void CVBandPrecFree(CVodeMem cv_mem); + +/* Prototype for difference quotient Jacobian calculation routine */ + +static int CVBandPDQJac(CVBandPrecData pdata, + realtype t, N_Vector y, N_Vector fy, + N_Vector ftemp, N_Vector ytemp); + +/* Redability replacements */ + +#define vec_tmpl (cv_mem->cv_tempv) + +/* + * ----------------------------------------------------------------- + * Initialization, Free, and Get Functions + * NOTE: The band linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVBandPrecInit will + * first test for a compatible N_Vector internal representation + * by checking that the function N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ + +int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + long int mup, mlp, storagemu; + int flag; + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + /* Test if the NVECTOR package is compatible with the BAND preconditioner */ + if(vec_tmpl->ops->nvgetarraypointer == NULL) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInit", MSGBP_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + pdata = NULL; + pdata = (CVBandPrecData) malloc(sizeof *pdata); /* Allocate data memory */ + if (pdata == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Load pointers and bandwidths into pdata block. */ + pdata->cvode_mem = cvode_mem; + pdata->N = N; + pdata->mu = mup = MIN(N-1, MAX(0,mu)); + pdata->ml = mlp = MIN(N-1, MAX(0,ml)); + + /* Initialize nfeBP counter */ + pdata->nfeBP = 0; + + /* Allocate memory for saved banded Jacobian approximation. */ + pdata->savedJ = NULL; + pdata->savedJ = NewBandMat(N, mup, mlp, mup); + if (pdata->savedJ == NULL) { + free(pdata); pdata = NULL; + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Allocate memory for banded preconditioner. */ + storagemu = MIN(N-1, mup+mlp); + pdata->savedP = NULL; + pdata->savedP = NewBandMat(N, mup, mlp, storagemu); + if (pdata->savedP == NULL) { + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Allocate memory for pivot array. */ + pdata->lpivots = NULL; + pdata->lpivots = NewLintArray(N); + if (pdata->lpivots == NULL) { + DestroyMat(pdata->savedP); + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Overwrite the P_data field in the SPILS memory */ + cvspils_mem->s_P_data = pdata; + + /* Attach the pfree function */ + cvspils_mem->s_pfree = CVBandPrecFree; + + /* Attach preconditioner solve and setup functions */ + flag = CVSpilsSetPreconditioner(cvode_mem, CVBandPrecSetup, CVBandPrecSolve); + + return(flag); +} + +int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwBP, long int *leniwBP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + long int N, ml, mu, smu; + + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + CVProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBandPrecData) cvspils_mem->s_P_data; + + N = pdata->N; + mu = pdata->mu; + ml = pdata->ml; + smu = MIN( N-1, mu + ml); + + *leniwBP = pdata->N; + *lenrwBP = N * ( 2*ml + smu + mu + 2 ); + + return(CVSPILS_SUCCESS); +} + +int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + CVProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBandPrecData) cvspils_mem->s_P_data; + + *nfevalsBP = pdata->nfeBP; + + return(CVSPILS_SUCCESS); +} + +/* Readability Replacements */ + +#define N (pdata->N) +#define mu (pdata->mu) +#define ml (pdata->ml) +#define lpivots (pdata->lpivots) +#define savedJ (pdata->savedJ) +#define savedP (pdata->savedP) +#define nfeBP (pdata->nfeBP) + +/* + * ----------------------------------------------------------------- + * CVBandPrecSetup + * ----------------------------------------------------------------- + * Together CVBandPrecSetup and CVBandPrecSolve use a banded + * difference quotient Jacobian to create a preconditioner. + * CVBandPrecSetup calculates a new J, if necessary, then + * calculates P = I - gamma*J, and does an LU factorization of P. + * + * The parameters of CVBandPrecSetup are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data from the + * previous PrecSetup call will be reused + * (with the current value of gamma). + * A CVBandPrecSetup call with jok == TRUE should only + * occur after a call with jok == FALSE. + * + * *jcurPtr is a pointer to an output integer flag which is + * set by CVBandPrecond as follows: + * *jcurPtr = TRUE if Jacobian data was recomputed. + * *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * bp_data is a pointer to preconditoner data (set by CVBandPrecInit) + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for vectors of length N for work space. This + * routine uses only tmp1 and tmp2. + * + * The value to be returned by the CVBandPrecSetup function is + * 0 if successful, or + * 1 if the band factorization failed. + * ----------------------------------------------------------------- + */ + +static int CVBandPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bp_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVBandPrecData pdata; + CVodeMem cv_mem; + int retval; + long int ier; + + /* Assume matrix and lpivots have already been allocated. */ + pdata = (CVBandPrecData) bp_data; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + if (jok) { + + /* If jok = TRUE, use saved copy of J. */ + *jcurPtr = FALSE; + BandCopy(savedJ, savedP, mu, ml); + + } else { + + /* If jok = FALSE, call CVBandPDQJac for new J value. */ + *jcurPtr = TRUE; + SetToZero(savedJ); + + retval = CVBandPDQJac(pdata, t, y, fy, tmp1, tmp2); + if (retval < 0) { + CVProcessError(cv_mem, -1, "CVBANDPRE", "CVBandPrecSetup", MSGBP_RHSFUNC_FAILED); + return(-1); + } + if (retval > 0) { + return(1); + } + + BandCopy(savedJ, savedP, mu, ml); + + } + + /* Scale and add I to get savedP = I - gamma*J. */ + BandScale(-gamma, savedP); + AddIdentity(savedP); + + /* Do LU factorization of matrix. */ + ier = BandGBTRF(savedP, lpivots); + + /* Return 0 if the LU was complete; otherwise return 1. */ + if (ier > 0) return(1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVBandPrecSolve + * ----------------------------------------------------------------- + * CVBandPrecSolve solves a linear system P z = r, where P is the + * matrix computed by CVBandPrecond. + * + * The parameters of CVBandPrecSolve used here are as follows: + * + * r is the right-hand side vector of the linear system. + * + * bp_data is a pointer to preconditoner data (set by CVBandPrecInit) + * + * z is the output vector computed by CVBandPrecSolve. + * + * The value returned by the CVBandPrecSolve function is always 0, + * indicating success. + * ----------------------------------------------------------------- + */ + +static int CVBandPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bp_data, N_Vector tmp) +{ + CVBandPrecData pdata; + realtype *zd; + + /* Assume matrix and lpivots have already been allocated. */ + pdata = (CVBandPrecData) bp_data; + + /* Copy r to z. */ + N_VScale(ONE, r, z); + + /* Do band backsolve on the vector z. */ + zd = N_VGetArrayPointer(z); + + BandGBTRS(savedP, lpivots, zd); + + return(0); +} + + +static void CVBandPrecFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + CVBandPrecData pdata; + + if (cv_mem->cv_lmem == NULL) return; + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) return; + pdata = (CVBandPrecData) cvspils_mem->s_P_data; + + DestroyMat(savedJ); + DestroyMat(savedP); + DestroyArray(lpivots); + + free(pdata); + pdata = NULL; +} + +#define ewt (cv_mem->cv_ewt) +#define uround (cv_mem->cv_uround) +#define h (cv_mem->cv_h) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) + +/* + * ----------------------------------------------------------------- + * CVBandPDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation to + * the Jacobian of f(t,y). It assumes that a band matrix of type + * DlsMat is stored column-wise, and that elements within each column + * are contiguous. This makes it possible to get the address of a column + * of J via the macro BAND_COL and to write a simple for loop to set + * each of the elements of a column in succession. + * ----------------------------------------------------------------- + */ + +static int CVBandPDQJac(CVBandPrecData pdata, + realtype t, N_Vector y, N_Vector fy, + N_Vector ftemp, N_Vector ytemp) +{ + CVodeMem cv_mem; + realtype fnorm, minInc, inc, inc_inv, srur; + long int group, i, j, width, ngroups, i1, i2; + realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data; + int retval; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp. */ + ewt_data = N_VGetArrayPointer(ewt); + fy_data = N_VGetArrayPointer(fy); + ftemp_data = N_VGetArrayPointer(ftemp); + y_data = N_VGetArrayPointer(y); + ytemp_data = N_VGetArrayPointer(ytemp); + + /* Load ytemp with y = predicted y vector. */ + N_VScale(ONE, y, ytemp); + + /* Set minimum increment based on uround and norm of f. */ + srur = RSqrt(uround); + fnorm = N_VWrmsNorm(fy, ewt); + minInc = (fnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE; + + /* Set bandwidth and number of column groups for band differencing. */ + width = ml + mu + 1; + ngroups = MIN(width, N); + + for (group = 1; group <= ngroups; group++) { + + /* Increment all y_j in group. */ + for(j = group-1; j < N; j += width) { + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + ytemp_data[j] += inc; + } + + /* Evaluate f with incremented y. */ + + retval = f(t, ytemp, ftemp, user_data); + nfeBP++; + if (retval != 0) return(retval); + + /* Restore ytemp, then form and load difference quotients. */ + for (j = group-1; j < N; j += width) { + ytemp_data[j] = y_data[j]; + col_j = BAND_COL(savedJ,j); + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + inc_inv = ONE/inc; + i1 = MAX(0, j-mu); + i2 = MIN(j+ml, N-1); + for (i=i1; i <= i2; i++) + BAND_COL_ELEM(col_j,i,j) = + inc_inv * (ftemp_data[i] - fy_data[i]); + } + } + + return(0); +} diff --git a/dep/cvode-2.7.0/cvode/cvode_bandpre_impl.h b/dep/cvode-2.7.0/cvode/cvode_bandpre_impl.h new file mode 100644 index 00000000..09e56d3b --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_bandpre_impl.h @@ -0,0 +1,76 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2010/12/01 22:19:48 $ + * ----------------------------------------------------------------- + * Programmer(s): Michael Wittman, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the CVBANDPRE module. + * ----------------------------------------------------------------- + */ + +#ifndef _CVBANDPRE_IMPL_H +#define _CVBANDPRE_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include +#include + +/* + * ----------------------------------------------------------------- + * Type: CVBandPrecData + * ----------------------------------------------------------------- + */ + +typedef struct CVBandPrecDataRec { + + /* Data set by user in CVBandPrecInit */ + + long int N; + long int ml, mu; + + /* Data set by CVBandPrecSetup */ + + DlsMat savedJ; + DlsMat savedP; + long int *lpivots; + + /* Rhs calls */ + + long int nfeBP; + + /* Pointer to cvode_mem */ + + void *cvode_mem; + +} *CVBandPrecData; + +/* + * ----------------------------------------------------------------- + * CVBANDPRE error messages + * ----------------------------------------------------------------- + */ + +#define MSGBP_MEM_NULL "Integrator memory is NULL." +#define MSGBP_LMEM_NULL "Linear solver memory is NULL. One of the SPILS linear solvers must be attached." +#define MSGBP_MEM_FAIL "A memory request failed." +#define MSGBP_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGBP_PMEM_NULL "Band preconditioner memory is NULL. CVBandPrecInit must be called." +#define MSGBP_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner." + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/cvode_bbdpre.c b/dep/cvode-2.7.0/cvode/cvode_bbdpre.c new file mode 100644 index 00000000..30f6844f --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_bbdpre.c @@ -0,0 +1,550 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2010/12/01 22:21:04 $ + * ----------------------------------------------------------------- + * Programmer(s): Michael Wittman, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file contains implementations of routines for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with CVODE, a CVSPILS linear + * solver, and the parallel implementation of NVECTOR. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvode_impl.h" +#include "cvode_bbdpre_impl.h" +#include "cvode_spils_impl.h" + +#include +#include +#include + +#include + +#define MIN_INC_MULT RCONST(1000.0) + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* Prototypes of functions CVBBDPrecSetup and CVBBDPrecSolve */ + +static int CVBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bbd_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +static int CVBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bbd_data, N_Vector tmp); + +/* Prototype for CVBBDPrecFree */ +static void CVBBDPrecFree(CVodeMem cv_mem); + + +/* Prototype for difference quotient Jacobian calculation routine */ + +static int CVBBDDQJac(CVBBDPrecData pdata, realtype t, + N_Vector y, N_Vector gy, + N_Vector ytemp, N_Vector gtemp); + +/* Redability replacements */ + +#define uround (cv_mem->cv_uround) +#define vec_tmpl (cv_mem->cv_tempv) + +/* + * ----------------------------------------------------------------- + * User-Callable Functions: initialization, reinit and free + * ----------------------------------------------------------------- + */ + +int CVBBDPrecInit(void *cvode_mem, long int Nlocal, + long int mudq, long int mldq, + long int mukeep, long int mlkeep, + realtype dqrely, + CVLocalFn gloc, CVCommFn cfn) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + long int muk, mlk, storage_mu; + int flag; + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + /* Test if the NVECTOR package is compatible with the BLOCK BAND preconditioner */ + if(vec_tmpl->ops->nvgetarraypointer == NULL) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + /* Allocate data memory */ + pdata = NULL; + pdata = (CVBBDPrecData) malloc(sizeof *pdata); + if (pdata == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set pointers to gloc and cfn; load half-bandwidths */ + pdata->cvode_mem = cvode_mem; + pdata->gloc = gloc; + pdata->cfn = cfn; + pdata->mudq = MIN(Nlocal-1, MAX(0,mudq)); + pdata->mldq = MIN(Nlocal-1, MAX(0,mldq)); + muk = MIN(Nlocal-1, MAX(0,mukeep)); + mlk = MIN(Nlocal-1, MAX(0,mlkeep)); + pdata->mukeep = muk; + pdata->mlkeep = mlk; + + /* Allocate memory for saved Jacobian */ + pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk); + if (pdata->savedJ == NULL) { + free(pdata); pdata = NULL; + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Allocate memory for preconditioner matrix */ + storage_mu = MIN(Nlocal-1, muk + mlk); + pdata->savedP = NULL; + pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu); + if (pdata->savedP == NULL) { + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + /* Allocate memory for lpivots */ + pdata->lpivots = NULL; + pdata->lpivots = NewLintArray(Nlocal); + if (pdata->lpivots == NULL) { + DestroyMat(pdata->savedP); + DestroyMat(pdata->savedJ); + free(pdata); pdata = NULL; + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set pdata->dqrely based on input dqrely (0 implies default). */ + pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround); + + /* Store Nlocal to be used in CVBBDPrecSetup */ + pdata->n_local = Nlocal; + + /* Set work space sizes and initialize nge */ + pdata->rpwsize = Nlocal*(muk + 2*mlk + storage_mu + 2); + pdata->ipwsize = Nlocal; + pdata->nge = 0; + + /* Overwrite the P_data field in the SPILS memory */ + cvspils_mem->s_P_data = pdata; + + /* Attach the pfree function */ + cvspils_mem->s_pfree = CVBBDPrecFree; + + /* Attach preconditioner solve and setup functions */ + flag = CVSpilsSetPreconditioner(cvode_mem, CVBBDPrecSetup, CVBBDPrecSolve); + + return(flag); +} + + +int CVBBDPrecReInit(void *cvode_mem, + long int mudq, long int mldq, + realtype dqrely) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + long int Nlocal; + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if one of the SPILS linear solvers has been attached */ + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + /* Test if the preconditioner data is non-NULL */ + if (cvspils_mem->s_P_data == NULL) { + CVProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + /* Load half-bandwidths */ + Nlocal = pdata->n_local; + pdata->mudq = MIN(Nlocal-1, MAX(0,mudq)); + pdata->mldq = MIN(Nlocal-1, MAX(0,mldq)); + + /* Set pdata->dqrely based on input dqrely (0 implies default). */ + pdata->dqrely = (dqrely > ZERO) ? dqrely : RSqrt(uround); + + /* Re-initialize nge */ + pdata->nge = 0; + + return(CVSPILS_SUCCESS); +} + +int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwBBDP, long int *leniwBBDP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + CVProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + *lenrwBBDP = pdata->rpwsize; + *leniwBBDP = pdata->ipwsize; + + return(CVSPILS_SUCCESS); +} + +int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (cv_mem->cv_lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) { + CVProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL); + return(CVSPILS_PMEM_NULL); + } + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + *ngevalsBBDP = pdata->nge; + + return(CVSPILS_SUCCESS); +} + +/* Readability Replacements */ + +#define Nlocal (pdata->n_local) +#define mudq (pdata->mudq) +#define mldq (pdata->mldq) +#define mukeep (pdata->mukeep) +#define mlkeep (pdata->mlkeep) +#define dqrely (pdata->dqrely) +#define gloc (pdata->gloc) +#define cfn (pdata->cfn) +#define savedJ (pdata->savedJ) +#define savedP (pdata->savedP) +#define lpivots (pdata->lpivots) +#define nge (pdata->nge) + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecSetup + * ----------------------------------------------------------------- + * CVBBDPrecSetup generates and factors a banded block of the + * preconditioner matrix on each processor, via calls to the + * user-supplied gloc and cfn functions. It uses difference + * quotient approximations to the Jacobian elements. + * + * CVBBDPrecSetup calculates a new J,if necessary, then calculates + * P = I - gamma*J, and does an LU factorization of P. + * + * The parameters of CVBBDPrecSetup used here are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data from the + * previous CVBBDPrecon call can be reused + * (with the current value of gamma). + * A CVBBDPrecon call with jok == TRUE should only occur + * after a call with jok == FALSE. + * + * jcurPtr is a pointer to an output integer flag which is + * set by CVBBDPrecon as follows: + * *jcurPtr = TRUE if Jacobian data was recomputed. + * *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * bbd_data is a pointer to the preconditioner data set by + * CVBBDPrecInit + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for NVectors which are be used by CVBBDPrecSetup + * as temporary storage or work space. + * + * Return value: + * The value returned by this CVBBDPrecSetup function is the int + * 0 if successful, + * 1 for a recoverable error (step will be retried). + * ----------------------------------------------------------------- + */ + +static int CVBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *bbd_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + long int ier; + CVBBDPrecData pdata; + CVodeMem cv_mem; + int retval; + + pdata = (CVBBDPrecData) bbd_data; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + BandCopy(savedJ, savedP, mukeep, mlkeep); + + } else { + + /* Otherwise call CVBBDDQJac for new J value */ + *jcurPtr = TRUE; + SetToZero(savedJ); + + retval = CVBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3); + if (retval < 0) { + CVProcessError(cv_mem, -1, "CVBBDPRE", "CVBBDPrecSetup", MSGBBD_FUNC_FAILED); + return(-1); + } + if (retval > 0) { + return(1); + } + + BandCopy(savedJ, savedP, mukeep, mlkeep); + + } + + /* Scale and add I to get P = I - gamma*J */ + BandScale(-gamma, savedP); + AddIdentity(savedP); + + /* Do LU factorization of P in place */ + ier = BandGBTRF(savedP, lpivots); + + /* Return 0 if the LU was complete; otherwise return 1 */ + if (ier > 0) return(1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecSolve + * ----------------------------------------------------------------- + * CVBBDPrecSolve solves a linear system P z = r, with the + * band-block-diagonal preconditioner matrix P generated and + * factored by CVBBDPrecSetup. + * + * The parameters of CVBBDPrecSolve used here are as follows: + * + * r is the right-hand side vector of the linear system. + * + * bbd_data is a pointer to the preconditioner data set by + * CVBBDPrecInit. + * + * z is the output vector computed by CVBBDPrecSolve. + * + * The value returned by the CVBBDPrecSolve function is always 0, + * indicating success. + * ----------------------------------------------------------------- + */ + +static int CVBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *bbd_data, N_Vector tmp) +{ + CVBBDPrecData pdata; + realtype *zd; + + pdata = (CVBBDPrecData) bbd_data; + + /* Copy r to z, then do backsolve and return */ + N_VScale(ONE, r, z); + + zd = N_VGetArrayPointer(z); + + BandGBTRS(savedP, lpivots, zd); + + return(0); +} + + +static void CVBBDPrecFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + CVBBDPrecData pdata; + + if (cv_mem->cv_lmem == NULL) return; + cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem; + + if (cvspils_mem->s_P_data == NULL) return; + pdata = (CVBBDPrecData) cvspils_mem->s_P_data; + + DestroyMat(savedJ); + DestroyMat(savedP); + DestroyArray(lpivots); + + free(pdata); + pdata = NULL; +} + + +#define ewt (cv_mem->cv_ewt) +#define h (cv_mem->cv_h) +#define user_data (cv_mem->cv_user_data) + +/* + * ----------------------------------------------------------------- + * Function : CVBBDDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation + * to the local block of the Jacobian of g(t,y). It assumes that a + * band matrix of type DlsMat is stored columnwise, and that elements + * within each column are contiguous. All matrix elements are generated + * as difference quotients, by way of calls to the user routine gloc. + * By virtue of the band structure, the number of these calls is + * bandwidth + 1, where bandwidth = mldq + mudq + 1. + * But the band matrix kept has bandwidth = mlkeep + mukeep + 1. + * This routine also assumes that the local elements of a vector are + * stored contiguously. + * ----------------------------------------------------------------- + */ + +static int CVBBDDQJac(CVBBDPrecData pdata, realtype t, + N_Vector y, N_Vector gy, + N_Vector ytemp, N_Vector gtemp) +{ + CVodeMem cv_mem; + realtype gnorm, minInc, inc, inc_inv; + long int group, i, j, width, ngroups, i1, i2; + realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j; + int retval; + + cv_mem = (CVodeMem) pdata->cvode_mem; + + /* Load ytemp with y = predicted solution vector */ + N_VScale(ONE, y, ytemp); + + /* Call cfn and gloc to get base value of g(t,y) */ + if (cfn != NULL) { + retval = cfn(Nlocal, t, y, user_data); + if (retval != 0) return(retval); + } + + retval = gloc(Nlocal, t, ytemp, gy, user_data); + nge++; + if (retval != 0) return(retval); + + /* Obtain pointers to the data for various vectors */ + y_data = N_VGetArrayPointer(y); + gy_data = N_VGetArrayPointer(gy); + ewt_data = N_VGetArrayPointer(ewt); + ytemp_data = N_VGetArrayPointer(ytemp); + gtemp_data = N_VGetArrayPointer(gtemp); + + /* Set minimum increment based on uround and norm of g */ + gnorm = N_VWrmsNorm(gy, ewt); + minInc = (gnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * Nlocal * gnorm) : ONE; + + /* Set bandwidth and number of column groups for band differencing */ + width = mldq + mudq + 1; + ngroups = MIN(width, Nlocal); + + /* Loop over groups */ + for (group=1; group <= ngroups; group++) { + + /* Increment all y_j in group */ + for(j=group-1; j < Nlocal; j+=width) { + inc = MAX(dqrely*ABS(y_data[j]), minInc/ewt_data[j]); + ytemp_data[j] += inc; + } + + /* Evaluate g with incremented y */ + retval = gloc(Nlocal, t, ytemp, gtemp, user_data); + nge++; + if (retval != 0) return(retval); + + /* Restore ytemp, then form and load difference quotients */ + for (j=group-1; j < Nlocal; j+=width) { + ytemp_data[j] = y_data[j]; + col_j = BAND_COL(savedJ,j); + inc = MAX(dqrely*ABS(y_data[j]), minInc/ewt_data[j]); + inc_inv = ONE/inc; + i1 = MAX(0, j-mukeep); + i2 = MIN(j+mlkeep, Nlocal-1); + for (i=i1; i <= i2; i++) + BAND_COL_ELEM(col_j,i,j) = + inc_inv * (gtemp_data[i] - gy_data[i]); + } + } + + return(0); +} diff --git a/dep/cvode-2.7.0/cvode/cvode_bbdpre_impl.h b/dep/cvode-2.7.0/cvode/cvode_bbdpre_impl.h new file mode 100644 index 00000000..10bb8bce --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_bbdpre_impl.h @@ -0,0 +1,82 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:19:48 $ + * ----------------------------------------------------------------- + * Programmer(s): Michael Wittman, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the CVBBDPRE module. + * ----------------------------------------------------------------- + */ + +#ifndef _CVBBDPRE_IMPL_H +#define _CVBBDPRE_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Type: CVBBDPrecData + * ----------------------------------------------------------------- + */ + +typedef struct CVBBDPrecDataRec { + + /* passed by user to CVBBDPrecAlloc and used by PrecSetup/PrecSolve */ + + long int mudq, mldq, mukeep, mlkeep; + realtype dqrely; + CVLocalFn gloc; + CVCommFn cfn; + + /* set by CVBBDPrecSetup and used by CVBBDPrecSolve */ + + DlsMat savedJ; + DlsMat savedP; + long int *lpivots; + + /* set by CVBBDPrecAlloc and used by CVBBDPrecSetup */ + + long int n_local; + + /* available for optional output */ + + long int rpwsize; + long int ipwsize; + long int nge; + + /* pointer to cvode_mem */ + + void *cvode_mem; + +} *CVBBDPrecData; + +/* + * ----------------------------------------------------------------- + * CVBBDPRE error messages + * ----------------------------------------------------------------- + */ + +#define MSGBBD_MEM_NULL "Integrator memory is NULL." +#define MSGBBD_LMEM_NULL "Linear solver memory is NULL. One of the SPILS linear solvers must be attached." +#define MSGBBD_MEM_FAIL "A memory request failed." +#define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGBBD_PMEM_NULL "BBD peconditioner memory is NULL. CVBBDPrecInit must be called." +#define MSGBBD_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/cvode_dense.c b/dep/cvode-2.7.0/cvode/cvode_dense.c new file mode 100644 index 00000000..a2e9f3bb --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_dense.c @@ -0,0 +1,341 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.12 $ + * $Date: 2010/12/01 22:21:04 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the impleentation file for the CVDENSE linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvode_direct_impl.h" +#include "cvode_impl.h" + +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* CVDENSE linit, lsetup, lsolve, and lfree routines */ + +static int cvDenseInit(CVodeMem cv_mem); + +static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + +static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); + +static void cvDenseFree(CVodeMem cv_mem); + +/* Readability Replacements */ + +#define lmm (cv_mem->cv_lmm) +#define f (cv_mem->cv_f) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define jacDQ (cvdls_mem->d_jacDQ) +#define jac (cvdls_mem->d_djac) +#define M (cvdls_mem->d_M) +#define lpivots (cvdls_mem->d_lpivots) +#define savedJ (cvdls_mem->d_savedJ) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define J_data (cvdls_mem->d_J_data) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ----------------------------------------------------------------- + * CVDense + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the dense linear solver module. CVDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be cvDenseInit, cvDenseSetup, cvDenseSolve, and cvDenseFree, + * respectively. It allocates memory for a structure of type + * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem) to + * TRUE, and the d_jac field to the default cvDlsDenseDQJac. + * Finally, it allocates memory for M, savedJ, and lpivots. + * The return value is SUCCESS = 0, or LMEM_FAIL = -1. + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVDense will first + * test for compatible a compatible N_Vector internal + * representation by checking that N_VGetArrayPointer and + * N_VSetArrayPointer exist. + * ----------------------------------------------------------------- + */ + +int CVDense(void *cvode_mem, long int N) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDENSE", "CVDense", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the DENSE solver */ + if (vec_tmpl->ops->nvgetarraypointer == NULL || + vec_tmpl->ops->nvsetarraypointer == NULL) { + CVProcessError(cv_mem, CVDLS_ILL_INPUT, "CVDENSE", "CVDense", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree !=NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvDenseInit; + lsetup = cvDenseSetup; + lsolve = cvDenseSolve; + lfree = cvDenseFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_DENSE; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + jac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + + setupNonNull = TRUE; + + /* Set problem dimension */ + n = N; + + /* Allocate memory for M, savedJ, and pivot array */ + + M = NULL; + M = NewDenseMat(N, N); + if (M == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + savedJ = NULL; + savedJ = NewDenseMat(N, N); + if (savedJ == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + lpivots = NULL; + lpivots = NewLintArray(N); + if (lpivots == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyMat(savedJ); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * cvDenseInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the dense + * linear solver. + * ----------------------------------------------------------------- + */ + +static int cvDenseInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + jac = cvDlsDenseDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvDenseSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the dense linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix + * M = I - gamma*J, updates counters, and calls the dense LU + * factorization routine. + * ----------------------------------------------------------------- + */ + +static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + long int ier; + CVDlsMem cvdls_mem; + int retval; + + cvdls_mem = (CVDlsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + DenseCopy(savedJ, M); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = jac(n, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3); + if (retval < 0) { + CVProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVDENSE", "cvDenseSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + DenseCopy(M, savedJ); + + } + + /* Scale and add I to get M = I - gamma*J */ + DenseScale(-gamma, M); + AddIdentity(M); + + /* Do LU factorization of M */ + ier = DenseGETRF(M, lpivots); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = ier; + if (ier > 0) return(1); + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvDenseSolve + * ----------------------------------------------------------------- + * This routine handles the solve operation for the dense linear solver + * by calling the dense backsolve routine. The returned value is 0. + * ----------------------------------------------------------------- + */ + +static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur) +{ + CVDlsMem cvdls_mem; + realtype *bd; + + cvdls_mem = (CVDlsMem) lmem; + + bd = N_VGetArrayPointer(b); + + DenseGETRS(M, lpivots, bd); + + /* If CV_BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + N_VScale(TWO/(ONE + gamrat), b, b); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * cvDenseFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the dense linear solver. + * ----------------------------------------------------------------- + */ + +static void cvDenseFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyMat(savedJ); + DestroyArray(lpivots); + free(cvdls_mem); + cv_mem->cv_lmem = NULL; +} + diff --git a/dep/cvode-2.7.0/cvode/cvode_diag.c b/dep/cvode-2.7.0/cvode/cvode_diag.c new file mode 100644 index 00000000..b7cfba2a --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_diag.c @@ -0,0 +1,437 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:21:04 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVDIAG linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvode_diag_impl.h" +#include "cvode_impl.h" + +/* Other Constants */ + +#define FRACT RCONST(0.1) +#define ONE RCONST(1.0) + +/* CVDIAG linit, lsetup, lsolve, and lfree routines */ + +static int CVDiagInit(CVodeMem cv_mem); + +static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); + +static void CVDiagFree(CVodeMem cv_mem); + +/* Readability Replacements */ + +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) +#define f (cv_mem->cv_f) +#define uround (cv_mem->cv_uround) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define rl1 (cv_mem->cv_rl1) +#define gamma (cv_mem->cv_gamma) +#define ewt (cv_mem->cv_ewt) +#define nfe (cv_mem->cv_nfe) +#define zn (cv_mem->cv_zn) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define gammasv (cvdiag_mem->di_gammasv) +#define M (cvdiag_mem->di_M) +#define bit (cvdiag_mem->di_bit) +#define bitcomp (cvdiag_mem->di_bitcomp) +#define nfeDI (cvdiag_mem->di_nfeDI) +#define last_flag (cvdiag_mem->di_last_flag) + +/* + * ----------------------------------------------------------------- + * CVDiag + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the diagonal linear solver module. CVDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVDiagInit, CVDiagSetup, CVDiagSolve, and CVDiagFree, + * respectively. It allocates memory for a structure of type + * CVDiagMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem) to + * TRUE. Finally, it allocates memory for M, bit, and bitcomp. + * The CVDiag return value is SUCCESS = 0, LMEM_FAIL = -1, or + * LIN_ILL_INPUT=-2. + * ----------------------------------------------------------------- + */ + +int CVDiag(void *cvode_mem) +{ + CVodeMem cv_mem; + CVDiagMem cvdiag_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiag", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VCompare and N_VInvTest are present */ + if(vec_tmpl->ops->nvcompare == NULL || + vec_tmpl->ops->nvinvtest == NULL) { + CVProcessError(cv_mem, CVDIAG_ILL_INPUT, "CVDIAG", "CVDiag", MSGDG_BAD_NVECTOR); + return(CVDIAG_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVDiagInit; + lsetup = CVDiagSetup; + lsolve = CVDiagSolve; + lfree = CVDiagFree; + + /* Get memory for CVDiagMemRec */ + cvdiag_mem = NULL; + cvdiag_mem = (CVDiagMem) malloc(sizeof(CVDiagMemRec)); + if (cvdiag_mem == NULL) { + CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + return(CVDIAG_MEM_FAIL); + } + + last_flag = CVDIAG_SUCCESS; + + /* Set flag setupNonNull = TRUE */ + setupNonNull = TRUE; + + /* Allocate memory for M, bit, and bitcomp */ + + M = N_VClone(vec_tmpl); + if (M == NULL) { + CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + free(cvdiag_mem); cvdiag_mem = NULL; + return(CVDIAG_MEM_FAIL); + } + + bit = N_VClone(vec_tmpl); + if (bit == NULL) { + CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + N_VDestroy(M); + free(cvdiag_mem); cvdiag_mem = NULL; + return(CVDIAG_MEM_FAIL); + } + + bitcomp = N_VClone(vec_tmpl); + if (bitcomp == NULL) { + CVProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL); + N_VDestroy(M); + N_VDestroy(bit); + free(cvdiag_mem); cvdiag_mem = NULL; + return(CVDIAG_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdiag_mem; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetWorkSpace + * ----------------------------------------------------------------- + */ + +int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS) +{ + CVodeMem cv_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetWorkSpace", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + *lenrwLS = 3*lrw1; + *leniwLS = 3*liw1; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetNumRhsEvals + * ----------------------------------------------------------------- + */ + +int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS) +{ + CVodeMem cv_mem; + CVDiagMem cvdiag_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetNumRhsEvals", MSGDG_LMEM_NULL); + return(CVDIAG_LMEM_NULL); + } + cvdiag_mem = (CVDiagMem) lmem; + + *nfevalsLS = nfeDI; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetLastFlag + * ----------------------------------------------------------------- + */ + +int CVDiagGetLastFlag(void *cvode_mem, long int *flag) +{ + CVodeMem cv_mem; + CVDiagMem cvdiag_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDIAG_MEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_CVMEM_NULL); + return(CVDIAG_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDIAG_LMEM_NULL, "CVDIAG", "CVDiagGetLastFlag", MSGDG_LMEM_NULL); + return(CVDIAG_LMEM_NULL); + } + cvdiag_mem = (CVDiagMem) lmem; + + *flag = last_flag; + + return(CVDIAG_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVDiagGetReturnFlagName + * ----------------------------------------------------------------- + */ + +char *CVDiagGetReturnFlagName(long int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case CVDIAG_SUCCESS: + sprintf(name,"CVDIAG_SUCCESS"); + break; + case CVDIAG_MEM_NULL: + sprintf(name,"CVDIAG_MEM_NULL"); + break; + case CVDIAG_LMEM_NULL: + sprintf(name,"CVDIAG_LMEM_NULL"); + break; + case CVDIAG_ILL_INPUT: + sprintf(name,"CVDIAG_ILL_INPUT"); + break; + case CVDIAG_MEM_FAIL: + sprintf(name,"CVDIAG_MEM_FAIL"); + break; + case CVDIAG_INV_FAIL: + sprintf(name,"CVDIAG_INV_FAIL"); + break; + case CVDIAG_RHSFUNC_UNRECVR: + sprintf(name,"CVDIAG_RHSFUNC_UNRECVR"); + break; + case CVDIAG_RHSFUNC_RECVR: + sprintf(name,"CVDIAG_RHSFUNC_RECVR"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * ----------------------------------------------------------------- + * CVDiagInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the diagonal + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVDiagInit(CVodeMem cv_mem) +{ + CVDiagMem cvdiag_mem; + + cvdiag_mem = (CVDiagMem) lmem; + + nfeDI = 0; + + last_flag = CVDIAG_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVDiagSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the diagonal linear + * solver. It constructs a diagonal approximation to the Newton matrix + * M = I - gamma*J, updates counters, and inverts M. + * ----------------------------------------------------------------- + */ + +static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + realtype r; + N_Vector ftemp, y; + booleantype invOK; + CVDiagMem cvdiag_mem; + int retval; + + cvdiag_mem = (CVDiagMem) lmem; + + /* Rename work vectors for use as temporary values of y and f */ + ftemp = vtemp1; + y = vtemp2; + + /* Form y with perturbation = FRACT*(func. iter. correction) */ + r = FRACT * rl1; + N_VLinearSum(h, fpred, -ONE, zn[1], ftemp); + N_VLinearSum(r, ftemp, ONE, ypred, y); + + /* Evaluate f at perturbed y */ + retval = f(tn, y, M, cv_mem->cv_user_data); + nfeDI++; + if (retval < 0) { + CVProcessError(cv_mem, CVDIAG_RHSFUNC_UNRECVR, "CVDIAG", "CVDiagSetup", MSGDG_RHSFUNC_FAILED); + last_flag = CVDIAG_RHSFUNC_UNRECVR; + return(-1); + } + if (retval > 0) { + last_flag = CVDIAG_RHSFUNC_RECVR; + return(1); + } + + /* Construct M = I - gamma*J with J = diag(deltaf_i/deltay_i) */ + N_VLinearSum(ONE, M, -ONE, fpred, M); + N_VLinearSum(FRACT, ftemp, -h, M, M); + N_VProd(ftemp, ewt, y); + /* Protect against deltay_i being at roundoff level */ + N_VCompare(uround, y, bit); + N_VAddConst(bit, -ONE, bitcomp); + N_VProd(ftemp, bit, y); + N_VLinearSum(FRACT, y, -ONE, bitcomp, y); + N_VDiv(M, y, M); + N_VProd(M, bit, M); + N_VLinearSum(ONE, M, -ONE, bitcomp, M); + + /* Invert M with test for zero components */ + invOK = N_VInvTest(M, M); + if (!invOK) { + last_flag = CVDIAG_INV_FAIL; + return(1); + } + + /* Set jcur = TRUE, save gamma in gammasv, and return */ + *jcurPtr = TRUE; + gammasv = gamma; + last_flag = CVDIAG_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVDiagSolve + * ----------------------------------------------------------------- + * This routine performs the solve operation for the diagonal linear + * solver. If necessary it first updates gamma in M = I - gamma*J. + * ----------------------------------------------------------------- + */ + +static int CVDiagSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur) +{ + booleantype invOK; + realtype r; + CVDiagMem cvdiag_mem; + + cvdiag_mem = (CVDiagMem) lmem; + + /* If gamma has changed, update factor in M, and save gamma value */ + + if (gammasv != gamma) { + r = gamma / gammasv; + N_VInv(M, M); + N_VAddConst(M, -ONE, M); + N_VScale(r, M, M); + N_VAddConst(M, ONE, M); + invOK = N_VInvTest(M, M); + if (!invOK) { + last_flag = CVDIAG_INV_FAIL; + return (1); + } + gammasv = gamma; + } + + /* Apply M-inverse to b */ + N_VProd(b, M, b); + + last_flag = CVDIAG_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVDiagFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the diagonal linear solver. + * ----------------------------------------------------------------- + */ + +static void CVDiagFree(CVodeMem cv_mem) +{ + CVDiagMem cvdiag_mem; + + cvdiag_mem = (CVDiagMem) lmem; + + N_VDestroy(M); + N_VDestroy(bit); + N_VDestroy(bitcomp); + free(cvdiag_mem); + cv_mem->cv_lmem = NULL; +} diff --git a/dep/cvode-2.7.0/cvode/cvode_diag_impl.h b/dep/cvode-2.7.0/cvode/cvode_diag_impl.h new file mode 100644 index 00000000..9ccf5adb --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_diag_impl.h @@ -0,0 +1,66 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2010/12/01 22:19:48 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the diagonal linear solver, CVDIAG. + * ----------------------------------------------------------------- + */ + +#ifndef _CVDIAG_IMPL_H +#define _CVDIAG_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: CVDiagMemRec, CVDiagMem + * ----------------------------------------------------------------- + * The type CVDiagMem is pointer to a CVDiagMemRec. + * This structure contains CVDiag solver-specific data. + * ----------------------------------------------------------------- + */ + +typedef struct { + + realtype di_gammasv; /* gammasv = gamma at the last call to setup */ + /* or solve */ + + N_Vector di_M; /* M = (I - gamma J)^{-1} , gamma = h / l1 */ + + N_Vector di_bit; /* temporary storage vector */ + + N_Vector di_bitcomp; /* temporary storage vector */ + + long int di_nfeDI; /* no. of calls to f due to difference + quotient diagonal Jacobian approximation */ + + long int di_last_flag; /* last error return flag */ + +} CVDiagMemRec, *CVDiagMem; + +/* Error Messages */ + +#define MSGDG_CVMEM_NULL "Integrator memory is NULL." +#define MSGDG_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGDG_MEM_FAIL "A memory request failed." +#define MSGDG_LMEM_NULL "CVDIAG memory is NULL." +#define MSGDG_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/cvode_direct.c b/dep/cvode-2.7.0/cvode/cvode_direct.c new file mode 100644 index 00000000..0e2d6e0c --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_direct.c @@ -0,0 +1,463 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2010/12/01 22:21:04 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVDLS linear solvers + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * IMPORTED HEADER FILES + * ================================================================= + */ + +#include +#include + +#include "cvode_impl.h" +#include "cvode_direct_impl.h" +#include + +/* + * ================================================================= + * FUNCTION SPECIFIC CONSTANTS + * ================================================================= + */ + +/* Constant for DQ Jacobian approximation */ +#define MIN_INC_MULT RCONST(1000.0) + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ================================================================= + * READIBILITY REPLACEMENTS + * ================================================================= + */ + +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define uround (cv_mem->cv_uround) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) + +#define lmem (cv_mem->cv_lmem) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define ml (cvdls_mem->d_ml) +#define mu (cvdls_mem->d_mu) +#define smu (cvdls_mem->d_smu) +#define jacDQ (cvdls_mem->d_jacDQ) +#define djac (cvdls_mem->d_djac) +#define bjac (cvdls_mem->d_bjac) +#define M (cvdls_mem->d_M) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ================================================================= + * EXPORTED FUNCTIONS + * ================================================================= + */ + +/* + * CVDlsSetDenseJacFn specifies the dense Jacobian function. + */ +int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + if (jac != NULL) { + jacDQ = FALSE; + djac = jac; + } else { + jacDQ = TRUE; + } + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsSetBandJacFn specifies the band Jacobian function. + */ +int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + if (jac != NULL) { + jacDQ = FALSE; + bjac = jac; + } else { + jacDQ = TRUE; + } + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetWorkSpace returns the length of workspace allocated for the + * CVDLS linear solver. + */ +int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetWorkSpace", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetWorkSpace", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + if (mtype == SUNDIALS_DENSE) { + *lenrwLS = 2*n*n; + *leniwLS = n; + } else if (mtype == SUNDIALS_BAND) { + *lenrwLS = n*(smu + mu + 2*ml + 2); + *leniwLS = n; + } + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetNumJacEvals returns the number of Jacobian evaluations. + */ +int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetNumJacEvals", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetNumJacEvals", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + *njevals = nje; + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetNumRhsEvals returns the number of calls to the ODE function + * needed for the DQ Jacobian approximation. + */ +int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetNumRhsEvals", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetNumRhsEvals", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + *nfevalsLS = nfeDQ; + + return(CVDLS_SUCCESS); +} + +/* + * CVDlsGetReturnFlagName returns the name associated with a CVDLS + * return value. + */ +char *CVDlsGetReturnFlagName(long int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case CVDLS_SUCCESS: + sprintf(name,"CVDLS_SUCCESS"); + break; + case CVDLS_MEM_NULL: + sprintf(name,"CVDLS_MEM_NULL"); + break; + case CVDLS_LMEM_NULL: + sprintf(name,"CVDLS_LMEM_NULL"); + break; + case CVDLS_ILL_INPUT: + sprintf(name,"CVDLS_ILL_INPUT"); + break; + case CVDLS_MEM_FAIL: + sprintf(name,"CVDLS_MEM_FAIL"); + break; + case CVDLS_JACFUNC_UNRECVR: + sprintf(name,"CVDLS_JACFUNC_UNRECVR"); + break; + case CVDLS_JACFUNC_RECVR: + sprintf(name,"CVDLS_JACFUNC_RECVR"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * CVDlsGetLastFlag returns the last flag set in a CVDLS function. + */ +int CVDlsGetLastFlag(void *cvode_mem, long int *flag) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetLastFlag", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetLastFlag", MSGD_LMEM_NULL); + return(CVDLS_LMEM_NULL); + } + cvdls_mem = (CVDlsMem) lmem; + + *flag = last_flag; + + return(CVDLS_SUCCESS); +} + +/* + * ================================================================= + * DQ JACOBIAN APPROXIMATIONS + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * cvDlsDenseDQJac + * ----------------------------------------------------------------- + * This routine generates a dense difference quotient approximation to + * the Jacobian of f(t,y). It assumes that a dense matrix of type + * DlsMat is stored column-wise, and that elements within each column + * are contiguous. The address of the jth column of J is obtained via + * the macro DENSE_COL and this pointer is associated with an N_Vector + * using the N_VGetArrayPointer/N_VSetArrayPointer functions. + * Finally, the actual computation of the jth column of the Jacobian is + * done with a call to N_VLinearSum. + * ----------------------------------------------------------------- + */ + +int cvDlsDenseDQJac(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + realtype fnorm, minInc, inc, inc_inv, yjsaved, srur; + realtype *tmp2_data, *y_data, *ewt_data; + N_Vector ftemp, jthCol; + long int j; + int retval = 0; + + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* data points to cvode_mem */ + cv_mem = (CVodeMem) data; + cvdls_mem = (CVDlsMem) lmem; + + /* Save pointer to the array in tmp2 */ + tmp2_data = N_VGetArrayPointer(tmp2); + + /* Rename work vectors for readibility */ + ftemp = tmp1; + jthCol = tmp2; + + /* Obtain pointers to the data for ewt, y */ + ewt_data = N_VGetArrayPointer(ewt); + y_data = N_VGetArrayPointer(y); + + /* Set minimum increment based on uround and norm of f */ + srur = RSqrt(uround); + fnorm = N_VWrmsNorm(fy, ewt); + minInc = (fnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE; + + for (j = 0; j < N; j++) { + + /* Generate the jth col of J(tn,y) */ + + N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol); + + yjsaved = y_data[j]; + inc = MAX(srur*ABS(yjsaved), minInc/ewt_data[j]); + y_data[j] += inc; + + retval = f(t, y, ftemp, user_data); + nfeDQ++; + if (retval != 0) break; + + y_data[j] = yjsaved; + + inc_inv = ONE/inc; + N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol); + + DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol); + } + + /* Restore original array pointer in tmp2 */ + N_VSetArrayPointer(tmp2_data, tmp2); + + return(retval); +} + +/* + * ----------------------------------------------------------------- + * cvDlsBandDQJac + * ----------------------------------------------------------------- + * This routine generates a banded difference quotient approximation to + * the Jacobian of f(t,y). It assumes that a band matrix of type + * DlsMat is stored column-wise, and that elements within each column + * are contiguous. This makes it possible to get the address of a column + * of J via the macro BAND_COL and to write a simple for loop to set + * each of the elements of a column in succession. + * ----------------------------------------------------------------- + */ + +int cvDlsBandDQJac(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + N_Vector ftemp, ytemp; + realtype fnorm, minInc, inc, inc_inv, srur; + realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data; + long int group, i, j, width, ngroups, i1, i2; + int retval = 0; + + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* data points to cvode_mem */ + cv_mem = (CVodeMem) data; + cvdls_mem = (CVDlsMem) lmem; + + /* Rename work vectors for use as temporary values of y and f */ + ftemp = tmp1; + ytemp = tmp2; + + /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp */ + ewt_data = N_VGetArrayPointer(ewt); + fy_data = N_VGetArrayPointer(fy); + ftemp_data = N_VGetArrayPointer(ftemp); + y_data = N_VGetArrayPointer(y); + ytemp_data = N_VGetArrayPointer(ytemp); + + /* Load ytemp with y = predicted y vector */ + N_VScale(ONE, y, ytemp); + + /* Set minimum increment based on uround and norm of f */ + srur = RSqrt(uround); + fnorm = N_VWrmsNorm(fy, ewt); + minInc = (fnorm != ZERO) ? + (MIN_INC_MULT * ABS(h) * uround * N * fnorm) : ONE; + + /* Set bandwidth and number of column groups for band differencing */ + width = mlower + mupper + 1; + ngroups = MIN(width, N); + + /* Loop over column groups. */ + for (group=1; group <= ngroups; group++) { + + /* Increment all y_j in group */ + for(j=group-1; j < N; j+=width) { + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + ytemp_data[j] += inc; + } + + /* Evaluate f with incremented y */ + + retval = f(tn, ytemp, ftemp, user_data); + nfeDQ++; + if (retval != 0) break; + + /* Restore ytemp, then form and load difference quotients */ + for (j=group-1; j < N; j+=width) { + ytemp_data[j] = y_data[j]; + col_j = BAND_COL(Jac,j); + inc = MAX(srur*ABS(y_data[j]), minInc/ewt_data[j]); + inc_inv = ONE/inc; + i1 = MAX(0, j-mupper); + i2 = MIN(j+mlower, N-1); + for (i=i1; i <= i2; i++) + BAND_COL_ELEM(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]); + } + } + + return(retval); +} + diff --git a/dep/cvode-2.7.0/cvode/cvode_direct_impl.h b/dep/cvode-2.7.0/cvode/cvode_direct_impl.h new file mode 100644 index 00000000..75ee016e --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_direct_impl.h @@ -0,0 +1,111 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:19:48 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common implementation header file for the CVDLS linear solvers. + * ----------------------------------------------------------------- + */ + +#ifndef _CVDLS_IMPL_H +#define _CVDLS_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * CVDLS solver constants + * ----------------------------------------------------------------- + * CVD_MSBJ maximum number of steps between Jacobian evaluations + * CVD_DGMAX maximum change in gamma between Jacobian evaluations + * ----------------------------------------------------------------- + */ + +#define CVD_MSBJ 50 +#define CVD_DGMAX RCONST(0.2) + +/* + * ----------------------------------------------------------------- + * Types : CVDlsMemRec, CVDlsMem + * ----------------------------------------------------------------- + * CVDlsMem is pointer to a CVDlsMemRec structure. + * ----------------------------------------------------------------- + */ + +typedef struct CVDlsMemRec { + + int d_type; /* SUNDIALS_DENSE or SUNDIALS_BAND */ + + long int d_n; /* problem dimension */ + + long int d_ml; /* lower bandwidth of Jacobian */ + long int d_mu; /* upper bandwidth of Jacobian */ + long int d_smu; /* upper bandwith of M = MIN(N-1,d_mu+d_ml) */ + + booleantype d_jacDQ; /* TRUE if using internal DQ Jacobian approx. */ + CVDlsDenseJacFn d_djac; /* dense Jacobian routine to be called */ + CVDlsBandJacFn d_bjac; /* band Jacobian routine to be called */ + void *d_J_data; /* user data is passed to djac or bjac */ + + DlsMat d_M; /* M = I - gamma * df/dy */ + DlsMat d_savedJ; /* savedJ = old Jacobian */ + + int *d_pivots; /* pivots = int pivot array for PM = LU */ + long int *d_lpivots; /* lpivots = long int pivot array for PM = LU */ + + long int d_nstlj; /* nstlj = nst at last Jacobian eval. */ + + long int d_nje; /* nje = no. of calls to jac */ + + long int d_nfeDQ; /* no. of calls to f due to DQ Jacobian approx. */ + + long int d_last_flag; /* last error return flag */ + +} *CVDlsMem; + +/* + * ----------------------------------------------------------------- + * Prototypes of internal functions + * ----------------------------------------------------------------- + */ + +int cvDlsDenseDQJac(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +int cvDlsBandDQJac(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + + +/* + * ----------------------------------------------------------------- + * Error Messages + * ----------------------------------------------------------------- + */ + +#define MSGD_CVMEM_NULL "Integrator memory is NULL." +#define MSGD_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGD_BAD_SIZES "Illegal bandwidth parameter(s). Must have 0 <= ml, mu <= N-1." +#define MSGD_MEM_FAIL "A memory request failed." +#define MSGD_LMEM_NULL "Linear solver memory is NULL." +#define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/cvode_impl.h b/dep/cvode-2.7.0/cvode/cvode_impl.h new file mode 100644 index 00000000..5c4010fd --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_impl.h @@ -0,0 +1,515 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.13 $ + * $Date: 2007/11/26 16:19:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban + * and Dan Shumaker @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Implementation header file for the main CVODE integrator. + * ----------------------------------------------------------------- + */ + +#ifndef _CVODE_IMPL_H +#define _CVODE_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * M A I N I N T E G R A T O R M E M O R Y B L O C K + * ================================================================= + */ + +/* Basic CVODE constants */ + +#define ADAMS_Q_MAX 12 /* max value of q for lmm == ADAMS */ +#define BDF_Q_MAX 5 /* max value of q for lmm == BDF */ +#define Q_MAX ADAMS_Q_MAX /* max value of q for either lmm */ +#define L_MAX (Q_MAX+1) /* max value of L for either lmm */ +#define NUM_TESTS 5 /* number of error test quantities */ + +#define HMIN_DEFAULT RCONST(0.0) /* hmin default value */ +#define HMAX_INV_DEFAULT RCONST(0.0) /* hmax_inv default value */ +#define MXHNIL_DEFAULT 10 /* mxhnil default value */ +#define MXSTEP_DEFAULT 500 /* mxstep default value */ + +/* + * ----------------------------------------------------------------- + * Types : struct CVodeMemRec, CVodeMem + * ----------------------------------------------------------------- + * The type CVodeMem is type pointer to struct CVodeMemRec. + * This structure contains fields to keep track of problem state. + * ----------------------------------------------------------------- + */ + +typedef struct CVodeMemRec { + + realtype cv_uround; /* machine unit roundoff */ + + /*-------------------------- + Problem Specification Data + --------------------------*/ + + CVRhsFn cv_f; /* y' = f(t,y(t)) */ + void *cv_user_data; /* user pointer passed to f */ + int cv_lmm; /* lmm = CV_ADAMS or CV_BDF */ + int cv_iter; /* iter = CV_FUNCTIONAL or CV_NEWTON */ + int cv_itol; /* itol = CV_SS, CV_SV, CV_WF, CV_NN */ + + realtype cv_reltol; /* relative tolerance */ + realtype cv_Sabstol; /* scalar absolute tolerance */ + N_Vector cv_Vabstol; /* vector absolute tolerance */ + booleantype cv_user_efun; /* TRUE if user sets efun */ + CVEwtFn cv_efun; /* function to set ewt */ + void *cv_e_data; /* user pointer passed to efun */ + + /*----------------------- + Nordsieck History Array + -----------------------*/ + + N_Vector cv_zn[L_MAX]; /* Nordsieck array, of size N x (q+1). + zn[j] is a vector of length N (j=0,...,q) + zn[j] = [1/factorial(j)] * h^j * (jth + derivative of the interpolating polynomial */ + + /*-------------------------- + other vectors of length N + -------------------------*/ + + N_Vector cv_ewt; /* error weight vector */ + N_Vector cv_y; /* y is used as temporary storage by the solver + The memory is provided by the user to CVode + where the vector is named yout. */ + N_Vector cv_acor; /* In the context of the solution of the nonlinear + equation, acor = y_n(m) - y_n(0). On return, + this vector is scaled to give the est. local err. */ + N_Vector cv_tempv; /* temporary storage vector */ + N_Vector cv_ftemp; /* temporary storage vector */ + + /*----------------- + Tstop information + -----------------*/ + + booleantype cv_tstopset; + realtype cv_tstop; + + /*--------- + Step Data + ---------*/ + + int cv_q; /* current order */ + int cv_qprime; /* order to be used on the next step + = q-1, q, or q+1 */ + int cv_next_q; /* order to be used on the next step */ + int cv_qwait; /* number of internal steps to wait before + considering a change in q */ + int cv_L; /* L = q + 1 */ + + realtype cv_hin; /* initial step size */ + realtype cv_h; /* current step size */ + realtype cv_hprime; /* step size to be used on the next step */ + realtype cv_next_h; /* step size to be used on the next step */ + realtype cv_eta; /* eta = hprime / h */ + realtype cv_hscale; /* value of h used in zn */ + realtype cv_tn; /* current internal value of t */ + realtype cv_tretlast; /* value of tret last returned by CVode */ + + realtype cv_tau[L_MAX+1]; /* array of previous q+1 successful step + sizes indexed from 1 to q+1 */ + realtype cv_tq[NUM_TESTS+1]; /* array of test quantities indexed from + 1 to NUM_TESTS(=5) */ + realtype cv_l[L_MAX]; /* coefficients of l(x) (degree q poly) */ + + realtype cv_rl1; /* the scalar 1/l[1] */ + realtype cv_gamma; /* gamma = h * rl1 */ + realtype cv_gammap; /* gamma at the last setup call */ + realtype cv_gamrat; /* gamma / gammap */ + + realtype cv_crate; /* estimated corrector convergence rate */ + realtype cv_acnrm; /* | acor | wrms */ + realtype cv_nlscoef; /* coeficient in nonlinear convergence test */ + int cv_mnewt; /* Newton iteration counter */ + + /*------ + Limits + ------*/ + + int cv_qmax; /* q <= qmax */ + long int cv_mxstep; /* maximum number of internal steps for one user call */ + int cv_maxcor; /* maximum number of corrector iterations for the + solution of the nonlinear equation */ + int cv_mxhnil; /* maximum number of warning messages issued to the + user that t + h == t for the next internal step */ + int cv_maxnef; /* maximum number of error test failures */ + int cv_maxncf; /* maximum number of nonlinear convergence failures */ + + realtype cv_hmin; /* |h| >= hmin */ + realtype cv_hmax_inv; /* |h| <= 1/hmax_inv */ + realtype cv_etamax; /* eta <= etamax */ + + /*-------- + Counters + --------*/ + + long int cv_nst; /* number of internal steps taken */ + long int cv_nfe; /* number of f calls */ + long int cv_ncfn; /* number of corrector convergence failures */ + long int cv_netf; /* number of error test failures */ + long int cv_nni; /* number of Newton iterations performed */ + long int cv_nsetups; /* number of setup calls */ + int cv_nhnil; /* number of messages issued to the user that + t + h == t for the next iternal step */ + + realtype cv_etaqm1; /* ratio of new to old h for order q-1 */ + realtype cv_etaq; /* ratio of new to old h for order q */ + realtype cv_etaqp1; /* ratio of new to old h for order q+1 */ + + /*---------------------------- + Space requirements for CVODE + ----------------------------*/ + + long int cv_lrw1; /* no. of realtype words in 1 N_Vector */ + long int cv_liw1; /* no. of integer words in 1 N_Vector */ + long int cv_lrw; /* no. of realtype words in CVODE work vectors */ + long int cv_liw; /* no. of integer words in CVODE work vectors */ + + /*------------------ + Linear Solver Data + ------------------*/ + + /* Linear Solver functions to be called */ + + int (*cv_linit)(struct CVodeMemRec *cv_mem); + + int (*cv_lsetup)(struct CVodeMemRec *cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + + int (*cv_lsolve)(struct CVodeMemRec *cv_mem, N_Vector b, N_Vector weight, + N_Vector ycur, N_Vector fcur); + + void (*cv_lfree)(struct CVodeMemRec *cv_mem); + + /* Linear Solver specific memory */ + + void *cv_lmem; + + /*------------ + Saved Values + ------------*/ + + int cv_qu; /* last successful q value used */ + long int cv_nstlp; /* step number of last setup call */ + realtype cv_h0u; /* actual initial stepsize */ + realtype cv_hu; /* last successful h value used */ + realtype cv_saved_tq5; /* saved value of tq[5] */ + booleantype cv_jcur; /* is Jacobian info. for lin. solver current? */ + realtype cv_tolsf; /* tolerance scale factor */ + int cv_qmax_alloc; /* value of qmax used when allocating memory */ + int cv_indx_acor; /* index of the zn vector with saved acor */ + booleantype cv_setupNonNull; /* does setup do anything? */ + + booleantype cv_VabstolMallocDone; + booleantype cv_MallocDone; + + /*------------------------------------------- + Error handler function and error ouput file + -------------------------------------------*/ + + CVErrHandlerFn cv_ehfun; /* error messages are handled by ehfun */ + void *cv_eh_data; /* data pointer passed to ehfun */ + FILE *cv_errfp; /* CVODE error messages are sent to errfp */ + + /*------------------------- + Stability Limit Detection + -------------------------*/ + + booleantype cv_sldeton; /* is Stability Limit Detection on? */ + realtype cv_ssdat[6][4]; /* scaled data array for STALD */ + int cv_nscon; /* counter for STALD method */ + long int cv_nor; /* counter for number of order reductions */ + + /*---------------- + Rootfinding Data + ----------------*/ + + CVRootFn cv_gfun; /* function g for roots sought */ + int cv_nrtfn; /* number of components of g */ + int *cv_iroots; /* array for root information */ + int *cv_rootdir; /* array specifying direction of zero-crossing */ + realtype cv_tlo; /* nearest endpoint of interval in root search */ + realtype cv_thi; /* farthest endpoint of interval in root search */ + realtype cv_trout; /* t value returned by rootfinding routine */ + realtype *cv_glo; /* saved array of g values at t = tlo */ + realtype *cv_ghi; /* saved array of g values at t = thi */ + realtype *cv_grout; /* array of g values at t = trout */ + realtype cv_toutc; /* copy of tout (if NORMAL mode) */ + realtype cv_ttol; /* tolerance on root location */ + int cv_taskc; /* copy of parameter itask */ + int cv_irfnd; /* flag showing whether last step had a root */ + long int cv_nge; /* counter for g evaluations */ + booleantype *cv_gactive; /* array with active/inactive event functions */ + int cv_mxgnull; /* number of warning messages about possible g==0 */ + + +} *CVodeMem; + +/* + * ================================================================= + * I N T E R F A C E T O L I N E A R S O L V E R S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Communication between CVODE and a CVODE Linear Solver + * ----------------------------------------------------------------- + * convfail (input to cv_lsetup) + * + * CV_NO_FAILURES : Either this is the first cv_setup call for this + * step, or the local error test failed on the + * previous attempt at this step (but the Newton + * iteration converged). + * + * CV_FAIL_BAD_J : This value is passed to cv_lsetup if + * + * (a) The previous Newton corrector iteration + * did not converge and the linear solver's + * setup routine indicated that its Jacobian- + * related data is not current + * or + * (b) During the previous Newton corrector + * iteration, the linear solver's solve routine + * failed in a recoverable manner and the + * linear solver's setup routine indicated that + * its Jacobian-related data is not current. + * + * CV_FAIL_OTHER : During the current internal step try, the + * previous Newton iteration failed to converge + * even though the linear solver was using current + * Jacobian-related data. + * ----------------------------------------------------------------- + */ + +/* Constants for convfail (input to cv_lsetup) */ + +#define CV_NO_FAILURES 0 +#define CV_FAIL_BAD_J 1 +#define CV_FAIL_OTHER 2 + +/* + * ----------------------------------------------------------------- + * int (*cv_linit)(CVodeMem cv_mem); + * ----------------------------------------------------------------- + * The purpose of cv_linit is to complete initializations for a + * specific linear solver, such as counters and statistics. + * An LInitFn should return 0 if it has successfully initialized the + * CVODE linear solver and a negative value otherwise. + * If an error does occur, an appropriate message should be sent to + * the error handler function. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*cv_lsetup)(CVodeMem cv_mem, int convfail, N_Vector ypred, + * N_Vector fpred, booleantype *jcurPtr, + * N_Vector vtemp1, N_Vector vtemp2, + * N_Vector vtemp3); + * ----------------------------------------------------------------- + * The job of cv_lsetup is to prepare the linear solver for + * subsequent calls to cv_lsolve. It may recompute Jacobian- + * related data is it deems necessary. Its parameters are as + * follows: + * + * cv_mem - problem memory pointer of type CVodeMem. See the + * typedef earlier in this file. + * + * convfail - a flag to indicate any problem that occurred during + * the solution of the nonlinear equation on the + * current time step for which the linear solver is + * being used. This flag can be used to help decide + * whether the Jacobian data kept by a CVODE linear + * solver needs to be updated or not. + * Its possible values have been documented above. + * + * ypred - the predicted y vector for the current CVODE internal + * step. + * + * fpred - f(tn, ypred). + * + * jcurPtr - a pointer to a boolean to be filled in by cv_lsetup. + * The function should set *jcurPtr=TRUE if its Jacobian + * data is current after the call and should set + * *jcurPtr=FALSE if its Jacobian data is not current. + * Note: If cv_lsetup calls for re-evaluation of + * Jacobian data (based on convfail and CVODE state + * data), it should return *jcurPtr=TRUE always; + * otherwise an infinite loop can result. + * + * vtemp1 - temporary N_Vector provided for use by cv_lsetup. + * + * vtemp3 - temporary N_Vector provided for use by cv_lsetup. + * + * vtemp3 - temporary N_Vector provided for use by cv_lsetup. + * + * The cv_lsetup routine should return 0 if successful, a positive + * value for a recoverable error, and a negative value for an + * unrecoverable error. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * int (*cv_lsolve)(CVodeMem cv_mem, N_Vector b, N_Vector weight, + * N_Vector ycur, N_Vector fcur); + * ----------------------------------------------------------------- + * cv_lsolve must solve the linear equation P x = b, where + * P is some approximation to (I - gamma J), J = (df/dy)(tn,ycur) + * and the RHS vector b is input. The N-vector ycur contains + * the solver's current approximation to y(tn) and the vector + * fcur contains the N_Vector f(tn,ycur). The solution is to be + * returned in the vector b. cv_lsolve returns a positive value + * for a recoverable error and a negative value for an + * unrecoverable error. Success is indicated by a 0 return value. + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * void (*cv_lfree)(CVodeMem cv_mem); + * ----------------------------------------------------------------- + * cv_lfree should free up any memory allocated by the linear + * solver. This routine is called once a problem has been + * completed and the linear solver is no longer needed. + * ----------------------------------------------------------------- + */ + +/* + * ================================================================= + * C V O D E I N T E R N A L F U N C T I O N S + * ================================================================= + */ + +/* Prototype of internal ewtSet function */ + +int CVEwtSet(N_Vector ycur, N_Vector weight, void *data); + +/* High level error handler */ + +void CVProcessError(CVodeMem cv_mem, + int error_code, const char *module, const char *fname, + const char *msgfmt, ...); + +/* Prototype of internal errHandler function */ + +void CVErrHandler(int error_code, const char *module, const char *function, + char *msg, void *data); + +/* + * ================================================================= + * C V O D E E R R O R M E S S A G E S + * ================================================================= + */ + +#if defined(SUNDIALS_EXTENDED_PRECISION) + +#define MSG_TIME "t = %Lg" +#define MSG_TIME_H "t = %Lg and h = %Lg" +#define MSG_TIME_INT "t = %Lg is not between tcur - hu = %Lg and tcur = %Lg." +#define MSG_TIME_TOUT "tout = %Lg" +#define MSG_TIME_TSTOP "tstop = %Lg" + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define MSG_TIME "t = %lg" +#define MSG_TIME_H "t = %lg and h = %lg" +#define MSG_TIME_INT "t = %lg is not between tcur - hu = %lg and tcur = %lg." +#define MSG_TIME_TOUT "tout = %lg" +#define MSG_TIME_TSTOP "tstop = %lg" + +#else + +#define MSG_TIME "t = %g" +#define MSG_TIME_H "t = %g and h = %g" +#define MSG_TIME_INT "t = %g is not between tcur - hu = %g and tcur = %g." +#define MSG_TIME_TOUT "tout = %g" +#define MSG_TIME_TSTOP "tstop = %g" + +#endif + +/* Initialization and I/O error messages */ + +#define MSGCV_NO_MEM "cvode_mem = NULL illegal." +#define MSGCV_CVMEM_FAIL "Allocation of cvode_mem failed." +#define MSGCV_MEM_FAIL "A memory request failed." +#define MSGCV_BAD_LMM "Illegal value for lmm. The legal values are CV_ADAMS and CV_BDF." +#define MSGCV_BAD_ITER "Illegal value for iter. The legal values are CV_FUNCTIONAL and CV_NEWTON." +#define MSGCV_NO_MALLOC "Attempt to call before CVodeInit." +#define MSGCV_NEG_MAXORD "maxord <= 0 illegal." +#define MSGCV_BAD_MAXORD "Illegal attempt to increase maximum method order." +#define MSGCV_SET_SLDET "Attempt to use stability limit detection with the CV_ADAMS method illegal." +#define MSGCV_NEG_HMIN "hmin < 0 illegal." +#define MSGCV_NEG_HMAX "hmax < 0 illegal." +#define MSGCV_BAD_HMIN_HMAX "Inconsistent step size limits: hmin > hmax." +#define MSGCV_BAD_RELTOL "reltol < 0 illegal." +#define MSGCV_BAD_ABSTOL "abstol has negative component(s) (illegal)." +#define MSGCV_NULL_ABSTOL "abstol = NULL illegal." +#define MSGCV_NULL_Y0 "y0 = NULL illegal." +#define MSGCV_NULL_F "f = NULL illegal." +#define MSGCV_NULL_G "g = NULL illegal." +#define MSGCV_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGCV_BAD_K "Illegal value for k." +#define MSGCV_NULL_DKY "dky = NULL illegal." +#define MSGCV_BAD_T "Illegal value for t." MSG_TIME_INT +#define MSGCV_NO_ROOT "Rootfinding was not initialized." + +/* CVode Error Messages */ + +#define MSGCV_NO_TOLS "No integration tolerances have been specified." +#define MSGCV_LSOLVE_NULL "The linear solver's solve routine is NULL." +#define MSGCV_YOUT_NULL "yout = NULL illegal." +#define MSGCV_TRET_NULL "tret = NULL illegal." +#define MSGCV_BAD_EWT "Initial ewt has component(s) equal to zero (illegal)." +#define MSGCV_EWT_NOW_BAD "At " MSG_TIME ", a component of ewt has become <= 0." +#define MSGCV_BAD_ITASK "Illegal value for itask." +#define MSGCV_BAD_H0 "h0 and tout - t0 inconsistent." +#define MSGCV_BAD_TOUT "Trouble interpolating at " MSG_TIME_TOUT ". tout too far back in direction of integration" +#define MSGCV_EWT_FAIL "The user-provide EwtSet function failed." +#define MSGCV_EWT_NOW_FAIL "At " MSG_TIME ", the user-provide EwtSet function failed." +#define MSGCV_LINIT_FAIL "The linear solver's init routine failed." +#define MSGCV_HNIL_DONE "The above warning has been issued mxhnil times and will not be issued again for this problem." +#define MSGCV_TOO_CLOSE "tout too close to t0 to start integration." +#define MSGCV_MAX_STEPS "At " MSG_TIME ", mxstep steps taken before reaching tout." +#define MSGCV_TOO_MUCH_ACC "At " MSG_TIME ", too much accuracy requested." +#define MSGCV_HNIL "Internal " MSG_TIME_H " are such that t + h = t on the next step. The solver will continue anyway." +#define MSGCV_ERR_FAILS "At " MSG_TIME_H ", the error test failed repeatedly or with |h| = hmin." +#define MSGCV_CONV_FAILS "At " MSG_TIME_H ", the corrector convergence test failed repeatedly or with |h| = hmin." +#define MSGCV_SETUP_FAILED "At " MSG_TIME ", the setup routine failed in an unrecoverable manner." +#define MSGCV_SOLVE_FAILED "At " MSG_TIME ", the solve routine failed in an unrecoverable manner." +#define MSGCV_RHSFUNC_FAILED "At " MSG_TIME ", the right-hand side routine failed in an unrecoverable manner." +#define MSGCV_RHSFUNC_UNREC "At " MSG_TIME ", the right-hand side failed in a recoverable manner, but no recovery is possible." +#define MSGCV_RHSFUNC_REPTD "At " MSG_TIME " repeated recoverable right-hand side function errors." +#define MSGCV_RHSFUNC_FIRST "The right-hand side routine failed at the first call." +#define MSGCV_RTFUNC_FAILED "At " MSG_TIME ", the rootfinding routine failed in an unrecoverable manner." +#define MSGCV_CLOSE_ROOTS "Root found at and very near " MSG_TIME "." +#define MSGCV_BAD_TSTOP "The value " MSG_TIME_TSTOP " is behind current " MSG_TIME " in the direction of integration." +#define MSGCV_INACTIVE_ROOTS "At the end of the first step, there are still some root functions identically 0. This warning will not be issued again." + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/cvode_io.c b/dep/cvode-2.7.0/cvode/cvode_io.c new file mode 100644 index 00000000..2645ca18 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_io.c @@ -0,0 +1,1129 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.12 $ + * $Date: 2010/12/01 22:21:04 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the optional input and output + * functions for the CVODE solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvode_impl.h" +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +#define lrw (cv_mem->cv_lrw) +#define liw (cv_mem->cv_liw) +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) + +/* + * ================================================================= + * CVODE optional input functions + * ================================================================= + */ + +/* + * CVodeSetErrHandlerFn + * + * Specifies the error handler function + */ + +int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetErrHandlerFn", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_ehfun = ehfun; + cv_mem->cv_eh_data = eh_data; + + return(CV_SUCCESS); +} + +/* + * CVodeSetErrFile + * + * Specifies the FILE pointer for output (NULL means no messages) + */ + +int CVodeSetErrFile(void *cvode_mem, FILE *errfp) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetErrFile", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_errfp = errfp; + + return(CV_SUCCESS); +} + +/* + * CVodeSetIterType + * + * Specifies the iteration type (CV_FUNCTIONAL or CV_NEWTON) + */ + +int CVodeSetIterType(void *cvode_mem, int iter) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetIterType", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if ((iter != CV_FUNCTIONAL) && (iter != CV_NEWTON)) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetIterType", MSGCV_BAD_ITER); + return (CV_ILL_INPUT); + } + + cv_mem->cv_iter = iter; + + return(CV_SUCCESS); +} + +/* + * CVodeSetUserData + * + * Specifies the user data pointer for f + */ + +int CVodeSetUserData(void *cvode_mem, void *user_data) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetUserData", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_user_data = user_data; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxOrd + * + * Specifies the maximum method order + */ + +int CVodeSetMaxOrd(void *cvode_mem, int maxord) +{ + CVodeMem cv_mem; + int qmax_alloc; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxOrd", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (maxord <= 0) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxOrd", MSGCV_NEG_MAXORD); + return(CV_ILL_INPUT); + } + + /* Cannot increase maximum order beyond the value that + was used when allocating memory */ + qmax_alloc = cv_mem->cv_qmax_alloc; + + if (maxord > qmax_alloc) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxOrd", MSGCV_BAD_MAXORD); + return(CV_ILL_INPUT); + } + + cv_mem->cv_qmax = maxord; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxNumSteps + * + * Specifies the maximum number of integration steps + */ + +int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxNumSteps", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + /* Passing mxsteps=0 sets the default. Passing mxsteps<0 disables the test. */ + + if (mxsteps == 0) + cv_mem->cv_mxstep = MXSTEP_DEFAULT; + else + cv_mem->cv_mxstep = mxsteps; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxHnilWarns + * + * Specifies the maximum number of warnings for small h + */ + +int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxHnilWarns", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_mxhnil = mxhnil; + + return(CV_SUCCESS); +} + +/* + *CVodeSetStabLimDet + * + * Turns on/off the stability limit detection algorithm + */ + +int CVodeSetStabLimDet(void *cvode_mem, booleantype sldet) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetStabLimDet", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if( sldet && (cv_mem->cv_lmm != CV_BDF) ) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetStabLimDet", MSGCV_SET_SLDET); + return(CV_ILL_INPUT); + } + + cv_mem->cv_sldeton = sldet; + + return(CV_SUCCESS); +} + +/* + * CVodeSetInitStep + * + * Specifies the initial step size + */ + +int CVodeSetInitStep(void *cvode_mem, realtype hin) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetInitStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_hin = hin; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMinStep + * + * Specifies the minimum step size + */ + +int CVodeSetMinStep(void *cvode_mem, realtype hmin) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMinStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (hmin<0) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMinStep", MSGCV_NEG_HMIN); + return(CV_ILL_INPUT); + } + + /* Passing 0 sets hmin = zero */ + if (hmin == ZERO) { + cv_mem->cv_hmin = HMIN_DEFAULT; + return(CV_SUCCESS); + } + + if (hmin * cv_mem->cv_hmax_inv > ONE) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMinStep", MSGCV_BAD_HMIN_HMAX); + return(CV_ILL_INPUT); + } + + cv_mem->cv_hmin = hmin; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxStep + * + * Specifies the maximum step size + */ + +int CVodeSetMaxStep(void *cvode_mem, realtype hmax) +{ + realtype hmax_inv; + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxStep", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (hmax < 0) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxStep", MSGCV_NEG_HMAX); + return(CV_ILL_INPUT); + } + + /* Passing 0 sets hmax = infinity */ + if (hmax == ZERO) { + cv_mem->cv_hmax_inv = HMAX_INV_DEFAULT; + return(CV_SUCCESS); + } + + hmax_inv = ONE/hmax; + if (hmax_inv * cv_mem->cv_hmin > ONE) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetMaxStep", MSGCV_BAD_HMIN_HMAX); + return(CV_ILL_INPUT); + } + + cv_mem->cv_hmax_inv = hmax_inv; + + return(CV_SUCCESS); +} + +/* + * CVodeSetStopTime + * + * Specifies the time beyond which the integration is not to proceed. + */ + +int CVodeSetStopTime(void *cvode_mem, realtype tstop) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetStopTime", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* If CVode was called at least once, test if tstop is legal + * (i.e. if it was not already passed). + * If CVodeSetStopTime is called before the first call to CVode, + * tstop will be checked in CVode. */ + if (cv_mem->cv_nst > 0) { + + if ( (tstop - cv_mem->cv_tn) * cv_mem->cv_h < ZERO ) { + CVProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeSetStopTime", MSGCV_BAD_TSTOP, cv_mem->cv_tn); + return(CV_ILL_INPUT); + } + + } + + cv_mem->cv_tstop = tstop; + cv_mem->cv_tstopset = TRUE; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxErrTestFails + * + * Specifies the maximum number of error test failures during one + * step try. + */ + +int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxErrTestFails", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxnef = maxnef; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxConvFails + * + * Specifies the maximum number of nonlinear convergence failures + * during one step try. + */ + +int CVodeSetMaxConvFails(void *cvode_mem, int maxncf) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxConvFails", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxncf = maxncf; + + return(CV_SUCCESS); +} + +/* + * CVodeSetMaxNonlinIters + * + * Specifies the maximum number of nonlinear iterations during + * one solve. + */ + +int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetMaxNonlinIters", MSGCV_NO_MEM); + return (CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_maxcor = maxcor; + + return(CV_SUCCESS); +} + +/* + * CVodeSetNonlinConvCoef + * + * Specifies the coeficient in the nonlinear solver convergence + * test + */ + +int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetNonlinConvCoef", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_nlscoef = nlscoef; + + return(CV_SUCCESS); +} + +/* + * CVodeSetRootDirection + * + * Specifies the direction of zero-crossings to be monitored. + * The default is to monitor both crossings. + */ + +int CVodeSetRootDirection(void *cvode_mem, int *rootdir) +{ + CVodeMem cv_mem; + int i, nrt; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetRootDirection", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + nrt = cv_mem->cv_nrtfn; + if (nrt==0) { + CVProcessError(NULL, CV_ILL_INPUT, "CVODE", "CVodeSetRootDirection", MSGCV_NO_ROOT); + return(CV_ILL_INPUT); + } + + for(i=0; icv_rootdir[i] = rootdir[i]; + + return(CV_SUCCESS); +} + +/* + * CVodeSetNoInactiveRootWarn + * + * Disables issuing a warning if some root function appears + * to be identically zero at the beginning of the integration + */ + +int CVodeSetNoInactiveRootWarn(void *cvode_mem) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeSetNoInactiveRootWarn", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + cv_mem->cv_mxgnull = 0; + + return(CV_SUCCESS); +} + + +/* + * ================================================================= + * CVODE optional output functions + * ================================================================= + */ + +/* + * Readability constants + */ + +#define nst (cv_mem->cv_nst) +#define nfe (cv_mem->cv_nfe) +#define ncfn (cv_mem->cv_ncfn) +#define netf (cv_mem->cv_netf) +#define nni (cv_mem->cv_nni) +#define nsetups (cv_mem->cv_nsetups) +#define qu (cv_mem->cv_qu) +#define next_q (cv_mem->cv_next_q) +#define ewt (cv_mem->cv_ewt) +#define hu (cv_mem->cv_hu) +#define next_h (cv_mem->cv_next_h) +#define h0u (cv_mem->cv_h0u) +#define tolsf (cv_mem->cv_tolsf) +#define acor (cv_mem->cv_acor) +#define lrw (cv_mem->cv_lrw) +#define liw (cv_mem->cv_liw) +#define nge (cv_mem->cv_nge) +#define iroots (cv_mem->cv_iroots) +#define nor (cv_mem->cv_nor) +#define sldeton (cv_mem->cv_sldeton) +#define tn (cv_mem->cv_tn) +#define efun (cv_mem->cv_efun) + +/* + * CVodeGetNumSteps + * + * Returns the current number of integration steps + */ + +int CVodeGetNumSteps(void *cvode_mem, long int *nsteps) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumSteps", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nsteps = nst; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumRhsEvals + * + * Returns the current number of calls to f + */ + +int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumRhsEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nfevals = nfe; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumLinSolvSetups + * + * Returns the current number of calls to the linear solver setup routine + */ + +int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumLinSolvSetups", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nlinsetups = nsetups; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumErrTestFails + * + * Returns the current number of error test failures + */ + +int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumErrTestFails", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *netfails = netf; + + return(CV_SUCCESS); +} + +/* + * CVodeGetLastOrder + * + * Returns the order on the last succesful step + */ + +int CVodeGetLastOrder(void *cvode_mem, int *qlast) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetLastOrder", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *qlast = qu; + + return(CV_SUCCESS); +} + +/* + * CVodeGetCurrentOrder + * + * Returns the order to be attempted on the next step + */ + +int CVodeGetCurrentOrder(void *cvode_mem, int *qcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetCurrentOrder", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *qcur = next_q; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumStabLimOrderReds + * + * Returns the number of order reductions triggered by the stability + * limit detection algorithm + */ + +int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumStabLimOrderReds", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + if (sldeton==FALSE) + *nslred = 0; + else + *nslred = nor; + + return(CV_SUCCESS); +} + +/* + * CVodeGetActualInitStep + * + * Returns the step size used on the first step + */ + +int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetActualInitStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *hinused = h0u; + + return(CV_SUCCESS); +} + +/* + * CVodeGetLastStep + * + * Returns the step size used on the last successful step + */ + +int CVodeGetLastStep(void *cvode_mem, realtype *hlast) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetLastStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *hlast = hu; + + return(CV_SUCCESS); +} + +/* + * CVodeGetCurrentStep + * + * Returns the step size to be attempted on the next step + */ + +int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetCurrentStep", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *hcur = next_h; + + return(CV_SUCCESS); +} + +/* + * CVodeGetCurrentTime + * + * Returns the current value of the independent variable + */ + +int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetCurrentTime", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *tcur = tn; + + return(CV_SUCCESS); +} + +/* + * CVodeGetTolScaleFactor + * + * Returns a suggested factor for scaling tolerances + */ + +int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfact) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetTolScaleFactor", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *tolsfact = tolsf; + + return(CV_SUCCESS); +} + +/* + * CVodeGetErrWeights + * + * This routine returns the current weight vector. + */ + +int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetErrWeights", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + N_VScale(ONE, ewt, eweight); + + return(CV_SUCCESS); +} + +/* + * CVodeGetEstLocalErrors + * + * Returns an estimate of the local error + */ + +int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetEstLocalErrors", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + N_VScale(ONE, acor, ele); + + return(CV_SUCCESS); +} + +/* + * CVodeGetWorkSpace + * + * Returns integrator work space requirements + */ + +int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetWorkSpace", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *leniw = liw; + *lenrw = lrw; + + return(CV_SUCCESS); +} + +/* + * CVodeGetIntegratorStats + * + * Returns integrator statistics + */ + +int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, long int *nfevals, + long int *nlinsetups, long int *netfails, int *qlast, + int *qcur, realtype *hinused, realtype *hlast, + realtype *hcur, realtype *tcur) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetIntegratorStats", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *nsteps = nst; + *nfevals = nfe; + *nlinsetups = nsetups; + *netfails = netf; + *qlast = qu; + *qcur = next_q; + *hinused = h0u; + *hlast = hu; + *hcur = next_h; + *tcur = tn; + + return(CV_SUCCESS); +} + +/* + * CVodeGetNumGEvals + * + * Returns the current number of calls to g (for rootfinding) + */ + +int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals) +{ + CVodeMem cv_mem; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetNumGEvals", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + *ngevals = nge; + + return(CV_SUCCESS); +} + +/* + * CVodeGetRootInfo + * + * Returns pointer to array rootsfound showing roots found + */ + +int CVodeGetRootInfo(void *cvode_mem, int *rootsfound) +{ + CVodeMem cv_mem; + int i, nrt; + + if (cvode_mem==NULL) { + CVProcessError(NULL, CV_MEM_NULL, "CVODE", "CVodeGetRootInfo", MSGCV_NO_MEM); + return(CV_MEM_NULL); + } + + cv_mem = (CVodeMem) cvode_mem; + + nrt = cv_mem->cv_nrtfn; + + for (i=0; i +#include + +#include +#include "cvode_direct_impl.h" +#include "cvode_impl.h" + +#include + +/* Constant */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ================================================================= + * PROTOTYPES FOR PRIVATE FUNCTIONS + * ================================================================= + */ + +/* CVLAPACK DENSE linit, lsetup, lsolve, and lfree routines */ +static int cvLapackDenseInit(CVodeMem cv_mem); +static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC); +static void cvLapackDenseFree(CVodeMem cv_mem); + +/* CVLAPACK BAND linit, lsetup, lsolve, and lfree routines */ +static int cvLapackBandInit(CVodeMem cv_mem); +static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC); +static void cvLapackBandFree(CVodeMem cv_mem); + +/* + * ================================================================= + * READIBILITY REPLACEMENTS + * ================================================================= + */ + +#define lmm (cv_mem->cv_lmm) +#define f (cv_mem->cv_f) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define gamrat (cv_mem->cv_gamrat) +#define ewt (cv_mem->cv_ewt) + +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define tempv (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define mtype (cvdls_mem->d_type) +#define n (cvdls_mem->d_n) +#define ml (cvdls_mem->d_ml) +#define mu (cvdls_mem->d_mu) +#define smu (cvdls_mem->d_smu) +#define jacDQ (cvdls_mem->d_jacDQ) +#define djac (cvdls_mem->d_djac) +#define bjac (cvdls_mem->d_bjac) +#define M (cvdls_mem->d_M) +#define savedJ (cvdls_mem->d_savedJ) +#define pivots (cvdls_mem->d_pivots) +#define nstlj (cvdls_mem->d_nstlj) +#define nje (cvdls_mem->d_nje) +#define nfeDQ (cvdls_mem->d_nfeDQ) +#define J_data (cvdls_mem->d_J_data) +#define last_flag (cvdls_mem->d_last_flag) + +/* + * ================================================================= + * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVLapackDense + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the linear solver module. CVLapackDense first + * calls the existing lfree routine if this is not NULL. Then it sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be cvLapackDenseInit, cvLapackDenseSetup, cvLapackDenseSolve, + * and cvLapackDenseFree, respectively. It allocates memory for a + * structure of type CVDlsMemRec and sets the cv_lmem field in + * (*cvode_mem) to the address of this structure. It sets setupNonNull + * in (*cvode_mem) to TRUE, and the d_jac field to the default + * cvDlsDenseDQJac. Finally, it allocates memory for M, pivots, and + * savedJ. + * The return value is SUCCESS = 0, or LMEM_FAIL = -1. + * + * NOTE: The dense linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVLapackDense will first + * test for a compatible N_Vector internal representation + * by checking that N_VGetArrayPointer and N_VSetArrayPointer + * exist. + * ----------------------------------------------------------------- + */ +int CVLapackDense(void *cvode_mem, int N) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVLAPACK", "CVLapackDense", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the LAPACK solver */ + if (tempv->ops->nvgetarraypointer == NULL || + tempv->ops->nvsetarraypointer == NULL) { + CVProcessError(cv_mem, CVDLS_ILL_INPUT, "CVLAPACK", "CVLapackDense", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree !=NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvLapackDenseInit; + lsetup = cvLapackDenseSetup; + lsolve = cvLapackDenseSolve; + lfree = cvLapackDenseFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_DENSE; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + djac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + setupNonNull = TRUE; + + /* Set problem dimension */ + n = (long int) N; + + /* Allocate memory for M, pivot array, and savedJ */ + M = NULL; + pivots = NULL; + savedJ = NULL; + + M = NewDenseMat(n, n); + if (M == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + pivots = NewIntArray(N); + if (pivots == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + savedJ = NewDenseMat(n, n); + if (savedJ == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyArray(pivots); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVLapackBand + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the band linear solver module. It first calls + * the existing lfree routine if this is not NULL. It then sets the + * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem) + * to be cvLapackBandInit, cvLapackBandSetup, cvLapackBandSolve, + * and cvLapackBandFree, respectively. It allocates memory for a + * structure of type CVLapackBandMemRec and sets the cv_lmem field in + * (*cvode_mem) to the address of this structure. It sets setupNonNull + * in (*cvode_mem) to be TRUE, mu to be mupper, ml to be mlower, and + * the jacE and jacI field to NULL. + * Finally, it allocates memory for M, pivots, and savedJ. + * The CVLapackBand return value is CVDLS_SUCCESS = 0, + * CVDLS_MEM_FAIL = -1, or CVDLS_ILL_INPUT = -2. + * + * NOTE: The CVLAPACK linear solver assumes a serial implementation + * of the NVECTOR package. Therefore, CVLapackBand will first + * test for compatible a compatible N_Vector internal + * representation by checking that the function + * N_VGetArrayPointer exists. + * ----------------------------------------------------------------- + */ +int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower) +{ + CVodeMem cv_mem; + CVDlsMem cvdls_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVDLS_MEM_NULL, "CVLAPACK", "CVLapackBand", MSGD_CVMEM_NULL); + return(CVDLS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Test if the NVECTOR package is compatible with the BAND solver */ + if (tempv->ops->nvgetarraypointer == NULL) { + CVProcessError(cv_mem, CVDLS_ILL_INPUT, "CVLAPACK", "CVLapackBand", MSGD_BAD_NVECTOR); + return(CVDLS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = cvLapackBandInit; + lsetup = cvLapackBandSetup; + lsolve = cvLapackBandSolve; + lfree = cvLapackBandFree; + + /* Get memory for CVDlsMemRec */ + cvdls_mem = NULL; + cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec)); + if (cvdls_mem == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + return(CVDLS_MEM_FAIL); + } + + /* Set matrix type */ + mtype = SUNDIALS_BAND; + + /* Initialize Jacobian-related data */ + jacDQ = TRUE; + bjac = NULL; + J_data = NULL; + + last_flag = CVDLS_SUCCESS; + setupNonNull = TRUE; + + /* Load problem dimension */ + n = (long int) N; + + /* Load half-bandwiths in cvdls_mem */ + ml = (long int) mlower; + mu = (long int) mupper; + + /* Test ml and mu for legality */ + if ((ml < 0) || (mu < 0) || (ml >= n) || (mu >= n)) { + CVProcessError(cv_mem, CVDLS_ILL_INPUT, "CVLAPACK", "CVLapackBand", MSGD_BAD_SIZES); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_ILL_INPUT); + } + + /* Set extended upper half-bandwith for M (required for pivoting) */ + smu = MIN(n-1, mu + ml); + + /* Allocate memory for M, pivot array, and savedJ */ + M = NULL; + pivots = NULL; + savedJ = NULL; + + M = NewBandMat(n, mu, ml, smu); + if (M == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + pivots = NewIntArray(N); + if (pivots == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + DestroyMat(M); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + savedJ = NewBandMat(n, mu, ml, smu); + if (savedJ == NULL) { + CVProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL); + DestroyMat(M); + DestroyArray(pivots); + free(cvdls_mem); cvdls_mem = NULL; + return(CVDLS_MEM_FAIL); + } + + /* Attach linear solver memory to integrator memory */ + lmem = cvdls_mem; + + return(CVDLS_SUCCESS); +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS + * ================================================================= + */ + +/* + * cvLapackDenseInit does remaining initializations specific to the dense + * linear solver. + */ +static int cvLapackDenseInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + djac = cvDlsDenseDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackDenseSetup does the setup operations for the dense linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J + * updates counters, and calls the dense LU factorization routine. + */ +static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVDlsMem cvdls_mem; + realtype dgamma, fact; + booleantype jbad, jok; + int ier, retval, one = 1; + int intn, lenmat; + + cvdls_mem = (CVDlsMem) lmem; + intn = (int) n; + lenmat = M->ldata ; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + dcopy_f77(&lenmat, savedJ->data, &one, M->data, &one); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = djac(n, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3); + + if (retval == 0) { + dcopy_f77(&lenmat, M->data, &one, savedJ->data, &one); + } else if (retval < 0) { + CVProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVLAPACK", "cvLapackDenseSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } else if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + } + + /* Scale J by - gamma */ + fact = -gamma; + dscal_f77(&lenmat, &fact, M->data, &one); + + /* Add identity to get M = I - gamma*J*/ + AddIdentity(M); + + /* Do LU factorization of M */ + dgetrf_f77(&intn, &intn, M->data, &intn, pivots, &ier); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = (long int) ier; + if (ier > 0) return(1); + return(0); +} + +/* + * cvLapackDenseSolve handles the solve operation for the dense linear solver + * by calling the dense backsolve routine. + */ +static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC) +{ + CVDlsMem cvdls_mem; + realtype *bd, fact; + int ier, one = 1; + int intn; + + cvdls_mem = (CVDlsMem) lmem; + intn = (int) n; + + bd = N_VGetArrayPointer(b); + + dgetrs_f77("N", &intn, &one, M->data, &intn, pivots, bd, &intn, &ier, 1); + + if (ier > 0) return(1); + + /* For BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + fact = TWO/(ONE + gamrat); + dscal_f77(&intn, &fact, bd, &one); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackDenseFree frees memory specific to the dense linear solver. + */ +static void cvLapackDenseFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyArray(pivots); + DestroyMat(savedJ); + free(cvdls_mem); + cvdls_mem = NULL; +} + +/* + * ================================================================= + * PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS + * ================================================================= + */ + +/* + * cvLapackBandInit does remaining initializations specific to the band + * linear solver. + */ +static int cvLapackBandInit(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + nje = 0; + nfeDQ = 0; + nstlj = 0; + + /* Set Jacobian function and data, depending on jacDQ */ + if (jacDQ) { + bjac = cvDlsBandDQJac; + J_data = cv_mem; + } else { + J_data = cv_mem->cv_user_data; + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackBandSetup does the setup operations for the band linear solver. + * It makes a decision whether or not to call the Jacobian evaluation + * routine based on various state variables, and if not it uses the + * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J, + * updates counters, and calls the band LU factorization routine. + */ +static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, + N_Vector yP, N_Vector fctP, + booleantype *jcurPtr, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + CVDlsMem cvdls_mem; + realtype dgamma, fact; + booleantype jbad, jok; + int ier, retval, one = 1; + int intn, iml, imu, lenmat, ldmat; + + cvdls_mem = (CVDlsMem) lmem; + intn = (int) n; + iml = (int) ml; + imu = (int) mu; + lenmat = M->ldata; + ldmat = M->ldim; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) || + (convfail == CV_FAIL_OTHER); + jok = !jbad; + + if (jok) { + + /* If jok = TRUE, use saved copy of J */ + *jcurPtr = FALSE; + dcopy_f77(&lenmat, savedJ->data, &one, M->data, &one); + + } else { + + /* If jok = FALSE, call jac routine for new J value */ + nje++; + nstlj = nst; + *jcurPtr = TRUE; + SetToZero(M); + + retval = bjac(n, mu, ml, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3); + if (retval == 0) { + dcopy_f77(&lenmat, M->data, &one, savedJ->data, &one); + } else if (retval < 0) { + CVProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVLAPACK", "cvLapackBandSetup", MSGD_JACFUNC_FAILED); + last_flag = CVDLS_JACFUNC_UNRECVR; + return(-1); + } else if (retval > 0) { + last_flag = CVDLS_JACFUNC_RECVR; + return(1); + } + + } + + /* Scale J by - gamma */ + fact = -gamma; + dscal_f77(&lenmat, &fact, M->data, &one); + + /* Add identity to get M = I - gamma*J*/ + AddIdentity(M); + + /* Do LU factorization of M */ + dgbtrf_f77(&intn, &intn, &iml, &imu, M->data, &ldmat, pivots, &ier); + + /* Return 0 if the LU was complete; otherwise return 1 */ + last_flag = (long int) ier; + if (ier > 0) return(1); + return(0); + +} + +/* + * cvLapackBandSolve handles the solve operation for the band linear solver + * by calling the band backsolve routine. + */ +static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector yC, N_Vector fctC) +{ + CVDlsMem cvdls_mem; + realtype *bd, fact; + int ier, one = 1; + int intn, iml, imu, ldmat; + + cvdls_mem = (CVDlsMem) lmem; + intn = (int) n; + iml = (int) ml; + imu = (int) mu; + ldmat = M->ldim; + + bd = N_VGetArrayPointer(b); + + dgbtrs_f77("N", &intn, &iml, &imu, &one, M->data, &ldmat, pivots, bd, &intn, &ier, 1); + if (ier > 0) return(1); + + /* For BDF, scale the correction to account for change in gamma */ + if ((lmm == CV_BDF) && (gamrat != ONE)) { + fact = TWO/(ONE + gamrat); + dscal_f77(&intn, &fact, bd, &one); + } + + last_flag = CVDLS_SUCCESS; + return(0); +} + +/* + * cvLapackBandFree frees memory specific to the band linear solver. + */ +static void cvLapackBandFree(CVodeMem cv_mem) +{ + CVDlsMem cvdls_mem; + + cvdls_mem = (CVDlsMem) lmem; + + DestroyMat(M); + DestroyArray(pivots); + DestroyMat(savedJ); + free(cvdls_mem); + cvdls_mem = NULL; +} + diff --git a/dep/cvode-2.7.0/cvode/cvode_spbcgs.c b/dep/cvode-2.7.0/cvode/cvode_spbcgs.c new file mode 100644 index 00000000..ffe10901 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_spbcgs.c @@ -0,0 +1,459 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2011/03/23 22:27:43 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPBCG linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvode_spils_impl.h" +#include "cvode_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* CVSPBCG linit, lsetup, lsolve, and lfree routines */ + +static int CVSpbcgInit(CVodeMem cv_mem); + +static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow); + +static void CVSpbcgFree(CVodeMem cv_mem); + + +/* Readability Replacements */ + +#define tq (cv_mem->cv_tq) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define errfp (cv_mem->cv_errfp) +#define mnewt (cv_mem->cv_mnewt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define deltar (cvspils_mem->s_deltar) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define nstlpre (cvspils_mem->s_nstlpre) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) +#define spils_mem (cvspils_mem->s_spils_mem) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcg + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the Spbcg linear solver module. CVSpbcg first + * calls the existing lfree routine if this is not NULL. It then sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVSpbcgInit, CVSpbcgSetup, CVSpbcgSolve, and CVSpbcgFree, + * respectively. It allocates memory for a structure of type + * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem), + * and sets various fields in the CVSpilsMemRec structure. + * Finally, CVSpbcg allocates memory for ytemp and x, and calls + * SpbcgMalloc to allocate memory for the Spbcg solver. + * ----------------------------------------------------------------- + */ + +int CVSpbcg(void *cvode_mem, int pretype, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPBCG", "CVSpbcg", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VDotProd is present */ + if (vec_tmpl->ops->nvdotprod == NULL) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVSpbcgInit; + lsetup = CVSpbcgSetup; + lsolve = CVSpbcgSolve; + lfree = CVSpbcgFree; + + /* Get memory for CVSpilsMemRec */ + cvspils_mem = NULL; + cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec)); + if (cvspils_mem == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set ILS type */ + cvspils_mem->s_type = SPILS_SPBCG; + + /* Set Spbcg parameters that have been passed in call sequence */ + cvspils_mem->s_pretype = pretype; + mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + j_data = NULL; + + /* Set defaults for preconditioner-related fields */ + cvspils_mem->s_pset = NULL; + cvspils_mem->s_psolve = NULL; + cvspils_mem->s_pfree = NULL; + cvspils_mem->s_P_data = cv_mem->cv_user_data; + + /* Set default values for the rest of the Spbcg parameters */ + cvspils_mem->s_eplifac = CVSPILS_EPLIN; + + cvspils_mem->s_last_flag = CVSPILS_SUCCESS; + + setupNonNull = FALSE; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_PRETYPE); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_ILL_INPUT); + } + + /* Allocate memory for ytemp and x */ + + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + x = N_VClone(vec_tmpl); + if (x == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt(N_VDotProd(ytemp, ytemp)); + + /* Call SpbcgMalloc to allocate workspace for Spbcg */ + spbcg_mem = NULL; + spbcg_mem = SpbcgMalloc(mxl, vec_tmpl); + if (spbcg_mem == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(x); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Attach SPBCG memory to spils memory structure */ + spils_mem = (void *) spbcg_mem; + + /* Attach linear solver memory to integrator memory */ + lmem = cvspils_mem; + + return(CVSPILS_SUCCESS); +} + + + +/* Additional readability replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define pset (cvspils_mem->s_pset) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the Spbcg + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVSpbcgInit(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + + cvspils_mem = (CVSpilsMem) lmem; + spbcg_mem = (SpbcgMem) spils_mem; + + /* Initialize counters */ + npe = nli = nps = ncfl = nstlpre = 0; + njtimes = nfes = 0; + + /* Check for legal combination pretype - psolve */ + if ((pretype != PREC_NONE) && (psolve == NULL)) { + CVProcessError(cv_mem, -1, "CVSPBCG", "CVSpbcgInit", MSGS_PSOLVE_REQ); + last_flag = CVSPILS_ILL_INPUT; + return(-1); + } + + /* Set setupNonNull = TRUE iff there is preconditioning + (pretype != PREC_NONE) and there is a preconditioning + setup phase (pset != NULL) */ + setupNonNull = (pretype != PREC_NONE) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = CVSpilsDQJtimes; + j_data = cv_mem; + } else { + j_data = user_data; + } + + /* Set maxl in the SPBCG memory in case it was changed by the user */ + spbcg_mem->l_max = maxl; + + last_flag = CVSPILS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the Spbcg linear solver. + * It makes a decision as to whether or not to signal for reevaluation + * of Jacobian data in the pset routine, based on various state + * variables, then it calls pset. If we signal for reevaluation, + * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output. + * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre. + * ----------------------------------------------------------------- + */ + +static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + int retval; + CVSpilsMem cvspils_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) || + (convfail == CV_FAIL_OTHER); + *jcurPtr = jbad; + jok = !jbad; + + /* Call pset routine and possibly reset jcur */ + retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, + vtemp1, vtemp2, vtemp3); + if (retval < 0) { + CVProcessError(cv_mem, SPBCG_PSET_FAIL_UNREC, "CVSPBCG", "CVSpbcgSetup", MSGS_PSET_FAILED); + last_flag = SPBCG_PSET_FAIL_UNREC; + } + if (retval > 0) { + last_flag = SPBCG_PSET_FAIL_REC; + } + + if (jbad) *jcurPtr = TRUE; + + /* If jcur = TRUE, increment npe and save nst value */ + if (*jcurPtr) { + npe++; + nstlpre = nst; + } + + last_flag = SPBCG_SUCCESS; + + /* Return the same value that pset returned */ + return(retval); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgSolve + * ----------------------------------------------------------------- + * This routine handles the call to the generic solver SpbcgSolve + * for the solution of the linear system Ax = b with the SPBCG method. + * The solution x is returned in the vector b. + * + * If the WRMS norm of b is small, we return x = b (if this is the first + * Newton iteration) or x = 0 (if a later Newton iteration). + * + * Otherwise, we set the tolerance parameter and initial guess (x = 0), + * call SpbcgSolve, and copy the solution x into b. The x-scaling and + * b-scaling arrays are both equal to weight. + * + * The counters nli, nps, and ncfl are incremented, and the return value + * is set according to the success of SpbcgSolve. The success flag is + * returned if SpbcgSolve converged, or if this is the first Newton + * iteration and the residual norm was reduced below its initial value. + * ----------------------------------------------------------------- + */ + +static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow) +{ + realtype bnorm, res_norm; + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + int nli_inc, nps_inc, retval; + + cvspils_mem = (CVSpilsMem) lmem; + + spbcg_mem = (SpbcgMem) spils_mem; + + /* Test norm(b); if small, return x = 0 or x = b */ + deltar = eplifac * tq[4]; + + bnorm = N_VWrmsNorm(b, weight); + if (bnorm <= deltar) { + if (mnewt > 0) N_VConst(ZERO, b); + return(0); + } + + /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */ + ycur = ynow; + fcur = fnow; + + /* Set inputs delta and initial guess x = 0 to SpbcgSolve */ + delta = deltar * sqrtN; + N_VConst(ZERO, x); + + /* Call SpbcgSolve and copy x to b */ + retval = SpbcgSolve(spbcg_mem, cv_mem, x, b, pretype, delta, + cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve, + &res_norm, &nli_inc, &nps_inc); + + N_VScale(ONE, x, b); + + /* Increment counters nli, nps, and ncfl */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPBCG_SUCCESS) ncfl++; + + /* Interpret return value from SpbcgSolve */ + + last_flag = retval; + + switch(retval) { + + case SPBCG_SUCCESS: + return(0); + break; + case SPBCG_RES_REDUCED: + if (mnewt == 0) return(0); + else return(1); + break; + case SPBCG_CONV_FAIL: + return(1); + break; + case SPBCG_PSOLVE_FAIL_REC: + return(1); + break; + case SPBCG_ATIMES_FAIL_REC: + return(1); + break; + case SPBCG_MEM_NULL: + return(-1); + break; + case SPBCG_ATIMES_FAIL_UNREC: + CVProcessError(cv_mem, SPBCG_ATIMES_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPBCG_PSOLVE_FAIL_UNREC: + CVProcessError(cv_mem, SPBCG_PSOLVE_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcgFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the Spbcg linear solver. + * ----------------------------------------------------------------- + */ + +static void CVSpbcgFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SpbcgMem spbcg_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(x); + + spbcg_mem = (SpbcgMem) spils_mem; + SpbcgFree(spbcg_mem); + + if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem); + + free(cvspils_mem); + cv_mem->cv_lmem = NULL; +} + diff --git a/dep/cvode-2.7.0/cvode/cvode_spgmr.c b/dep/cvode-2.7.0/cvode/cvode_spgmr.c new file mode 100644 index 00000000..08d85dae --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_spgmr.c @@ -0,0 +1,463 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2011/03/23 22:27:43 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPGMR linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvode_spils_impl.h" +#include "cvode_impl.h" + +#include +#include + +/* Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* CVSPGMR linit, lsetup, lsolve, and lfree routines */ + +static int CVSpgmrInit(CVodeMem cv_mem); + +static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow); + +static void CVSpgmrFree(CVodeMem cv_mem); + +/* Readability Replacements */ + +#define tq (cv_mem->cv_tq) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define mnewt (cv_mem->cv_mnewt) +#define ropt (cv_mem->cv_ropt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define deltar (cvspils_mem->s_deltar) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define nstlpre (cvspils_mem->s_nstlpre) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) +#define spils_mem (cvspils_mem->s_spils_mem) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * CVSpgmr + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the Spgmr linear solver module. CVSpgmr first + * calls the existing lfree routine if this is not NULL. It then sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVSpgmrInit, CVSpgmrSetup, CVSpgmrSolve, and CVSpgmrFree, + * respectively. It allocates memory for a structure of type + * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem), + * and sets various fields in the CVSpilsMemRec structure. + * Finally, CVSpgmr allocates memory for ytemp and x, and calls + * SpgmrMalloc to allocate memory for the Spgmr solver. + * ----------------------------------------------------------------- + */ + +int CVSpgmr(void *cvode_mem, int pretype, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + SpgmrMem spgmr_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPGMR", "CVSpgmr", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VDotProd is present */ + if(vec_tmpl->ops->nvdotprod == NULL) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVSpgmrInit; + lsetup = CVSpgmrSetup; + lsolve = CVSpgmrSolve; + lfree = CVSpgmrFree; + + /* Get memory for CVSpilsMemRec */ + cvspils_mem = NULL; + cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec)); + if (cvspils_mem == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set ILS type */ + cvspils_mem->s_type = SPILS_SPGMR; + + /* Set Spgmr parameters that have been passed in call sequence */ + cvspils_mem->s_pretype = pretype; + mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + j_data = NULL; + + /* Set defaults for preconditioner-related fields */ + cvspils_mem->s_pset = NULL; + cvspils_mem->s_psolve = NULL; + cvspils_mem->s_pfree = NULL; + cvspils_mem->s_P_data = cv_mem->cv_user_data; + + /* Set default values for the rest of the Spgmr parameters */ + cvspils_mem->s_gstype = MODIFIED_GS; + cvspils_mem->s_eplifac = CVSPILS_EPLIN; + + cvspils_mem->s_last_flag = CVSPILS_SUCCESS; + + setupNonNull = FALSE; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_PRETYPE); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_ILL_INPUT); + } + + /* Allocate memory for ytemp and x */ + + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + x = N_VClone(vec_tmpl); + if (x == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt( N_VDotProd(ytemp, ytemp) ); + + /* Call SpgmrMalloc to allocate workspace for Spgmr */ + spgmr_mem = NULL; + spgmr_mem = SpgmrMalloc(mxl, vec_tmpl); + if (spgmr_mem == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(x); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Attach SPGMR memory to spils memory structure */ + spils_mem = (void *) spgmr_mem; + + /* Attach linear solver memory to integrator memory */ + lmem = cvspils_mem; + + return(CVSPILS_SUCCESS); +} + + +/* Additional readability Replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define gstype (cvspils_mem->s_gstype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define pset (cvspils_mem->s_pset) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * CVSpgmrInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the Spgmr + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVSpgmrInit(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + cvspils_mem = (CVSpilsMem) lmem; + + /* Initialize counters */ + npe = nli = nps = ncfl = nstlpre = 0; + njtimes = nfes = 0; + + /* Check for legal combination pretype - psolve */ + if ((pretype != PREC_NONE) && (psolve == NULL)) { + CVProcessError(cv_mem, -1, "CVSPGMR", "CVSpgmrInit", MSGS_PSOLVE_REQ); + last_flag = CVSPILS_ILL_INPUT; + return(-1); + } + + /* Set setupNonNull = TRUE iff there is preconditioning (pretype != PREC_NONE) + and there is a preconditioning setup phase (pset != NULL) */ + setupNonNull = (pretype != PREC_NONE) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = CVSpilsDQJtimes; + j_data = cv_mem; + } else { + j_data = user_data; + } + + last_flag = CVSPILS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVSpgmrSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the Spgmr linear solver. + * It makes a decision as to whether or not to signal for re-evaluation + * of Jacobian data in the pset routine, based on various state + * variables, then it calls pset. If we signal for re-evaluation, + * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output. + * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre. + * ----------------------------------------------------------------- + */ + +static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + int retval; + CVSpilsMem cvspils_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) || + (convfail == CV_FAIL_OTHER); + *jcurPtr = jbad; + jok = !jbad; + + /* Call pset routine and possibly reset jcur */ + retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, + vtemp1, vtemp2, vtemp3); + if (retval < 0) { + CVProcessError(cv_mem, SPGMR_PSET_FAIL_UNREC, "CVSPGMR", "CVSpgmrSetup", MSGS_PSET_FAILED); + last_flag = SPGMR_PSET_FAIL_UNREC; + } + if (retval > 0) { + last_flag = SPGMR_PSET_FAIL_REC; + } + + if (jbad) *jcurPtr = TRUE; + + /* If jcur = TRUE, increment npe and save nst value */ + if (*jcurPtr) { + npe++; + nstlpre = nst; + } + + last_flag = SPGMR_SUCCESS; + + /* Return the same value that pset returned */ + return(retval); +} + +/* + * ----------------------------------------------------------------- + * CVSpgmrSolve + * ----------------------------------------------------------------- + * This routine handles the call to the generic solver SpgmrSolve + * for the solution of the linear system Ax = b with the SPGMR method, + * without restarts. The solution x is returned in the vector b. + * + * If the WRMS norm of b is small, we return x = b (if this is the first + * Newton iteration) or x = 0 (if a later Newton iteration). + * + * Otherwise, we set the tolerance parameter and initial guess (x = 0), + * call SpgmrSolve, and copy the solution x into b. The x-scaling and + * b-scaling arrays are both equal to weight, and no restarts are allowed. + * + * The counters nli, nps, and ncfl are incremented, and the return value + * is set according to the success of SpgmrSolve. The success flag is + * returned if SpgmrSolve converged, or if this is the first Newton + * iteration and the residual norm was reduced below its initial value. + * ----------------------------------------------------------------- + */ + +static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow) +{ + realtype bnorm, res_norm; + CVSpilsMem cvspils_mem; + SpgmrMem spgmr_mem; + int nli_inc, nps_inc, retval; + + cvspils_mem = (CVSpilsMem) lmem; + + spgmr_mem = (SpgmrMem) spils_mem; + + /* Test norm(b); if small, return x = 0 or x = b */ + deltar = eplifac * tq[4]; + + bnorm = N_VWrmsNorm(b, weight); + if (bnorm <= deltar) { + if (mnewt > 0) N_VConst(ZERO, b); + return(0); + } + + /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */ + ycur = ynow; + fcur = fnow; + + /* Set inputs delta and initial guess x = 0 to SpgmrSolve */ + delta = deltar * sqrtN; + N_VConst(ZERO, x); + + /* Call SpgmrSolve and copy x to b */ + retval = SpgmrSolve(spgmr_mem, cv_mem, x, b, pretype, gstype, delta, 0, + cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve, + &res_norm, &nli_inc, &nps_inc); + + N_VScale(ONE, x, b); + + /* Increment counters nli, nps, and ncfl */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPGMR_SUCCESS) ncfl++; + + /* Interpret return value from SpgmrSolve */ + + last_flag = retval; + + switch(retval) { + + case SPGMR_SUCCESS: + return(0); + break; + case SPGMR_RES_REDUCED: + if (mnewt == 0) return(0); + else return(1); + break; + case SPGMR_CONV_FAIL: + return(1); + break; + case SPGMR_QRFACT_FAIL: + return(1); + break; + case SPGMR_PSOLVE_FAIL_REC: + return(1); + break; + case SPGMR_ATIMES_FAIL_REC: + return(1); + break; + case SPGMR_MEM_NULL: + return(-1); + break; + case SPGMR_ATIMES_FAIL_UNREC: + CVProcessError(cv_mem, SPGMR_ATIMES_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPGMR_PSOLVE_FAIL_UNREC: + CVProcessError(cv_mem, SPGMR_PSOLVE_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + case SPGMR_GS_FAIL: + return(-1); + break; + case SPGMR_QRSOL_FAIL: + return(-1); + break; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVSpgmrFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the Spgmr linear solver. + * ----------------------------------------------------------------- + */ + +static void CVSpgmrFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SpgmrMem spgmr_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(x); + + spgmr_mem = (SpgmrMem) spils_mem; + SpgmrFree(spgmr_mem); + + if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem); + + free(cvspils_mem); + cv_mem->cv_lmem = NULL; +} + diff --git a/dep/cvode-2.7.0/cvode/cvode_spils.c b/dep/cvode-2.7.0/cvode/cvode_spils.c new file mode 100644 index 00000000..2fa5e4e0 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_spils.c @@ -0,0 +1,697 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2011/06/23 00:19:54 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPILS linear solvers. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "cvode_impl.h" +#include "cvode_spils_impl.h" + +/* Private constants */ + +#define ZERO RCONST(0.0) +#define PT25 RCONST(0.25) +#define ONE RCONST(1.0) + +/* Algorithmic constants */ + +#define MAX_ITERS 3 /* max. number of attempts to recover in DQ J*v */ + +/* Readability Replacements */ + +#define lrw1 (cv_mem->cv_lrw1) +#define liw1 (cv_mem->cv_liw1) +#define tq (cv_mem->cv_tq) +#define tn (cv_mem->cv_tn) +#define h (cv_mem->cv_h) +#define gamma (cv_mem->cv_gamma) +#define nfe (cv_mem->cv_nfe) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define lmem (cv_mem->cv_lmem) + +#define ils_type (cvspils_mem->s_type) +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * OPTIONAL INPUT and OUTPUT + * ----------------------------------------------------------------- + */ + + +/* + * ----------------------------------------------------------------- + * CVSpilsSetPrecType + * ----------------------------------------------------------------- + */ + +int CVSpilsSetPrecType(void *cvode_mem, int pretype) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPrecType", MSGS_BAD_PRETYPE); + return(CVSPILS_ILL_INPUT); + } + + cvspils_mem->s_pretype = pretype; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsSetGSType + * ----------------------------------------------------------------- + */ + +int CVSpilsSetGSType(void *cvode_mem, int gstype) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + if (ils_type != SPILS_SPGMR) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_LSTYPE); + return(CVSPILS_ILL_INPUT); + } + + /* Check for legal gstype */ + if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_GSTYPE); + return(CVSPILS_ILL_INPUT); + } + + cvspils_mem->s_gstype = gstype; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSpilsSetMaxl + * ----------------------------------------------------------------- + */ + +int CVSpilsSetMaxl(void *cvode_mem, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(NULL, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + if (ils_type == SPILS_SPGMR) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetMaxl", MSGS_BAD_LSTYPE); + return(CVSPILS_ILL_INPUT); + } + + mxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + cvspils_mem->s_maxl = mxl; + + return(CVSPILS_SUCCESS); +} + + +/* + * ----------------------------------------------------------------- + * CVSpilsSetEpsLin + * ----------------------------------------------------------------- + */ + +int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + /* Check for legal eplifac */ + if(eplifac < ZERO) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetEpsLin", MSGS_BAD_EPLIN); + return(CVSPILS_ILL_INPUT); + } + + cvspils_mem->s_eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsSetPrecSetupFn + * ----------------------------------------------------------------- + */ + +int CVSpilsSetPreconditioner(void *cvode_mem, + CVSpilsPrecSetupFn pset, CVSpilsPrecSolveFn psolve) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + cvspils_mem->s_pset = pset; + cvspils_mem->s_psolve = psolve; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsSetJacTimesVecFn + * ----------------------------------------------------------------- + */ + +int CVSpilsSetJacTimesVecFn(void *cvode_mem, CVSpilsJacTimesVecFn jtv) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + if (jtv != NULL) { + jtimesDQ = FALSE; + jtimes = jtv; + } else { + jtimesDQ = TRUE; + } + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetWorkSpace + * ----------------------------------------------------------------- + */ + +int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int maxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + + switch(ils_type) { + case SPILS_SPGMR: + maxl = cvspils_mem->s_maxl; + *lenrwLS = lrw1*(maxl + 5) + maxl*(maxl + 4) + 1; + *leniwLS = liw1*(maxl + 5); + break; + case SPILS_SPBCG: + *lenrwLS = lrw1 * 9; + *leniwLS = liw1 * 9; + break; + case SPILS_SPTFQMR: + *lenrwLS = lrw1*11; + *leniwLS = liw1*11; + break; + } + + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumPrecEvals + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *npevals = npe; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumPrecSolves + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *npsolves = nps; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumLinIters + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *nliters = nli; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumConvFails + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *nlcfails = ncfl; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumJtimesEvals + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *njvevals = njtimes; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetNumRhsEvals + * ----------------------------------------------------------------- + */ + +int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *nfevalsLS = nfes; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetLastFlag + * ----------------------------------------------------------------- + */ + +int CVSpilsGetLastFlag(void *cvode_mem, long int *flag) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + if (lmem == NULL) { + CVProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_LMEM_NULL); + return(CVSPILS_LMEM_NULL); + } + cvspils_mem = (CVSpilsMem) lmem; + + *flag = last_flag; + + return(CVSPILS_SUCCESS); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsGetReturnFlagName + * ----------------------------------------------------------------- + */ + +char *CVSpilsGetReturnFlagName(long int flag) +{ + char *name; + + name = (char *)malloc(30*sizeof(char)); + + switch(flag) { + case CVSPILS_SUCCESS: + sprintf(name,"CVSPILS_SUCCESS"); + break; + case CVSPILS_MEM_NULL: + sprintf(name,"CVSPILS_MEM_NULL"); + break; + case CVSPILS_LMEM_NULL: + sprintf(name,"CVSPILS_LMEM_NULL"); + break; + case CVSPILS_ILL_INPUT: + sprintf(name,"CVSPILS_ILL_INPUT"); + break; + case CVSPILS_MEM_FAIL: + sprintf(name,"CVSPILS_MEM_FAIL"); + break; + case CVSPILS_PMEM_NULL: + sprintf(name,"CVSPILS_PMEM_NULL"); + break; + default: + sprintf(name,"NONE"); + } + + return(name); +} + +/* + * ----------------------------------------------------------------- + * CVSPILS private functions + * ----------------------------------------------------------------- + */ + + +/* Additional readability Replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * CVSpilsAtimes + * ----------------------------------------------------------------- + * This routine generates the matrix-vector product z = Mv, where + * M = I - gamma*J. The product J*v is obtained by calling the jtimes + * routine. It is then scaled by -gamma and added to v to obtain M*v. + * The return value is the same as the value returned by jtimes -- + * 0 if successful, nonzero otherwise. + * ----------------------------------------------------------------- + */ + +int CVSpilsAtimes(void *cvode_mem, N_Vector v, N_Vector z) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int jtflag; + + cv_mem = (CVodeMem) cvode_mem; + cvspils_mem = (CVSpilsMem) lmem; + + jtflag = jtimes(v, z, tn, ycur, fcur, j_data, ytemp); + njtimes++; + if (jtflag != 0) return(jtflag); + + N_VLinearSum(ONE, v, -gamma, z, z); + + return(0); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsPSolve + * ----------------------------------------------------------------- + * This routine interfaces between the generic Sp***Solve routine + * (within the SPGMR, SPBCG, or SPTFQMR solver) and the + * user's psolve routine. It passes to psolve all required state + * information from cvode_mem. Its return value is the same as that + * returned by psolve. Note that the generic SP*** solver guarantees + * that CVSpilsPSolve will not be called in the case in which + * preconditioning is not done. This is the only case in which the + * user's psolve routine is allowed to be NULL. + * ----------------------------------------------------------------- + */ + +int CVSpilsPSolve(void *cvode_mem, N_Vector r, N_Vector z, int lr) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + int retval; + + cv_mem = (CVodeMem) cvode_mem; + cvspils_mem = (CVSpilsMem)lmem; + + /* This call is counted in nps within the CVSp***Solve routine */ + retval = psolve(tn, ycur, fcur, r, z, gamma, delta, lr, P_data, ytemp); + + return(retval); +} + +/* + * ----------------------------------------------------------------- + * CVSpilsDQJtimes + * ----------------------------------------------------------------- + * This routine generates a difference quotient approximation to + * the Jacobian times vector f_y(t,y) * v. The approximation is + * Jv = vnrm[f(y + v/vnrm) - f(y)], where vnrm = (WRMS norm of v) is + * input, i.e. the WRMS norm of v/vnrm is 1. + * ----------------------------------------------------------------- + */ + +int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *data, N_Vector work) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + realtype sig, siginv; + int iter, retval; + + /* data is cvode_mem */ + cv_mem = (CVodeMem) data; + cvspils_mem = (CVSpilsMem) lmem; + + /* Initialize perturbation to 1/||v|| */ + sig = ONE/N_VWrmsNorm(v, ewt); + + for (iter=0; iter 0) return(+1); + + /* Replace Jv by (Jv - fy)/sig */ + siginv = ONE/sig; + N_VLinearSum(siginv, Jv, -siginv, fy, Jv); + + return(0); +} diff --git a/dep/cvode-2.7.0/cvode/cvode_spils_impl.h b/dep/cvode-2.7.0/cvode/cvode_spils_impl.h new file mode 100644 index 00000000..be5491f0 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_spils_impl.h @@ -0,0 +1,142 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2010/12/01 22:19:48 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common implementation header file for the scaled, preconditioned + * linear solver modules. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSPILS_IMPL_H +#define _CVSPILS_IMPL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include "cvode_impl.h" + +/* Types of iterative linear solvers */ + +#define SPILS_SPGMR 1 +#define SPILS_SPBCG 2 +#define SPILS_SPTFQMR 3 + +/* + * ----------------------------------------------------------------- + * Types : CVSpilsMemRec, CVSpilsMem + * ----------------------------------------------------------------- + * The type CVSpilsMem is pointer to a CVSpilsMemRec. + * ----------------------------------------------------------------- + */ + +typedef struct CVSpilsMemRec { + + int s_type; /* type of scaled preconditioned iterative LS */ + + int s_pretype; /* type of preconditioning */ + int s_gstype; /* type of Gram-Schmidt orthogonalization */ + realtype s_sqrtN; /* sqrt(N) */ + realtype s_eplifac; /* eplifac = user specified or EPLIN_DEFAULT */ + realtype s_deltar; /* deltar = delt * tq4 */ + realtype s_delta; /* delta = deltar * sqrtN */ + int s_maxl; /* maxl = maximum dimension of the Krylov space */ + + long int s_nstlpre; /* value of nst at the last pset call */ + long int s_npe; /* npe = total number of pset calls */ + long int s_nli; /* nli = total number of linear iterations */ + long int s_nps; /* nps = total number of psolve calls */ + long int s_ncfl; /* ncfl = total number of convergence failures */ + long int s_njtimes; /* njtimes = total number of calls to jtimes */ + long int s_nfes; /* nfeSG = total number of calls to f for + difference quotient Jacobian-vector products */ + + N_Vector s_ytemp; /* temp vector passed to jtimes and psolve */ + N_Vector s_x; /* temp vector used by CVSpilsSolve */ + N_Vector s_ycur; /* CVODE current y vector in Newton Iteration */ + N_Vector s_fcur; /* fcur = f(tn, ycur) */ + + void* s_spils_mem; /* memory used by the generic solver */ + + /* Preconditioner computation + * (a) user-provided: + * - P_data == user_data + * - pfree == NULL (the user dealocates memory for user_data) + * (b) internal preconditioner module + * - P_data == cvode_mem + * - pfree == set by the prec. module and called in CVodeFree + */ + CVSpilsPrecSetupFn s_pset; + CVSpilsPrecSolveFn s_psolve; + void (*s_pfree)(CVodeMem cv_mem); + void *s_P_data; + + /* Jacobian times vector compuation + * (a) jtimes function provided by the user: + * - j_data == user_data + * - jtimesDQ == FALSE + * (b) internal jtimes + * - j_data == cvode_mem + * - jtimesDQ == TRUE + */ + booleantype s_jtimesDQ; + CVSpilsJacTimesVecFn s_jtimes; + void *s_j_data; + + long int s_last_flag; /* last error flag returned by any function */ + +} *CVSpilsMem; + +/* + * ----------------------------------------------------------------- + * Prototypes of internal functions + * ----------------------------------------------------------------- + */ + +/* Atimes and PSolve routines called by generic solver */ + +int CVSpilsAtimes(void *cv_mem, N_Vector v, N_Vector z); + +int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z, int lr); + +/* Difference quotient approximation for Jac times vector */ + +int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, void *data, + N_Vector work); + +/* + * ----------------------------------------------------------------- + * Error Messages + * ----------------------------------------------------------------- + */ + +#define MSGS_CVMEM_NULL "Integrator memory is NULL." +#define MSGS_MEM_FAIL "A memory request failed." +#define MSGS_BAD_NVECTOR "A required vector operation is not implemented." +#define MSGS_BAD_LSTYPE "Incompatible linear solver type." +#define MSGS_BAD_PRETYPE "Illegal value for pretype. Legal values are PREC_NONE, PREC_LEFT, PREC_RIGHT, and PREC_BOTH." +#define MSGS_PSOLVE_REQ "pretype != PREC_NONE, but PSOLVE = NULL is illegal." +#define MSGS_LMEM_NULL "Linear solver memory is NULL." +#define MSGS_BAD_GSTYPE "Illegal value for gstype. Legal values are MODIFIED_GS and CLASSICAL_GS." +#define MSGS_BAD_EPLIN "eplifac < 0 illegal." + +#define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner." +#define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner." +#define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner." + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/cvode_sptfqmr.c b/dep/cvode-2.7.0/cvode/cvode_sptfqmr.c new file mode 100644 index 00000000..bf842906 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/cvode_sptfqmr.c @@ -0,0 +1,459 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2011/03/23 22:27:43 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the CVSPTFQMR linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include "cvode_spils_impl.h" +#include "cvode_impl.h" + +#include +#include + +/* Other Constants */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* CVSPTFQMR linit, lsetup, lsolve, and lfree routines */ + +static int CVSptfqmrInit(CVodeMem cv_mem); + +static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3); + +static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow); + +static void CVSptfqmrFree(CVodeMem cv_mem); + + +/* Readability Replacements */ + +#define tq (cv_mem->cv_tq) +#define nst (cv_mem->cv_nst) +#define tn (cv_mem->cv_tn) +#define gamma (cv_mem->cv_gamma) +#define gammap (cv_mem->cv_gammap) +#define f (cv_mem->cv_f) +#define user_data (cv_mem->cv_user_data) +#define ewt (cv_mem->cv_ewt) +#define errfp (cv_mem->cv_errfp) +#define mnewt (cv_mem->cv_mnewt) +#define linit (cv_mem->cv_linit) +#define lsetup (cv_mem->cv_lsetup) +#define lsolve (cv_mem->cv_lsolve) +#define lfree (cv_mem->cv_lfree) +#define lmem (cv_mem->cv_lmem) +#define vec_tmpl (cv_mem->cv_tempv) +#define setupNonNull (cv_mem->cv_setupNonNull) + +#define sqrtN (cvspils_mem->s_sqrtN) +#define ytemp (cvspils_mem->s_ytemp) +#define x (cvspils_mem->s_x) +#define ycur (cvspils_mem->s_ycur) +#define fcur (cvspils_mem->s_fcur) +#define delta (cvspils_mem->s_delta) +#define deltar (cvspils_mem->s_deltar) +#define npe (cvspils_mem->s_npe) +#define nli (cvspils_mem->s_nli) +#define nps (cvspils_mem->s_nps) +#define ncfl (cvspils_mem->s_ncfl) +#define nstlpre (cvspils_mem->s_nstlpre) +#define njtimes (cvspils_mem->s_njtimes) +#define nfes (cvspils_mem->s_nfes) +#define spils_mem (cvspils_mem->s_spils_mem) + +#define jtimesDQ (cvspils_mem->s_jtimesDQ) +#define jtimes (cvspils_mem->s_jtimes) +#define j_data (cvspils_mem->s_j_data) + +#define last_flag (cvspils_mem->s_last_flag) + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmr + * ----------------------------------------------------------------- + * This routine initializes the memory record and sets various function + * fields specific to the Sptfqmr linear solver module. CVSptfqmr first + * calls the existing lfree routine if this is not NULL. It then sets + * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem) + * to be CVSptfqmrInit, CVSptfqmrSetup, CVSptfqmrSolve, and CVSptfqmrFree, + * respectively. It allocates memory for a structure of type + * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the + * address of this structure. It sets setupNonNull in (*cvode_mem), + * and sets various fields in the CVSpilsMemRec structure. + * Finally, CVSptfqmr allocates memory for ytemp and x, and calls + * SptfqmrMalloc to allocate memory for the Sptfqmr solver. + * ----------------------------------------------------------------- + */ + +int CVSptfqmr(void *cvode_mem, int pretype, int maxl) +{ + CVodeMem cv_mem; + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + int mxl; + + /* Return immediately if cvode_mem is NULL */ + if (cvode_mem == NULL) { + CVProcessError(NULL, CVSPILS_MEM_NULL, "CVSPTFQMR", "CVSptfqmr", MSGS_CVMEM_NULL); + return(CVSPILS_MEM_NULL); + } + cv_mem = (CVodeMem) cvode_mem; + + /* Check if N_VDotProd is present */ + if (vec_tmpl->ops->nvdotprod == NULL) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_NVECTOR); + return(CVSPILS_ILL_INPUT); + } + + if (lfree != NULL) lfree(cv_mem); + + /* Set four main function fields in cv_mem */ + linit = CVSptfqmrInit; + lsetup = CVSptfqmrSetup; + lsolve = CVSptfqmrSolve; + lfree = CVSptfqmrFree; + + /* Get memory for CVSpilsMemRec */ + cvspils_mem = NULL; + cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec)); + if (cvspils_mem == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + return(CVSPILS_MEM_FAIL); + } + + /* Set ILS type */ + cvspils_mem->s_type = SPILS_SPTFQMR; + + /* Set Sptfqmr parameters that have been passed in call sequence */ + cvspils_mem->s_pretype = pretype; + mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl; + + /* Set defaults for Jacobian-related fileds */ + jtimesDQ = TRUE; + jtimes = NULL; + j_data = NULL; + + /* Set defaults for preconditioner-related fields */ + cvspils_mem->s_pset = NULL; + cvspils_mem->s_psolve = NULL; + cvspils_mem->s_pfree = NULL; + cvspils_mem->s_P_data = cv_mem->cv_user_data; + + /* Set default values for the rest of the Sptfqmr parameters */ + cvspils_mem->s_eplifac = CVSPILS_EPLIN; + + cvspils_mem->s_last_flag = CVSPILS_SUCCESS; + + setupNonNull = FALSE; + + /* Check for legal pretype */ + if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) { + CVProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_PRETYPE); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_ILL_INPUT); + } + + /* Allocate memory for ytemp and x */ + + ytemp = N_VClone(vec_tmpl); + if (ytemp == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + x = N_VClone(vec_tmpl); + if (x == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Compute sqrtN from a dot product */ + N_VConst(ONE, ytemp); + sqrtN = RSqrt(N_VDotProd(ytemp, ytemp)); + + /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */ + sptfqmr_mem = NULL; + sptfqmr_mem = SptfqmrMalloc(mxl, vec_tmpl); + if (sptfqmr_mem == NULL) { + CVProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL); + N_VDestroy(ytemp); + N_VDestroy(x); + free(cvspils_mem); cvspils_mem = NULL; + return(CVSPILS_MEM_FAIL); + } + + /* Attach SPTFQMR memory to spils memory structure */ + spils_mem = (void *) sptfqmr_mem; + + /* Attach linear solver memory to integrator memory */ + lmem = cvspils_mem; + + return(CVSPILS_SUCCESS); +} + +/* Additional readability replacements */ + +#define pretype (cvspils_mem->s_pretype) +#define eplifac (cvspils_mem->s_eplifac) +#define maxl (cvspils_mem->s_maxl) +#define psolve (cvspils_mem->s_psolve) +#define pset (cvspils_mem->s_pset) +#define P_data (cvspils_mem->s_P_data) + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrInit + * ----------------------------------------------------------------- + * This routine does remaining initializations specific to the Sptfqmr + * linear solver. + * ----------------------------------------------------------------- + */ + +static int CVSptfqmrInit(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + + cvspils_mem = (CVSpilsMem) lmem; + sptfqmr_mem = (SptfqmrMem) spils_mem; + + /* Initialize counters */ + npe = nli = nps = ncfl = nstlpre = 0; + njtimes = nfes = 0; + + /* Check for legal combination pretype - psolve */ + if ((pretype != PREC_NONE) && (psolve == NULL)) { + CVProcessError(cv_mem, -1, "CVSPTFQMR", "CVSptfqmrInit", MSGS_PSOLVE_REQ); + last_flag = CVSPILS_ILL_INPUT; + return(-1); + } + + /* Set setupNonNull = TRUE iff there is preconditioning + (pretype != PREC_NONE) and there is a preconditioning + setup phase (pset != NULL) */ + setupNonNull = (pretype != PREC_NONE) && (pset != NULL); + + /* Set Jacobian-related fields, based on jtimesDQ */ + if (jtimesDQ) { + jtimes = CVSpilsDQJtimes; + j_data = cv_mem; + } else { + j_data = user_data; + } + + /* Set maxl in the SPTFQMR memory in case it was changed by the user */ + sptfqmr_mem->l_max = maxl; + + last_flag = CVSPILS_SUCCESS; + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrSetup + * ----------------------------------------------------------------- + * This routine does the setup operations for the Sptfqmr linear solver. + * It makes a decision as to whether or not to signal for reevaluation + * of Jacobian data in the pset routine, based on various state + * variables, then it calls pset. If we signal for reevaluation, + * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output. + * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre. + * ----------------------------------------------------------------- + */ + +static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, + N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1, + N_Vector vtemp2, N_Vector vtemp3) +{ + booleantype jbad, jok; + realtype dgamma; + int retval; + CVSpilsMem cvspils_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */ + dgamma = ABS((gamma/gammap) - ONE); + jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) || + ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) || + (convfail == CV_FAIL_OTHER); + *jcurPtr = jbad; + jok = !jbad; + + /* Call pset routine and possibly reset jcur */ + retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, + vtemp1, vtemp2, vtemp3); + if (retval < 0) { + CVProcessError(cv_mem, SPTFQMR_PSET_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSetup", MSGS_PSET_FAILED); + last_flag = SPTFQMR_PSET_FAIL_UNREC; + } + if (retval > 0) { + last_flag = SPTFQMR_PSET_FAIL_REC; + } + + if (jbad) *jcurPtr = TRUE; + + /* If jcur = TRUE, increment npe and save nst value */ + if (*jcurPtr) { + npe++; + nstlpre = nst; + } + + last_flag = SPTFQMR_SUCCESS; + + /* Return the same value that pset returned */ + return(retval); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrSolve + * ----------------------------------------------------------------- + * This routine handles the call to the generic solver SptfqmrSolve + * for the solution of the linear system Ax = b with the SPTFQMR method. + * The solution x is returned in the vector b. + * + * If the WRMS norm of b is small, we return x = b (if this is the first + * Newton iteration) or x = 0 (if a later Newton iteration). + * + * Otherwise, we set the tolerance parameter and initial guess (x = 0), + * call SptfqmrSolve, and copy the solution x into b. The x-scaling and + * b-scaling arrays are both equal to weight. + * + * The counters nli, nps, and ncfl are incremented, and the return value + * is set according to the success of SptfqmrSolve. The success flag is + * returned if SptfqmrSolve converged, or if this is the first Newton + * iteration and the residual norm was reduced below its initial value. + * ----------------------------------------------------------------- + */ + +static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight, + N_Vector ynow, N_Vector fnow) +{ + realtype bnorm, res_norm; + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + int nli_inc, nps_inc, retval; + + cvspils_mem = (CVSpilsMem) lmem; + + sptfqmr_mem = (SptfqmrMem) spils_mem; + + /* Test norm(b); if small, return x = 0 or x = b */ + deltar = eplifac * tq[4]; + + bnorm = N_VWrmsNorm(b, weight); + if (bnorm <= deltar) { + if (mnewt > 0) N_VConst(ZERO, b); + return(0); + } + + /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */ + ycur = ynow; + fcur = fnow; + + /* Set inputs delta and initial guess x = 0 to SptfqmrSolve */ + delta = deltar * sqrtN; + N_VConst(ZERO, x); + + /* Call SptfqmrSolve and copy x to b */ + retval = SptfqmrSolve(sptfqmr_mem, cv_mem, x, b, pretype, delta, + cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve, + &res_norm, &nli_inc, &nps_inc); + + N_VScale(ONE, x, b); + + /* Increment counters nli, nps, and ncfl */ + nli += nli_inc; + nps += nps_inc; + if (retval != SPTFQMR_SUCCESS) ncfl++; + + /* Interpret return value from SpgmrSolve */ + + last_flag = retval; + + switch(retval) { + + case SPTFQMR_SUCCESS: + return(0); + break; + case SPTFQMR_RES_REDUCED: + if (mnewt == 0) return(0); + else return(1); + break; + case SPTFQMR_CONV_FAIL: + return(1); + break; + case SPTFQMR_PSOLVE_FAIL_REC: + return(1); + break; + case SPTFQMR_ATIMES_FAIL_REC: + return(1); + break; + case SPTFQMR_MEM_NULL: + return(-1); + break; + case SPTFQMR_ATIMES_FAIL_UNREC: + CVProcessError(cv_mem, SPTFQMR_ATIMES_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_JTIMES_FAILED); + return(-1); + break; + case SPTFQMR_PSOLVE_FAIL_UNREC: + CVProcessError(cv_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_PSOLVE_FAILED); + return(-1); + break; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmrFree + * ----------------------------------------------------------------- + * This routine frees memory specific to the Sptfqmr linear solver. + * ----------------------------------------------------------------- + */ + +static void CVSptfqmrFree(CVodeMem cv_mem) +{ + CVSpilsMem cvspils_mem; + SptfqmrMem sptfqmr_mem; + + cvspils_mem = (CVSpilsMem) lmem; + + N_VDestroy(ytemp); + N_VDestroy(x); + + sptfqmr_mem = (SptfqmrMem) spils_mem; + SptfqmrFree(sptfqmr_mem); + + if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem); + + free(cvspils_mem); + cv_mem->cv_lmem = NULL; + + return; +} + diff --git a/dep/cvode-2.7.0/cvode/fcmix/CMakeLists.txt b/dep/cvode-2.7.0/cvode/fcmix/CMakeLists.txt new file mode 100644 index 00000000..0c19eaa1 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/CMakeLists.txt @@ -0,0 +1,45 @@ +# CMakeLists.txt file for the FCVODE library + +# Add variable fcvode_SOURCES with the sources for the FCVODE library +SET(fcvode_SOURCES + fcvband.c + fcvbbd.c + fcvbp.c + fcvdense.c + fcvewt.c + fcvjtimes.c + fcvode.c + fcvpreco.c + fcvroot.c + ) + +IF(LAPACK_FOUND) + SET(fcvode_BL_SOURCES fcvlapack.c fcvlapband.c fcvlapdense.c) +ELSE(LAPACK_FOUND) + SET(fcvode_BL_SOURCES "") +ENDIF(LAPACK_FOUND) + +# Add source directories to include directories for access to +# implementation only header files (both for fcvode and cvode) +INCLUDE_DIRECTORIES(.) +INCLUDE_DIRECTORIES(..) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Only build STATIC libraries (we cannot build shared libraries +# for the FCMIX interfaces due to unresolved symbol errors +# coming from inexistent user-provided functions) + +# Add the build target for the FCVODE library +ADD_LIBRARY(sundials_fcvode_static STATIC ${fcvode_SOURCES} ${fcvode_BL_SOURCES}) + +# Set the library name and make sure it is not deleted +SET_TARGET_PROPERTIES(sundials_fcvode_static + PROPERTIES OUTPUT_NAME sundials_fcvode CLEAN_DIRECT_OUTPUT 1) + +# Install the FCVODE library +INSTALL(TARGETS sundials_fcvode_static DESTINATION lib) + +# +MESSAGE(STATUS "Added CVODE FCMIX module") diff --git a/dep/cvode-2.7.0/cvode/fcmix/Makefile.in b/dep/cvode-2.7.0/cvode/fcmix/Makefile.in new file mode 100644 index 00000000..9dec9a61 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/Makefile.in @@ -0,0 +1,125 @@ +# ----------------------------------------------------------------- +# $Revision: 1.9 $ +# $Date: 2009/03/25 23:10:50 $ +# ----------------------------------------------------------------- +# Programmer(s): Radu Serban and Aaron Collier @ LLNL +# ----------------------------------------------------------------- +# Copyright (c) 2002, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# ----------------------------------------------------------------- +# Makefile for FCVODE module +# +# @configure_input@ +# ----------------------------------------------------------------- + +SHELL = @SHELL@ + +srcdir = @srcdir@ +builddir = @builddir@ +abs_builddir = @abs_builddir@ +top_builddir = @top_builddir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ + +INSTALL = @INSTALL@ +INSTALL_LIB = @INSTALL_PROGRAM@ +INSTALL_HEADER = @INSTALL_DATA@ + +LIBTOOL = @LIBTOOL@ +LIBTOOL_DEPS = @LIBTOOL_DEPS@ + +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +LAPACK_ENABLED = @LAPACK_ENABLED@ + +top_srcdir = $(srcdir)/../../.. + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/cvode -I$(top_builddir)/include + +LIB_REVISION = 0:1:0 + +FCVODE_LIB = libsundials_fcvode.la + +FCVODE_SRC_FILES = fcvode.c fcvband.c fcvdense.c fcvjtimes.c fcvpreco.c fcvbbd.c fcvbp.c fcvroot.c fcvewt.c +FCVODE_BL_SRC_FILES = fcvlapack.c fcvlapband.c fcvlapdense.c + +FCVODE_OBJ_FILES = $(FCVODE_SRC_FILES:.c=.o) +FCVODE_BL_OBJ_FILES = $(FCVODE_BL_SRC_FILES:.c=.o) + +FCVODE_LIB_FILES = $(FCVODE_SRC_FILES:.c=.lo) +FCVODE_BL_LIB_FILES = $(FCVODE_BL_SRC_FILES:.c=.lo) + +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs + +# ---------------------------------------------------------------------------------------------------------------------- + +all: $(FCVODE_LIB) + +$(FCVODE_LIB): $(FCVODE_LIB_FILES) + @if test "X${LAPACK_ENABLED}" = "Xyes"; then \ + make lib_with_bl; \ + else \ + make lib_without_bl; \ + fi + +lib_without_bl: $(FCVODE_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FCVODE_LIB) $(FCVODE_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION) + +lib_with_bl: $(FCVODE_LIB_FILES) $(FCVODE_BL_LIB_FILES) + $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $(FCVODE_LIB) $(FCVODE_LIB_FILES) $(FCVODE_BL_LIB_FILES) -rpath $(libdir) $(LDFLAGS) $(LIBS) -static -version-info $(LIB_REVISION) + +install: $(FCVODE_LIB) + $(mkinstalldirs) $(libdir) + $(LIBTOOL) --mode=install $(INSTALL_LIB) $(FCVODE_LIB) $(libdir) + +uninstall: + $(LIBTOOL) --mode=uninstall rm -f $(libdir)/$(FCVODE_LIB) + +clean: + $(LIBTOOL) --mode=clean rm -f $(FCVODE_LIB) + rm -f $(FCVODE_LIB_FILES) + rm -f $(FCVODE_BL_LIB_FILES) + rm -f $(FCVODE_OBJ_FILES) + rm -f $(FCVODE_BL_OBJ_FILES) + +distclean: clean + rm -f Makefile + +fcvode.lo: $(srcdir)/fcvode.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvode.c +fcvewt.lo: $(srcdir)/fcvewt.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvewt.c +fcvband.lo: $(srcdir)/fcvband.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvband.c +fcvdense.lo: $(srcdir)/fcvdense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvdense.c +fcvlapack.lo: $(srcdir)/fcvlapack.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvlapack.c +fcvlapband.lo: $(srcdir)/fcvlapband.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvlapband.c +fcvlapdense.lo: $(srcdir)/fcvlapdense.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvlapdense.c +fcvjtimes.lo: $(srcdir)/fcvjtimes.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvjtimes.c +fcvpreco.lo: $(srcdir)/fcvpreco.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvpreco.c +fcvbbd.lo: $(srcdir)/fcvbbd.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvbbd.c +fcvbp.lo: $(srcdir)/fcvbp.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvbp.c +fcvroot.lo: $(srcdir)/fcvroot.c + $(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) -c $(srcdir)/fcvroot.c + +libtool: $(top_builddir)/$(LIBTOOL_DEPS) + @cd ${top_builddir} ; \ + ${SHELL} ./config.status --recheck ; \ + cd ${abs_builddir} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvband.c b/dep/cvode-2.7.0/cvode/fcmix/fcvband.c new file mode 100644 index 00000000..e7d75f01 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvband.c @@ -0,0 +1,97 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:27:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for CVODE/CVBAND, for the case of + * a user-supplied Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/******************************************************************************/ + +/* Prototype of the Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FCV_BJAC(long int*, long int*, long int*, long int*, /* N,MU,ML,EBAND */ + realtype*, realtype*, realtype*, /* T, Y, FY */ + realtype*, /* BJAC */ + realtype*, /* H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, realtype*, realtype*, /* V1, V2, V3 */ + int*); /* IER */ +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_BANDSETJAC(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag == 0) { + *ier = CVDlsSetBandJacFn(CV_cvodemem, NULL); + } else { + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVDlsSetBandJacFn(CV_cvodemem, FCVBandJac); + } +} + +/***************************************************************************/ + +/* C function CVBandJac interfaces between CVODE and a Fortran subroutine + FCVBJAC for solution of a linear system with band Jacobian approximation. + Addresses of arguments are passed to FCVBJAC, using the macro + BAND_COL from BAND and the routine N_VGetArrayPointer from NVECTOR. + The address passed for J is that of the element in column 0 with row + index -mupper. An extended bandwith equal to (J->smu) + mlower + 1 is + passed as the column dimension of the corresponding array. + Auxiliary data is assumed to be communicated by Common. */ + +int FCVBandJac(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + int ier; + realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data; + realtype h; + long int eband; + FCVUserData CV_userdata; + + CVodeGetLastStep(CV_cvodemem, &h); + + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + eband = (J->s_mu) + mlower + 1; + jacdata = BAND_COL(J,0) - mupper; + + CV_userdata = (FCVUserData) user_data; + + FCV_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata, jacdata, &h, + CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier); + + return(ier); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvbbd.c b/dep/cvode-2.7.0/cvode/fcmix/fcvbbd.c new file mode 100644 index 00000000..30400daf --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvbbd.c @@ -0,0 +1,141 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:27:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This module contains the routines necessary to interface with the + * CVBBDPRE module and user-supplied Fortran routines. + * The routines here call the generically named routines and provide + * a standard interface to the C code of the CVBBDPRE package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual function names, prototypes, global vars.*/ +#include "fcvbbd.h" /* prototypes of interfaces to CVBBDPRE */ + +#include /* prototypes of CVBBDPRE functions and macros */ +#include /* prototypes of CVSPTFQMR interface routines */ +#include /* prototypes of CVSPBCG interface routines */ +#include /* prototypes of CVSPGMR interface routines */ + +/***************************************************************************/ + +/* Prototypes of the Fortran routines */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FCV_GLOCFN(long int*, /* NLOC */ + realtype*, realtype*, realtype*, /* T, YLOC, GLOC */ + long int*, realtype*, /* IPAR, RPAR */ + int *ier); /* IER */ + + extern void FCV_COMMFN(long int*, /* NLOC */ + realtype*, realtype*, /* T, Y */ + long int*, realtype*, /* IPAR, RPAR */ + int *ier); /* IER */ + +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, long int *mu, long int *ml, + realtype* dqrely, int *ier) +{ + + /* + First call CVBBDPrecInit to initialize CVBBDPRE module: + Nloc is the local vector size + mudq,mldq are the half-bandwidths for computing preconditioner blocks + mu, ml are the half-bandwidths of the retained preconditioner blocks + dqrely is the difference quotient relative increment factor + FCVgloc is a pointer to the CVLocalFn function + FCVcfn is a pointer to the CVCommFn function + */ + + *ier = CVBBDPrecInit(CV_cvodemem, *Nloc, *mudq, *mldq, *mu, *ml, + *dqrely, FCVgloc, FCVcfn); + + return; +} + +/***************************************************************************/ + +void FCV_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq, realtype* dqrely, int *ier) +{ + /* + First call CVReInitBBD to re-initialize CVBBDPRE module: + mudq,mldq are the half-bandwidths for computing preconditioner blocks + dqrely is the difference quotient relative increment factor + FCVgloc is a pointer to the CVLocalFn function + FCVcfn is a pointer to the CVCommFn function + */ + + *ier = CVBBDPrecReInit(CV_cvodemem, *mudq, *mldq, *dqrely); +} + +/***************************************************************************/ + +/* C function FCVgloc to interface between CVBBDPRE module and a Fortran + subroutine FCVLOCFN. */ + +int FCVgloc(long int Nloc, realtype t, N_Vector yloc, N_Vector gloc, void *user_data) +{ + int ier; + realtype *yloc_data, *gloc_data; + FCVUserData CV_userdata; + + yloc_data = N_VGetArrayPointer(yloc); + gloc_data = N_VGetArrayPointer(gloc); + + CV_userdata = (FCVUserData) user_data; + + FCV_GLOCFN(&Nloc, &t, yloc_data, gloc_data, + CV_userdata->ipar, CV_userdata->rpar, + &ier); + return(ier); +} + +/***************************************************************************/ + +/* C function FCVcfn to interface between CVBBDPRE module and a Fortran + subroutine FCVCOMMF. */ + +int FCVcfn(long int Nloc, realtype t, N_Vector y, void *user_data) +{ + int ier; + realtype *yloc; + FCVUserData CV_userdata; + + yloc = N_VGetArrayPointer(y); + + CV_userdata = (FCVUserData) user_data; + + FCV_COMMFN(&Nloc, &t, yloc, CV_userdata->ipar, CV_userdata->rpar, &ier); + + return(ier); +} + +/***************************************************************************/ + +/* C function FCVBBDOPT to access optional outputs from CVBBD_Data */ + +void FCV_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd) +{ + CVBBDPrecGetWorkSpace(CV_cvodemem, lenrwbbd, leniwbbd); + CVBBDPrecGetNumGfnEvals(CV_cvodemem, ngebbd); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvbbd.h b/dep/cvode-2.7.0/cvode/fcmix/fcvbbd.h new file mode 100644 index 00000000..94011410 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvbbd.h @@ -0,0 +1,331 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2010/12/15 19:40:08 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the Fortran interface include file for the BBD + * preconditioner (CVBBDPRE) + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================== + * + * FCVBBD Interface Package + * + * The FCVBBD Interface Package is a package of C functions which, + * together with the FCVODE Interface Package, support the use of the + * CVODE solver (parallel MPI version) with the CVBBDPRE preconditioner module, + * for the solution of ODE systems in a mixed Fortran/C setting. The + * combination of CVODE and CVBBDPRE solves systems dy/dt = f(t,y) with + * the SPGMR (scaled preconditioned GMRES), SPTFQMR (scaled preconditioned TFQMR), + * or SPBCG (scaled preconditioned Bi-CGSTAB) method for the linear systems that + * arise, and with a preconditioner that is block-diagonal with banded blocks. + * While CVODE and CVBBDPRE are written in C, it is assumed here that the user's + * calling program and user-supplied problem-defining routines are written in + * Fortran. + * + * The user-callable functions in this package, with the corresponding + * CVODE and CVBBDPRE functions, are as follows: + * FCVBBDININT interfaces to CVBBDPrecInit + * FCVBBDSPTFQMR interfaces to CVBBDSptfqmr + * FCVBBDSPBCG interfaces to CVBBDSpbcg + * FCVBBDPSGMR interfaces to CVBBDSpgmr + * FCVBBDREINIT interfaces to CVBBDPrecReInit + * FCVBBDOPT accesses optional outputs + * + * In addition to the Fortran right-hand side function FCVFUN, the + * user-supplied functions used by this package, are listed below, + * each with the corresponding interface function which calls it (and its + * type within CVBBDPRE or CVODE): + * FCVLOCFN is called by the interface function FCVgloc of type CVLocalFn + * FCVCOMMF is called by the interface function FCVcfn of type CVCommFn + * FCVJTIMES (optional) is called by the interface function FCVJtimes of + * type CVSpilsJtimesFn + * (The names of all user-supplied routines here are fixed, in order to + * maximize portability for the resulting mixed-language program.) + * + * Important note on portability. + * In this package, the names of the interface functions, and the names of + * the Fortran user routines called by them, appear as dummy names + * which are mapped to actual values by a series of definitions in the + * header file fcvbbd.h. + * + * ============================================================================== + * + * Usage of the FCVODE/FCVBBD Interface Packages + * + * The usage of the combined interface packages FCVODE and FCVBBD requires + * calls to seven to twelve interface functions, and three or four user-supplied + * routines which define the problem to be solved and indirectly define + * the preconditioner. These function calls and user routines are + * summarized separately below. + * + * Some details are omitted, and the user is referred to the CVODE user document + * for more complete information. + * + * (1) User-supplied right-hand side routine: FCVFUN + * The user must in all cases supply the following Fortran routine + * SUBROUTINE FCVFUN (T, Y, YDOT, IPAR, RPAR, IER) + * DIMENSION Y(*), YDOT(*), IPAR(*), RPAR(*) + * It must set the YDOT array to f(t,y), the right-hand side of the ODE + * system, as function of T = t and the array Y = y. Here Y and YDOT + * are distributed vectors. + * + * (2) User-supplied routines to define preconditoner: FCVLOCFN and FCVCOMMF + * + * The routines in the CVBBDPRE module provide a preconditioner matrix + * for CVODE that is block-diagonal with banded blocks. The blocking + * corresponds to the distribution of the dependent variable vector y + * among the processors. Each preconditioner block is generated from the + * Jacobian of the local part (on the current processor) of a given + * function g(t,y) approximating f(t,y). The blocks are generated by a + * difference quotient scheme on each processor independently, utilizing + * an assumed banded structure with given half-bandwidths. A separate + * pair of half-bandwidths defines the band matrix retained. + * + * (2.1) Local approximate function FCVLOCFN. + * The user must supply a subroutine of the form + * SUBROUTINE FCVLOCFN (NLOC, T, YLOC, GLOC, IPAR, RPAR, IER) + * DIMENSION YLOC(*), GLOC(*), IPAR(*), RPAR(*) + * to compute the function g(t,y) which approximates the right-hand side + * function f(t,y). This function is to be computed locally, i.e. without + * interprocess communication. (The case where g is mathematically + * identical to f is allowed.) It takes as input the local vector length + * NLOC, the independent variable value T = t, and the local realtype + * dependent variable array YLOC. It is to compute the local part of + * g(t,y) and store this in the realtype array GLOC. + * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred, + * and IER < 0 if an unrecoverable error ocurred. + * + * (2.2) Communication function FCVCOMMF. + * The user must also supply a subroutine of the form + * SUBROUTINE FCVCOMMF (NLOC, T, YLOC, IPAR, RPAR, IER) + * DIMENSION YLOC(*), IPAR(*), RPAR(*) + * which is to perform all interprocess communication necessary to + * evaluate the approximate right-hand side function g described above. + * This function takes as input the local vector length NLOC, the + * independent variable value T = t, and the local real dependent + * variable array YLOC. It is expected to save communicated data in + * work space defined by the user, and made available to CVLOCFN. + * Each call to the FCVCOMMF is preceded by a call to FCVFUN with the same + * (t,y) arguments. Thus FCVCOMMF can omit any communications done by + * FCVFUN if relevant to the evaluation of g. + * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred, + * and IER < 0 if an unrecoverable error ocurred. + * + * (3) Optional user-supplied Jacobian-vector product routine: FCVJTIMES + * As an option, the user may supply a routine that computes the product + * of the system Jacobian J = df/dy and a given vector v. If supplied, it + * must have the following form: + * SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, EWT, IPAR, RPAR, WORK, IER) + * DIMENSION V(*), FJV(*), Y(*), FY(*), EWT(*), IPAR(*), RPAR(*), WORK(*) + * Typically this routine will use only NEQ, T, Y, V, and FJV. It must + * compute the product vector Jv, where the vector v is stored in V, and store + * the product in FJV. On return, set IER = 0 if FCVJTIMES was successful, + * and nonzero otherwise. + * + * (4) Initialization: FNVINITP, FCVMALLOC, FCVBBDINIT. + * + * (4.1) To initialize the parallel vector specification, the user must make + * the following call: + * CALL FNVINITP (NLOCAL, NGLOBAL, IER) + * The arguments are: + * NLOCAL = local size of vectors on this processor + * NGLOBAL = the system size, and the global size of vectors (the sum + * of all values of NLOCAL) + * IER = return completion flag. Values are 0 = success, -1 = failure. + * + * Note: If MPI was initialized by the user, the communicator must be + * set to MPI_COMM_WORLD. If not, this routine initializes MPI and sets + * the communicator equal to MPI_COMM_WORLD. + * + * (4.2) To set various problem and solution parameters and allocate + * internal memory for CVODE, make the following call: + * CALL FCVMALLOC(T0, Y0, METH, ITMETH, IATOL, RTOL, ATOL, + * 1 IOUT, ROUT, IPAR, RPAR, IER) + * The arguments are: + * T0 = initial value of t + * Y0 = array of initial conditions + * METH = basic integration method: 1 = Adams (nonstiff), 2 = BDF (stiff) + * ITMETH = nonlinear iteration method: 1 = functional iteration, 2 = Newton iter. + * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array + * RTOL = relative tolerance (scalar) + * ATOL = absolute tolerance (scalar or array) + * IOUT = array of length 21 for integer optional outputs + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * ROUT = array of length 6 for real optional outputs + * IPAR = array with user integer data + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * RPAR = array with user real data + * IER = return completion flag. Values are 0 = success, and -1 = failure. + * See printed message for details in case of failure. + * + * (4.3) Attach one of the 3 SPILS linear solvers. Make one of the + * following calls (see fcvode.h) for more details. + * CALL FCVSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER) + * CALL FCVSPBCG(IPRETYPE, MAXL, DELT, IER) + * CALL FCVSPTFQMR(IPRETYPE, MAXL, DELT, IER) + * + * (4.4) To allocate memory and initialize data associated with the CVBBDPRE + * preconditioner, make the following call: + * CALL FCVBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER) + * + * The arguments are: + * NLOCAL = local size of vectors on this processor + * MUDQ,MLDQ = upper and lower half-bandwidths to be used in the computation + * of the local Jacobian blocks by difference quotients. + * These may be smaller than the true half-bandwidths of the + * Jacobian of the local block of g, when smaller values may + * provide greater efficiency. + * MU, ML = upper and lower half-bandwidths of the band matrix that + * is retained as an approximation of the local Jacobian block. + * These may be smaller than MUDQ and MLDQ. + * DQRELY = relative increment factor in y for difference quotients + * (optional). 0.0 indicates the default, sqrt(unit roundoff). + * IER = return completion flag: IER=0: success, IER<0: an error occurred + * + * CALL FCVBBDSPTFQMR(IPRETYPE, MAXL, DELT, IER) + * (4.5) To specify whether the Krylov linear solver (GMRES, Bi-CGSTAB, or TFQMR) + * should use the supplied FCVJTIMES or the internal finite difference approximation, + * make the call + * CALL FCVSPILSSETJAC(FLAG, IER) + * where FLAG=0 for finite differences approximation or + * FLAG=1 to use the supplied routine FCVJTIMES + * + * (5) Re-initialization: FCVREINIT, FCVBBDREINIT + * If a sequence of problems of the same size is being solved using the SPGMR, SPBCG, + * SPTFQMR linear solver in combination with the CVBBDPRE preconditioner, then the + * CVODE package can be reinitialized for the second and subsequent problems + * so as to avoid further memory allocation. First, in place of the call + * to FCVMALLOC, make the following call: + * CALL FCVREINIT(T0, Y0, IATOL, RTOL, ATOL, IER) + * The arguments have the same names and meanings as those of FCVMALLOC, except + * that METH and ITMETH have been omitted from the argument list (being unchanged + * for the new problem). FCVREINIT performs the same initializations as + * FCVMALLOC, but does no memory allocation, using instead the existing + * internal memory created by the previous FCVMALLOC call. + * + * If there is a change in any of the linear solver arguments, then + * a call to FCVSPGMR, FCVSPBCG, or FCVSPTFQMR must also be made; + * in this case the linear solver memory is reallocated. + * + * Following the call to FCVREINIT, a call to FCVBBDINIT may or may not be needed. + * If the input arguments are the same, no FCVBBDINIT call is needed. + * If there is a change in input arguments, then make the call + * CALL FCVBBDREINIT(NLOCAL, MUDQ, MLDQ, DQRELY, IER) + * This reinitializes the BBD preconditioner, but without reallocating its memory. + * The arguments of the have the same names and meanings as FCVBBDINIT. + * If the value of MU or ML is being changed, then a call to FCVBBDINIT must + * be made. + * + * (6) The integrator: FCVODE + * Carrying out the integration is accomplished by making calls as follows: + * CALL FCVODE (TOUT, T, Y, ITASK, IER) + * The arguments are: + * TOUT = next value of t at which a solution is desired (input) + * T = value of t reached by the solver on output + * Y = array containing the computed solution on output + * ITASK = task indicator: + * 1 = normal mode (overshoot TOUT and interpolate) + * 2 = one-step mode (return after each internal step taken) + * 3 = normal mode with TSTOP check + * 4 = one-step mode with TSTOP check + * IER = completion flag: 0 = success, 1 = TSTOP return, 2 = root return, + * negative values are various failure modes (see CVODE User Guide). + * The current values of the optional outputs are available in IOUT and ROUT. + * + * (7) Optional outputs: FCVBBDOPT + * Optional outputs specific to the SP* solver are LRW, LIW, LFLG, NFELS, NJTV, + * NPE, NPS, NLI, NCFL, stored in IOUT(13)...IOUT(21). + * To obtain the optional outputs associated with the CVBBDPRE module, make + * the following call: + * CALL FCVBBDOPT (LENRWBBD, LENIWBBD, NGEBBD) + * The arguments returned are: + * LENRWBBD = length of real preconditioner work space, in realtype words. + * This size is local to the current processor. + * LENIWBBD = length of integer preconditioner work space, in integer words. + * This size is local to the current processor. + * NGEBBD = number of g(t,y) evaluations (calls to CVLOCFN) so far. + * + * (8) Computing solution derivatives: FCVDKY + * To obtain a derivative of the solution (optionally), of order up to + * the current method order, make the following call: + * CALL FCVDKY (T, K, DKY) + * The arguments are: + * T = value of t at which solution derivative is desired + * K = derivative order (0 .le. K .le. QU) + * DKY = array containing computed K-th derivative of y on return + * + * (9) Memory freeing: FCVFREE + * To the free the internal memory created by the calls to FNVINITP, + * FCVMALLOC, and FCVBBDINIT, make the following call: + * CALL FCVFREE + * + * ============================================================================== + */ + +#ifndef _FCVBBD_H +#define _FCVBBD_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* header files */ + +#include /* definition of type N_Vector */ +#include /* definition of type realtype */ + +/* Definitions of interface function names */ + +#if defined(SUNDIALS_F77_FUNC) + +#define FCV_BBDINIT SUNDIALS_F77_FUNC(fcvbbdinit, FCVBBDINIT) +#define FCV_BBDSPTFQMR SUNDIALS_F77_FUNC(fcvbbdsptfqmr, FCVBBDSPTFQMR) +#define FCV_BBDSPBCG SUNDIALS_F77_FUNC(fcvbbdspbcg, FCVBBDSPBCG) +#define FCV_BBDSPGMR SUNDIALS_F77_FUNC(fcvbbdspgmr, FCVBBDSPGMR) +#define FCV_BBDREINIT SUNDIALS_F77_FUNC(fcvbbdreinit, FCVBBDREINIT) +#define FCV_BBDOPT SUNDIALS_F77_FUNC(fcvbbdopt, FCVBBDOPT) +#define FCV_GLOCFN SUNDIALS_F77_FUNC(fcvglocfn, FCVGLOCFN) +#define FCV_COMMFN SUNDIALS_F77_FUNC(fcvcommfn, FCVCOMMFN) + +#else + +#define FCV_BBDINIT fcvbbdinit_ +#define FCV_BBDSPTFQMR fcvbbdsptfqmr_ +#define FCV_BBDSPBCG fcvbbdspbcg_ +#define FCV_BBDSPGMR fcvbbdspgmr_ +#define FCV_BBDREINIT fcvbbdreinit_ +#define FCV_BBDOPT fcvbbdopt_ +#define FCV_GLOCFN fcvglocfn_ +#define FCV_COMMFN fcvcommfn_ + +#endif + +/* Prototypes of exported functions */ + +void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, long int *mu, long int *ml, + realtype* dqrely, int *ier); +void FCV_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq, realtype* dqrely, int *ier); +void FCV_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd); + +/* Prototypes: Functions Called by the CVBBDPRE Module */ + +int FCVgloc(long int Nloc, realtype t, N_Vector yloc, N_Vector gloc, void *user_data); + +int FCVcfn(long int Nloc, realtype t, N_Vector y, void *user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvbp.c b/dep/cvode-2.7.0/cvode/fcmix/fcvbp.c new file mode 100644 index 00000000..4c6b1108 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvbp.c @@ -0,0 +1,54 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2010/09/30 20:51:36 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This module contains the routines necessary to interface with the + * CVBANDPRE module and user-supplied Fortran routines. + * The routines here call the generically named routines and provide + * a standard interface to the C code of the CVBANDPRE package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "fcvbp.h" /* prototypes of interfaces to CVBANDPRE */ + +#include /* prototypes of CVBANDPRE functions and macros */ +#include /* prototypes of CVSPTFQMR interface routines */ +#include /* prototypes of CVSPBCG interface routines */ +#include /* prototypes of CVSPGMR interface routines */ + +/***************************************************************************/ + +void FCV_BPINIT(long int *N, long int *mu, long int *ml, int *ier) +{ + /* + Call CVBandPrecInit to initialize the CVBANDPRE module: + N is the vector size + mu, ml are the half-bandwidths of the retained preconditioner blocks + */ + + *ier = CVBandPrecInit(CV_cvodemem, *N, *mu, *ml); + + return; +} + +/***************************************************************************/ + +/* C function FCVBPOPT to access optional outputs from CVBANDPRE_Data */ + +void FCV_BPOPT(long int *lenrwbp, long int *leniwbp, long int *nfebp) +{ + CVBandPrecGetWorkSpace(CV_cvodemem, lenrwbp, leniwbp); + CVBandPrecGetNumRhsEvals(CV_cvodemem, nfebp); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvbp.h b/dep/cvode-2.7.0/cvode/fcmix/fcvbp.h new file mode 100644 index 00000000..2312e9e5 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvbp.h @@ -0,0 +1,256 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2010/12/15 19:40:08 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the Fortran interface include file for the BAND + * preconditioner (CVBANDPRE). + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================== + * + * FCVBP Interface Package + * + * The FCVBP Interface Package is a package of C functions which, + * together with the FCVODE Interface Package, support the use of the + * CVODE solver (serial version) with the CVBANDPRE preconditioner module, + * for the solution of ODE systems in a mixed Fortran/C setting. The + * combination of CVODE and CVBANDPRE solves systems dy/dt = f(t,y) with the + * SPGMR (scaled preconditioned GMRES), SPTFQMR (scaled preconditioned TFQMR), + * or SPBCG (scaled preconditioned Bi-CGSTAB) method for the linear systems + * that arise, and with a banded difference quotient Jacobian-based preconditioner. + * + * The user-callable functions in this package, with the corresponding + * CVODE and CVBBDPRE functions, are as follows: + * FCVBPINIT interfaces to CVBandPrecInit + * FCVBPSPTFQMR interfaces to CVBPSptfqmr + * FCVBPSPBCG interfaces to CVBPSpbcg + * FCVBPSPGMR interfaces to CVBPSpgmr + * FCVBPOPT accesses optional outputs + * + * In addition to the Fortran right-hand side function FCVFUN, the + * user may (optionally) supply a routine FCVJTIMES which is called by + * the interface function FCVJtimes of type CVSpilsJtimesFn. + * (The names of all user-supplied routines here are fixed, in order to + * maximize portability for the resulting mixed-language program.) + * + * Important note on portability. + * In this package, the names of the interface functions, and the names of + * the Fortran user routines called by them, appear as dummy names + * which are mapped to actual values by a series of definitions in the + * header file fcvbp.h. + * + * ============================================================================== + * + * Usage of the FCVODE/FCVBP Interface Packages + * + * The usage of the combined interface packages FCVODE and FCVBP requires + * calls to seven to ten interface functions, and one or two user-supplied + * routines which define the problem to be solved and indirectly define + * the preconditioner. These function calls and user routines are + * summarized separately below. + * + * Some details are omitted, and the user is referred to the CVODE user document + * for more complete information. + * + * (1) User-supplied right-hand side routine: FCVFUN + * The user must in all cases supply the following Fortran routine + * SUBROUTINE FCVFUN (T, Y, YDOT, IPAR, RPAR, IER) + * DIMENSION Y(*), YDOT(*), IPAR(*), RPAR(*) + * It must set the YDOT array to f(t,y), the right-hand side of the ODE + * system, as function of T = t and the array Y = y. Here Y and YDOT + * are distributed vectors. + * + * (2) Optional user-supplied Jacobian-vector product routine: FCVJTIMES + * As an option, the user may supply a routine that computes the product + * of the system Jacobian J = df/dy and a given vector v. If supplied, it + * must have the following form: + * SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, EWT, IPAR, RPAR, WORK, IER) + * DIMENSION V(*), FJV(*), Y(*), FY(*), EWT(*), IPAR(*), RPAR(*), WORK(*) + * Typically this routine will use only NEQ, T, Y, V, and FJV. It must + * compute the product vector Jv, where the vector v is stored in V, and store + * the product in FJV. On return, set IER = 0 if FCVJTIMES was successful, + * and nonzero otherwise. + * + * (3) Initialization: FNVINITS, FCVMALLOC, FCVBPINIT. + * + * (3.1) To initialize the serial vector specification, the user must make + * the following call: + * CALL FNVINITS(NEQ, IER) + * where NEQ is the problem size and IER is a return completion flag. + * Possible values for IER are 0 = success, -1 = failure. + * + * (3.2) To set various problem and solution parameters and allocate + * internal memory for CVODE, make the following call: + * CALL FCVMALLOC(T0, Y0, METH, ITMETH, IATOL, RTOL, ATOL, + * 1 IOUT, ROUT, IPAR, RPAR, IER) + * The arguments are: + * T0 = initial value of t + * Y0 = array of initial conditions + * METH = basic integration method: 1 = Adams (nonstiff), 2 = BDF (stiff) + * ITMETH = nonlinear iteration method: 1 = functional iteration, 2 = Newton iter. + * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array + * RTOL = relative tolerance (scalar) + * ATOL = absolute tolerance (scalar or array) + * IOUT = array of length 21 for integer optional outputs + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * ROUT = array of length 6 for real optional outputs + * IPAR = array with user integer data + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * RPAR = array with user real data + * IER = return completion flag. Values are 0 = success, and -1 = failure. + * See printed message for details in case of failure. + * + * (3.3) To allocate memory and initialize data associated with the CVBANDPRE + * preconditioner, make the following call: + * CALL FCVBPINIT(NEQ, MU, ML, IER) + * The arguments are: + * NEQ = problem size + * MU, ML = upper and lower half-bandwidths of the band matrix that + * is retained as an approximation of the Jacobian. + * IER = return completion flag: IER=0: success, IER<0: and error occurred + * + * (3.4A) To specify the SPGMR linear solver with the CVBANDPRE preconditioner, + * make the following call + * CALL FCVBPSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER) + * The arguments are: + * IPRETYPE = preconditioner type: + * 0 = none + * 1 = left only + * 2 = right only + * 3 = both sides. + * IGSTYPE = Gram-schmidt process type: 0 = modified G-S, 1 = classical G-S. + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * DELT = linear convergence tolerance factor; 0.0 indicates default. + * IER = return completion flag: IER=0: success, IER<0: ans error occurred + * + * (3.4B) To specify the SPBCG linear solver with the CVBANDPRE preconditioner, + * make the following call + * CALL FCVBPSPBCG(IPRETYPE, MAXL, DELT, IER) + * The arguments are: + * IPRETYPE = preconditioner type: + * 0 = none + * 1 = left only + * 2 = right only + * 3 = both sides. + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * DELT = linear convergence tolerance factor; 0.0 indicates default. + * IER = return completion flag: IER=0: success, IER<0: ans error occurred + * + * (3.4C) To specify the SPTFQMR linear solver with the CVBANDPRE preconditioner, + * make the following call + * CALL FCVBPSPTFQMR(IPRETYPE, MAXL, DELT, IER) + * The arguments are: + * IPRETYPE = preconditioner type: + * 0 = none + * 1 = left only + * 2 = right only + * 3 = both sides. + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * DELT = linear convergence tolerance factor; 0.0 indicates default. + * IER = return completion flag: IER=0: success, IER<0: ans error occurred + * + * (3.5) To specify whether the Krylov linear solver (GMRES, Bi-CGSTAB, or TFQMR) + * should use the supplied FCVJTIMES or the internal finite difference approximation, + * make the call + * CALL FCVSPILSSETJAC(FLAG, IER) + * where FLAG=0 for finite differences approxaimtion or + * FLAG=1 to use the supplied routine FCVJTIMES + * + * (4) The integrator: FCVODE + * Carrying out the integration is accomplished by making calls as follows: + * CALL FCVODE (TOUT, T, Y, ITASK, IER) + * The arguments are: + * TOUT = next value of t at which a solution is desired (input) + * T = value of t reached by the solver on output + * Y = array containing the computed solution on output + * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate); + * 2 = one-step mode (return after each internal step taken); + * 3 = normal mode with TSTOP; 4 = one-step mode with TSTOP. + * IER = completion flag: 0 = success, 1 = TSTOP return, 2 = root return, + * negative values are various failure modes (see CVODE User Guide). + * The current values of the optional outputs are available in IOUT and ROUT. + * + * (5) Optional outputs: FCVBPOPT + * Optional outputs specific to the SP* solver are LRW, LIW, LFLG, NFELS, NJTV, + * NPE, NPS, NLI, NCFL, stored in IOUT(13)...IOUT(21). + * To obtain the optional outputs associated with the CVBANDPRE module, make + * the following call: + * CALL FCVBPOPT(LENRWBP, LENIWBP, NFEBP) + * The arguments returned are: + * LENRWBP = length of real preconditioner work space, in realtype words. + * This size is local to the current processor. + * LENIWBP = length of integer preconditioner work space, in integer words. + * This size is local to the current processor. + * NFEBP = number of f(t,y) evaluations for CVBANDPRE + * + * (6) Computing solution derivatives: FCVDKY + * To obtain a derivative of the solution (optionally), of order up to + * the current method order, make the following call: + * CALL FCVDKY (T, K, DKY) + * The arguments are: + * T = value of t at which solution derivative is desired + * K = derivative order (0 .le. K .le. QU) + * DKY = array containing computed K-th derivative of y on return + * + * (7) Memory freeing: FCVFREE + * To the free the internal memory created by the calls to FNVINITS, + * FCVMALLOC, and FCVBPINIT, make the following call: + * CALL FCVFREE + * + * ============================================================================== + */ + +#ifndef _FCVBP_H +#define _FCVBP_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* header files */ + +#include /* definition of type N_Vector */ +#include /* definition of type realtype */ + +/* Definitions of interface function names */ + +#if defined(SUNDIALS_F77_FUNC) + +#define FCV_BPINIT SUNDIALS_F77_FUNC(fcvbpinit, FCVBPINIT) +#define FCV_BPSPTFQMR SUNDIALS_F77_FUNC(fcvbpsptfqmr, FCVBPSPTFQMR) +#define FCV_BPSPBCG SUNDIALS_F77_FUNC(fcvbpspbcg, FCVBPSPBCG) +#define FCV_BPSPGMR SUNDIALS_F77_FUNC(fcvbpspgmr, FCVBPSPGMR) +#define FCV_BPOPT SUNDIALS_F77_FUNC(fcvbpopt, FCVBPOPT) + +#else + +#define FCV_BPINIT fcvbpinit_ +#define FCV_BPSPTFQMR fcvbpsptfqmr_ +#define FCV_BPSPBCG fcvbpspbcg_ +#define FCV_BPSPGMR fcvbpspgmr_ +#define FCV_BPOPT fcvbpopt_ + +#endif + +/* Prototypes of exported function */ +void FCV_BPINIT(long int *N, long int *mu, long int *ml, int *ier); +void FCV_BPSPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier); +void FCV_BPSPBCG(int *pretype, int *maxl, realtype *delt, int *ier); +void FCV_BPSPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier); +void FCV_BPOPT(long int *lenrwbp, long int *leniwbp, long int *nfebp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvdense.c b/dep/cvode-2.7.0/cvode/fcmix/fcvdense.c new file mode 100644 index 00000000..fa7cd4c6 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvdense.c @@ -0,0 +1,93 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:27:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for CVODE/CVDENSE, for the case + * of a user-supplied Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/***************************************************************************/ + +/* Prototype of the Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FCV_DJAC(long int*, /* N */ + realtype*, realtype*, realtype*, /* T, Y, FY */ + realtype*, /* DJAC */ + realtype*, /* H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, realtype*, realtype*, /* V1, V2, V3 */ + int *ier); /* IER */ +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_DENSESETJAC(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag == 0) { + *ier = CVDlsSetDenseJacFn(CV_cvodemem, NULL); + } else { + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVDlsSetDenseJacFn(CV_cvodemem, FCVDenseJac); + } +} + +/***************************************************************************/ + +/* C function CVDenseJac interfaces between CVODE and a Fortran subroutine + FCVDJAC for solution of a linear system with dense Jacobian approximation. + Addresses of arguments are passed to FCVDJAC, using the macro + DENSE_COL from DENSE and the routine N_VGetArrayPointer from NVECTOR. + Auxiliary data is assumed to be communicated by Common. */ + +int FCVDenseJac(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + int ier; + realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data; + realtype h; + FCVUserData CV_userdata; + + CVodeGetLastStep(CV_cvodemem, &h); + + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + jacdata = DENSE_COL(J,0); + + CV_userdata = (FCVUserData) user_data; + + FCV_DJAC(&N, &t, ydata, fydata, jacdata, &h, + CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier); + + return(ier); +} + diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvewt.c b/dep/cvode-2.7.0/cvode/fcmix/fcvewt.c new file mode 100644 index 00000000..60a1f8df --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvewt.c @@ -0,0 +1,74 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:28:59 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for CVODE, for the case of a + * user-supplied error weight calculation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars. */ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +/***************************************************************************/ + +/* Prototype of the Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FCV_EWT(realtype*, realtype*, /* Y, EWT */ + long int*, realtype*, /* IPAR, RPAR */ + int*); /* IER */ +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +/* + * User-callable function to interface to CVodeSetEwtFn. + */ + +void FCV_EWTSET(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag != 0) { + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVodeWFtolerances(CV_cvodemem, FCVEwtSet); + } +} + +/***************************************************************************/ + +/* + * C function to interface between CVODE and a Fortran subroutine FCVEWT. + */ + +int FCVEwtSet(N_Vector y, N_Vector ewt, void *user_data) +{ + int ier = 0; + realtype *ydata, *ewtdata; + FCVUserData CV_userdata; + + ydata = N_VGetArrayPointer(y); + ewtdata = N_VGetArrayPointer(ewt); + + CV_userdata = (FCVUserData) user_data; + + FCV_EWT(ydata, ewtdata, CV_userdata->ipar, CV_userdata->rpar, &ier); + + return(ier); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvjtimes.c b/dep/cvode-2.7.0/cvode/fcmix/fcvjtimes.c new file mode 100644 index 00000000..eb5f20ec --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvjtimes.c @@ -0,0 +1,95 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:28:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * The C function FCVJtimes is to interface between the + * CVSP* module and the user-supplied Jacobian-vector + * product routine FCVJTIMES. Note the use of the generic name + * FCV_JTIMES below. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/***************************************************************************/ + +/* Prototype of the Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FCV_JTIMES(realtype*, realtype*, /* V, JV */ + realtype*, realtype*, realtype*, /* T, Y, FY */ + realtype*, /* H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, /* WRK */ + int*); /* IER */ + +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_SPILSSETJAC(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag == 0) { + *ier = CVSpilsSetJacTimesVecFn(CV_cvodemem, NULL); + } else { + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVSpilsSetJacTimesVecFn(CV_cvodemem, FCVJtimes); + } +} + +/***************************************************************************/ + +/* C function FCVJtimes to interface between CVODE and user-supplied + Fortran routine FCVJTIMES for Jacobian * vector product. + Addresses of v, Jv, t, y, fy, h, and work are passed to FCVJTIMES, + using the routine N_VGetArrayPointer from NVECTOR. + A return flag ier from FCVJTIMES is returned by FCVJtimes. + Auxiliary data is assumed to be communicated by common blocks. */ + +int FCVJtimes(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *user_data, N_Vector work) +{ + realtype *vdata, *Jvdata, *ydata, *fydata, *wkdata; + realtype h; + FCVUserData CV_userdata; + + int ier = 0; + + CVodeGetLastStep(CV_cvodemem, &h); + + vdata = N_VGetArrayPointer(v); + Jvdata = N_VGetArrayPointer(Jv); + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + wkdata = N_VGetArrayPointer(work); + + CV_userdata = (FCVUserData) user_data; + + FCV_JTIMES (vdata, Jvdata, &t, ydata, fydata, &h, + CV_userdata->ipar, CV_userdata->rpar, wkdata, &ier); + + return(ier); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvlapack.c b/dep/cvode-2.7.0/cvode/fcmix/fcvlapack.c new file mode 100644 index 00000000..62ec7570 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvlapack.c @@ -0,0 +1,52 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/11/10 21:04:11 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for CVODE/CVLAPACK + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/***************************************************************************/ + +void FCV_LAPACKDENSE(int *neq, int *ier) +{ + /* neq is the problem size */ + + *ier = CVLapackDense(CV_cvodemem, *neq); + + CV_ls = CV_LS_LAPACKDENSE; +} + +/***************************************************************************/ + +void FCV_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier) +{ + /* + neq is the problem size + mupper is the upper bandwidth + mlower is the lower bandwidth + */ + + *ier = CVLapackBand(CV_cvodemem, *neq, *mupper, *mlower); + + CV_ls = CV_LS_LAPACKBAND; +} + +/***************************************************************************/ + diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvlapband.c b/dep/cvode-2.7.0/cvode/fcmix/fcvlapband.c new file mode 100644 index 00000000..e3fe9f66 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvlapband.c @@ -0,0 +1,106 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:27:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for CVODE/CVLAPACK, for the case + * of a user-supplied band Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/***************************************************************************/ + +/* Prototype of the Fortran routines */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FCV_BJAC(long int*, long int*, long int*, long int*, /* N,MU,ML,EBAND */ + realtype*, realtype*, realtype*, /* T, Y, FY */ + realtype*, /* LBJAC */ + realtype*, /* H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, realtype*, realtype*, /* V1, V2, V3 */ + int*); /* IER */ + +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_LAPACKBANDSETJAC(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag == 0) { + + *ier = CVDlsSetBandJacFn(CV_cvodemem, NULL); + + } else { + + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVDlsSetBandJacFn(CV_cvodemem, FCVLapackBandJac); + + } + +} + +/***************************************************************************/ + +/* The C function FCVLapackBandJac interfaces between CVODE and a + * Fortran subroutine FCVBJAC for the solution of a linear system using + * Lapack with band Jacobian approximation. + * Addresses of arguments are passed to FCVBJAC, using the macro + * BAND_COL and the routine N_VGetArrayPointer from NVECTOR. + * The address passed for J is that of the element in column 0 with row + * index -mupper. An extended bandwith equal to (J->smu) + mlower + 1 is + * passed as the column dimension of the corresponding array. + * Auxiliary data is assumed to be communicated by Common. + */ + +int FCVLapackBandJac(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + int ier; + realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data; + realtype h; + long int eband; + FCVUserData CV_userdata; + + CVodeGetLastStep(CV_cvodemem, &h); + + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + eband = (J->s_mu) + mlower + 1; + jacdata = BAND_COL(J,0) - mupper; + + CV_userdata = (FCVUserData) user_data; + + FCV_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata, jacdata, &h, + CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier); + + return(ier); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvlapdense.c b/dep/cvode-2.7.0/cvode/fcmix/fcvlapdense.c new file mode 100644 index 00000000..bb87e240 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvlapdense.c @@ -0,0 +1,95 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:27:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Fortran/C interface routines for CVODE/CVLAPACK, for the case + * of a user-supplied dense Jacobian approximation routine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/***************************************************************************/ + +/* Prototype of the Fortran routines */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FCV_DJAC(long int*, /* N */ + realtype*, realtype*, realtype*, /* T, Y, FY */ + realtype*, /* LDJAC */ + realtype*, /* H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, realtype*, realtype*, /* V1, V2, V3 */ + int *ier); /* IER */ +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_LAPACKDENSESETJAC(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag == 0) { + *ier = CVDlsSetDenseJacFn(CV_cvodemem, NULL); + } else { + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVDlsSetDenseJacFn(CV_cvodemem, FCVLapackDenseJac); + } +} + +/***************************************************************************/ + +/* The C function FCVLapackDenseJac interfaces between CVODE and a + * Fortran subroutine FCVDJAC for solution of a linear system using + * Lapack with dense Jacobian approximation. + * Addresses of arguments are passed to FCVDJAC, using the macro + * DENSE_COL and the routine N_VGetArrayPointer from NVECTOR. + * Auxiliary data is assumed to be communicated by Common. + */ + +int FCVLapackDenseJac(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + int ier; + realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data; + realtype h; + FCVUserData CV_userdata; + + CVodeGetLastStep(CV_cvodemem, &h); + + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + jacdata = DENSE_COL(J,0); + + CV_userdata = (FCVUserData) user_data; + + FCV_DJAC(&N, &t, ydata, fydata, jacdata, &h, + CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier); + + return(ier); +} + diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvode.c b/dep/cvode-2.7.0/cvode/fcmix/fcvode.c new file mode 100644 index 00000000..883c58d8 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvode.c @@ -0,0 +1,603 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2010/12/09 19:36:24 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the Fortran interface to + * the CVODE package. See fcvode.h for usage. + * NOTE: some routines are necessarily stored elsewhere to avoid + * linking problems. Therefore, see also fcvpreco.c, fcvpsol.c, + * and fcvjtimes.c for all the options available. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include "fcvode.h" /* actual function names, prototypes, global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include /* prototypes for CVBAND interface routines */ +#include /* prototypes for CVDENSE interface routines */ +#include /* prototypes for CVDIAG interface routines */ +#include /* prototypes for CVSPGMR interface routines */ +#include /* prototypes for CVSPBCG interface routines */ +#include /* prototypes for CVSPTFQMR interface routines */ + +/***************************************************************************/ + +/* Definitions for global variables shared amongst various routines */ + +void *CV_cvodemem; +long int *CV_iout; +realtype *CV_rout; +int CV_nrtfn; +int CV_ls; + +/***************************************************************************/ + +/* private constant(s) */ +#define ZERO RCONST(0.0) + +/***************************************************************************/ + +/* Prototypes of the Fortran routines */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FCV_FUN(realtype*, /* T */ + realtype*, /* Y */ + realtype*, /* YDOT */ + long int*, /* IPAR */ + realtype*, /* RPAR */ + int*); /* IER */ +#ifdef __cplusplus +} +#endif + +/**************************************************************************/ + +void FCV_MALLOC(realtype *t0, realtype *y0, + int *meth, int *itmeth, int *iatol, + realtype *rtol, realtype *atol, + long int *iout, realtype *rout, + long int *ipar, realtype *rpar, + int *ier) +{ + int lmm, iter; + N_Vector Vatol; + FCVUserData CV_userdata; + + *ier = 0; + + /* Check for required vector operations */ + if(F2C_CVODE_vec->ops->nvgetarraypointer == NULL || + F2C_CVODE_vec->ops->nvsetarraypointer == NULL) { + *ier = -1; + printf("A required vector operation is not implemented.\n\n"); + return; + } + + /* Initialize all pointers to NULL */ + CV_cvodemem = NULL; + Vatol = NULL; + + /* Create CVODE object */ + lmm = (*meth == 1) ? CV_ADAMS : CV_BDF; + iter = (*itmeth == 1) ? CV_FUNCTIONAL : CV_NEWTON; + CV_cvodemem = CVodeCreate(lmm, iter); + if (CV_cvodemem == NULL) { + *ier = -1; + return; + } + + /* Set and attach user data */ + CV_userdata = NULL; + CV_userdata = (FCVUserData) malloc(sizeof *CV_userdata); + if (CV_userdata == NULL) { + *ier = -1; + return; + } + CV_userdata->rpar = rpar; + CV_userdata->ipar = ipar; + + *ier = CVodeSetUserData(CV_cvodemem, CV_userdata); + if(*ier != CV_SUCCESS) { + free(CV_userdata); CV_userdata = NULL; + *ier = -1; + return; + } + + /* Set data in F2C_CVODE_vec to y0 */ + N_VSetArrayPointer(y0, F2C_CVODE_vec); + + /* Call CVodeInit */ + *ier = CVodeInit(CV_cvodemem, FCVf, *t0, F2C_CVODE_vec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + + /* On failure, exit */ + if(*ier != CV_SUCCESS) { + free(CV_userdata); CV_userdata = NULL; + *ier = -1; + return; + } + + /* Set tolerances */ + switch (*iatol) { + case 1: + *ier = CVodeSStolerances(CV_cvodemem, *rtol, *atol); + break; + case 2: + Vatol = NULL; + Vatol = N_VCloneEmpty(F2C_CVODE_vec); + if (Vatol == NULL) { + free(CV_userdata); CV_userdata = NULL; + *ier = -1; + return; + } + N_VSetArrayPointer(atol, Vatol); + *ier = CVodeSVtolerances(CV_cvodemem, *rtol, Vatol); + N_VDestroy(Vatol); + break; + } + + /* On failure, exit */ + if(*ier != CV_SUCCESS) { + free(CV_userdata); CV_userdata = NULL; + *ier = -1; + return; + } + + /* Grab optional output arrays and store them in global variables */ + CV_iout = iout; + CV_rout = rout; + + /* Store the unit roundoff in rout for user access */ + CV_rout[5] = UNIT_ROUNDOFF; + + return; +} + +/***************************************************************************/ + +void FCV_REINIT(realtype *t0, realtype *y0, + int *iatol, realtype *rtol, realtype *atol, + int *ier) +{ + N_Vector Vatol; + + *ier = 0; + + /* Initialize all pointers to NULL */ + Vatol = NULL; + + /* Set data in F2C_CVODE_vec to y0 */ + N_VSetArrayPointer(y0, F2C_CVODE_vec); + + /* Call CVReInit */ + *ier = CVodeReInit(CV_cvodemem, *t0, F2C_CVODE_vec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + + /* On failure, exit */ + if (*ier != CV_SUCCESS) { + *ier = -1; + return; + } + + /* Set tolerances */ + switch (*iatol) { + case 1: + *ier = CVodeSStolerances(CV_cvodemem, *rtol, *atol); + break; + case 2: + Vatol = NULL; + Vatol = N_VCloneEmpty(F2C_CVODE_vec); + if (Vatol == NULL) { + *ier = -1; + return; + } + N_VSetArrayPointer(atol, Vatol); + *ier = CVodeSVtolerances(CV_cvodemem, *rtol, Vatol); + N_VDestroy(Vatol); + break; + } + + /* On failure, exit */ + if (*ier != CV_SUCCESS) { + *ier = -1; + return; + } + + return; +} + +/***************************************************************************/ + +void FCV_SETIIN(char key_name[], long int *ival, int *ier, int key_len) +{ + if (!strncmp(key_name,"MAX_ORD", (size_t)key_len)) + *ier = CVodeSetMaxOrd(CV_cvodemem, (int) *ival); + else if (!strncmp(key_name,"MAX_NSTEPS", (size_t)key_len)) + *ier = CVodeSetMaxNumSteps(CV_cvodemem, (int) *ival); + else if (!strncmp(key_name,"MAX_ERRFAIL", (size_t)key_len)) + *ier = CVodeSetMaxErrTestFails(CV_cvodemem, (int) *ival); + else if (!strncmp(key_name,"MAX_NITERS", (size_t)key_len)) + *ier = CVodeSetMaxNonlinIters(CV_cvodemem, (int) *ival); + else if (!strncmp(key_name,"MAX_CONVFAIL", (size_t)key_len)) + *ier = CVodeSetMaxConvFails(CV_cvodemem, (int) *ival); + else if (!strncmp(key_name,"HNIL_WARNS", (size_t)key_len)) + *ier = CVodeSetMaxHnilWarns(CV_cvodemem, (int) *ival); + else if (!strncmp(key_name,"STAB_LIM", (size_t)key_len)) + *ier = CVodeSetStabLimDet(CV_cvodemem, (int) *ival); + else { + *ier = -99; + printf("FCVSETIIN: Unrecognized key.\n\n"); + } + +} + +/***************************************************************************/ + +void FCV_SETRIN(char key_name[], realtype *rval, int *ier, int key_len) +{ + if (!strncmp(key_name,"INIT_STEP", (size_t)key_len)) + *ier = CVodeSetInitStep(CV_cvodemem, *rval); + else if (!strncmp(key_name,"MAX_STEP", (size_t)key_len)) + *ier = CVodeSetMaxStep(CV_cvodemem, *rval); + else if (!strncmp(key_name,"MIN_STEP", (size_t)key_len)) + *ier = CVodeSetMinStep(CV_cvodemem, *rval); + else if (!strncmp(key_name,"STOP_TIME", (size_t)key_len)) + *ier = CVodeSetStopTime(CV_cvodemem, *rval); + else if (!strncmp(key_name,"NLCONV_COEF", (size_t)key_len)) + *ier = CVodeSetNonlinConvCoef(CV_cvodemem, *rval); + else { + *ier = -99; + printf("FCVSETRIN: Unrecognized key.\n\n"); + } + +} + +/***************************************************************************/ + +void FCV_DENSE(long int *neq, int *ier) +{ + /* neq is the problem size */ + + *ier = CVDense(CV_cvodemem, *neq); + + CV_ls = CV_LS_DENSE; +} + +/***************************************************************************/ + +void FCV_BAND(long int *neq, long int *mupper, long int *mlower, int *ier) +{ + /* + neq is the problem size + mupper is the upper bandwidth + mlower is the lower bandwidth + */ + + *ier = CVBand(CV_cvodemem, *neq, *mupper, *mlower); + + CV_ls = CV_LS_BAND; +} + +/***************************************************************************/ + +void FCV_DIAG(int *ier) +{ + *ier = CVDiag(CV_cvodemem); + + CV_ls = CV_LS_DIAG; +} + +/***************************************************************************/ + +void FCV_SPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier) +{ + /* + pretype the preconditioner type + maxl the maximum Krylov dimension + gstype the Gram-Schmidt process type + delt the linear convergence tolerance factor + */ + + *ier = CVSpgmr(CV_cvodemem, *pretype, *maxl); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetGSType(CV_cvodemem, *gstype); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt); + if (*ier != CVSPILS_SUCCESS) return; + + CV_ls = CV_LS_SPGMR; +} + +/***************************************************************************/ + +void FCV_SPBCG(int *pretype, int *maxl, realtype *delt, int *ier) +{ + /* + pretype the preconditioner type + maxl the maximum Krylov dimension + delt the linear convergence tolerance factor + */ + + *ier = CVSpbcg(CV_cvodemem, *pretype, *maxl); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt); + if (*ier != CVSPILS_SUCCESS) return; + + CV_ls = CV_LS_SPBCG; +} + +/***************************************************************************/ + +void FCV_SPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier) +{ + /* + pretype the preconditioner type + maxl the maximum Krylov dimension + delt the linear convergence tolerance factor + */ + + *ier = CVSptfqmr(CV_cvodemem, *pretype, *maxl); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt); + if (*ier != CVSPILS_SUCCESS) return; + + CV_ls = CV_LS_SPTFQMR; +} + +/***************************************************************************/ + +void FCV_SPGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier) +{ + /* + pretype the preconditioner type + gstype the Gram-Schmidt process type + delt the linear convergence tolerance factor + */ + + *ier = CVSpilsSetPrecType(CV_cvodemem, *pretype); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetGSType(CV_cvodemem, *gstype); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt); + if (*ier != CVSPILS_SUCCESS) return; + + CV_ls = CV_LS_SPGMR; +} + +/***************************************************************************/ + +void FCV_SPBCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier) +{ + /* + pretype the preconditioner type + maxl the maximum Krylov subspace dimension + delt the linear convergence tolerance factor + */ + + *ier = CVSpilsSetPrecType(CV_cvodemem, *pretype); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetMaxl(CV_cvodemem, *maxl); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt); + if (*ier != CVSPILS_SUCCESS) return; + + CV_ls = CV_LS_SPBCG; +} + +/***************************************************************************/ + +void FCV_SPTFQMRREINIT(int *pretype, int *maxl, realtype *delt, int *ier) +{ + /* + pretype the preconditioner type + maxl the maximum Krylov subspace dimension + delt the linear convergence tolerance factor + */ + + *ier = CVSpilsSetPrecType(CV_cvodemem, *pretype); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetMaxl(CV_cvodemem, *maxl); + if (*ier != CVSPILS_SUCCESS) return; + + *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt); + if (*ier != CVSPILS_SUCCESS) return; + + CV_ls = CV_LS_SPTFQMR; +} + +/***************************************************************************/ + +void FCV_CVODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier) +{ + /* + tout is the t value where output is desired + F2C_CVODE_vec is the N_Vector containing the solution on return + t is the returned independent variable value + itask is the task indicator (1 = CV_NORMAL, 2 = CV_ONE_STEP, + 3 = CV_NORMAL_TSTOP, 4 = CV_ONE_STEP_TSTOP) + */ + + int qu, qcur; + + N_VSetArrayPointer(y, F2C_CVODE_vec); + + *ier = CVode(CV_cvodemem, *tout, F2C_CVODE_vec, t, *itask); + + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + + /* Load optional outputs in iout & rout */ + CVodeGetWorkSpace(CV_cvodemem, + &CV_iout[0], /* LENRW */ + &CV_iout[1]); /* LENIW */ + CVodeGetIntegratorStats(CV_cvodemem, + &CV_iout[2], /* NST */ + &CV_iout[3], /* NFE */ + &CV_iout[7], /* NSETUPS */ + &CV_iout[4], /* NETF */ + &qu, /* QU */ + &qcur, /* QCUR */ + &CV_rout[0], /* H0U */ + &CV_rout[1], /* HU */ + &CV_rout[2], /* HCUR */ + &CV_rout[3]); /* TCUR */ + CV_iout[8] = (long int) qu; + CV_iout[9] = (long int) qcur; + CVodeGetTolScaleFactor(CV_cvodemem, + &CV_rout[4]); /* TOLSFAC */ + CVodeGetNonlinSolvStats(CV_cvodemem, + &CV_iout[6], /* NNI */ + &CV_iout[5]); /* NCFN */ + CVodeGetNumStabLimOrderReds(CV_cvodemem, &CV_iout[10]); /* NOR */ + + /* Root finding is on */ + if (CV_nrtfn != 0) + CVodeGetNumGEvals(CV_cvodemem, &CV_iout[11]); /* NGE */ + + switch(CV_ls) { + case CV_LS_DENSE: + case CV_LS_BAND: + case CV_LS_LAPACKDENSE: + case CV_LS_LAPACKBAND: + CVDlsGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]); /* LENRWLS,LENIWLS */ + CVDlsGetLastFlag(CV_cvodemem, &CV_iout[14]); /* LSTF */ + CVDlsGetNumRhsEvals(CV_cvodemem, &CV_iout[15]); /* NFELS */ + CVDlsGetNumJacEvals(CV_cvodemem, &CV_iout[16]); /* NJE */ + break; + case CV_LS_DIAG: + CVDiagGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]); /* LENRWLS,LENIWLS */ + CVDiagGetLastFlag(CV_cvodemem, &CV_iout[14]); /* LSTF */ + CVDiagGetNumRhsEvals(CV_cvodemem, &CV_iout[15]); /* NFELS */ + break; + case CV_LS_SPGMR: + case CV_LS_SPBCG: + case CV_LS_SPTFQMR: + CVSpilsGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]); /* LENRWLS,LENIWLS */ + CVSpilsGetLastFlag(CV_cvodemem, &CV_iout[14]); /* LSTF */ + CVSpilsGetNumRhsEvals(CV_cvodemem, &CV_iout[15]); /* NFELS */ + CVSpilsGetNumJtimesEvals(CV_cvodemem, &CV_iout[16]); /* NJTV */ + CVSpilsGetNumPrecEvals(CV_cvodemem, &CV_iout[17]); /* NPE */ + CVSpilsGetNumPrecSolves(CV_cvodemem, &CV_iout[18]); /* NPS */ + CVSpilsGetNumLinIters(CV_cvodemem, &CV_iout[19]); /* NLI */ + CVSpilsGetNumConvFails(CV_cvodemem, &CV_iout[20]); /* NCFL */ + } +} + +/***************************************************************************/ + +void FCV_DKY (realtype *t, int *k, realtype *dky, int *ier) +{ + /* + t is the t value where output is desired + k is the derivative order + F2C_CVODE_vec is the N_Vector containing the solution derivative on return + */ + + N_VSetArrayPointer(dky, F2C_CVODE_vec); + + *ier = 0; + *ier = CVodeGetDky(CV_cvodemem, *t, *k, F2C_CVODE_vec); + + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + +} + +/*************************************************/ + +void FCV_GETERRWEIGHTS(realtype *eweight, int *ier) +{ + /* Attach user data to vector */ + N_VSetArrayPointer(eweight, F2C_CVODE_vec); + + *ier = 0; + *ier = CVodeGetErrWeights(CV_cvodemem, F2C_CVODE_vec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + + return; +} + +/*************************************************/ + +void FCV_GETESTLOCALERR(realtype *ele, int *ier) +{ + /* Attach user data to vector */ + N_VSetArrayPointer(ele, F2C_CVODE_vec); + + *ier = 0; + *ier = CVodeGetEstLocalErrors(CV_cvodemem, F2C_CVODE_vec); + + /* Reset data pointers */ + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + + return; +} + +/***************************************************************************/ + +void FCV_FREE () +{ + CVodeMem cv_mem; + + cv_mem = (CVodeMem) CV_cvodemem; + + free(cv_mem->cv_user_data); cv_mem->cv_user_data = NULL; + + CVodeFree(&CV_cvodemem); + + N_VSetArrayPointer(NULL, F2C_CVODE_vec); + N_VDestroy(F2C_CVODE_vec); +} + +/***************************************************************************/ + +/* + * C function CVf to interface between CVODE and a Fortran subroutine FCVFUN. + * Addresses of t, y, and ydot are passed to CVFUN, using the + * routine N_VGetArrayPointer from the NVECTOR module. + * Auxiliary data is assumed to be communicated by Common. + */ + +int FCVf(realtype t, N_Vector y, N_Vector ydot, void *user_data) +{ + int ier; + realtype *ydata, *dydata; + FCVUserData CV_userdata; + + ydata = N_VGetArrayPointer(y); + dydata = N_VGetArrayPointer(ydot); + + CV_userdata = (FCVUserData) user_data; + + FCV_FUN(&t, ydata, dydata, CV_userdata->ipar, CV_userdata->rpar, &ier); + + return(ier); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvode.h b/dep/cvode-2.7.0/cvode/fcmix/fcvode.h new file mode 100644 index 00000000..08232af8 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvode.h @@ -0,0 +1,758 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.9 $ + * $Date: 2010/12/01 22:27:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for FCVODE, the Fortran interface to + * the CVODE package. + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================= + * + * FCVODE Interface Package + * + * The FCVODE Interface Package is a package of C functions which support + * the use of the CVODE solver, for the solution of ODE systems + * dy/dt = f(t,y), in a mixed Fortran/C setting. While CVODE is written + * in C, it is assumed here that the user's calling program and + * user-supplied problem-defining routines are written in Fortran. + * This package provides the necessary interface to CVODE for both the + * serial and the parallel NVECTOR implementations. + * + * The user-callable functions, with the corresponding CVODE functions, + * are as follows: + * + * FNVINITS and FNVINITP interface to N_VNew_Serial and + * N_VNew_Parallel, respectively + * + * FCVMALLOC interfaces to CVodeCreate, CVodeSetUserData, and CVodeInit + * + * FCVREINIT interfaces to CVReInit + * + * FCVSETIIN and FCVSETRIN interface to CVodeSet* + * + * FCVEWTSET interfaces to CVodeWFtolerances + * + * FCVDIAG interfaces to CVDiag + * + * FCVDENSE interfaces to CVDense + * FCVDENSESETJAC interfaces to CVDenseSetJacFn + * + * FCVBAND interfaces to CVBand + * FCVBANDSETJAC interfaces to CVBandSetJacFn + * + * FCVLAPACKDENSE interfaces to CVLapackDense + * FCVLAPACKBAND interfaces to CVLapackBand + * FCVLAPACKDENSESETJAC interfaces to CVLapackSetJacFn + * FCVLAPACKBANDSETJAC interfaces to CVLapackSetJacFn + * + * FCVSPGMR and FCVSPGMRREINIT interface to CVSpgmr and CVSpilsSet* + * FCVSPBCG, FCVSPBCGREINIT interface to CVSpbcg and CVSpilsSet* + * FCVSPTFQMR, FCVSPTFQMRREINIT interface to CVSptfqmr and CVSpilsSet* + * + * FCVSPILSSETJAC interfaces to CVSpilsSetJacTimesVecFn + * FCVSPILSSETPREC interfaces to CVSpilsSetPreconditioner + * + * FCVODE interfaces to CVode, CVodeGet*, and CV*Get* + * + * FCVDKY interfaces to CVodeGetDky + * + * FCVGETERRWEIGHTS interfaces to CVodeGetErrWeights + * + * FCVGETESTLOCALERR interfaces to CVodeGetEstLocalErrors + * + * FCVFREE interfaces to CVodeFree + * + * The user-supplied functions, each listed with the corresponding interface + * function which calls it (and its type within CVODE), are as follows: + * FCVFUN is called by the interface function FCVf of type CVRhsFn + * FCVDJAC is called by the interface fn. FCVDenseJac of type CVDenseJacFn + * FCVBJAC is called by the interface fn. FCVBandJac of type CVBandJacFn + * FCVLDJAC is called by the interface fn. FCVLapackDenseJac of type CVLapackJacFn + * FCVLBJAC is called by the interface fn. FCVLapackBandJac of type CVLapackJacFn + * FCVPSOL is called by the interface fn. FCVPSol of type CVSpilsPrecSolveFn + * FCVPSET is called by the interface fn. FCVPSet of type CVSpilsPrecSetupFn + * FCVJTIMES is called by interface fn. FCVJtimes of type CVSpilsJacTimesVecFn + * FCVEWT is called by interface fn. FCVEwtSet of type CVEwtFn + * In contrast to the case of direct use of CVODE, and of most Fortran ODE + * solvers, the names of all user-supplied routines here are fixed, in + * order to maximize portability for the resulting mixed-language program. + * + * Important note on portability. + * In this package, the names of the interface functions, and the names of + * the Fortran user routines called by them, appear as dummy names + * which are mapped to actual values by a series of definitions, in this + * and other header files. + * + * ============================================================================= + * + * Usage of the FCVODE Interface Package + * + * The usage of FCVODE requires calls to five or more interface + * functions, depending on the method options selected, and one or more + * user-supplied routines which define the problem to be solved. These + * function calls and user routines are summarized separately below. + * + * Some details are omitted, and the user is referred to the user documents + * on CVODE for more complete documentation. Information on the + * arguments of any given user-callable interface routine, or of a given + * user-supplied function called by an interface function, can be found in + * the documentation on the corresponding function in the CVODE package. + * + * The number labels on the instructions below end with s for instructions + * that apply to the serial version of CVODE only, and end with p for + * those that apply to the parallel version only. + * + * ----------------------------------------------------------------------------- + * + * (1) User-supplied right-hand side routine: FCVFUN + * The user must in all cases supply the following Fortran routine + * SUBROUTINE FCVFUN (T, Y, YDOT, IPAR, RPAR, IER) + * DIMENSION Y(*), YDOT(*), IPAR(*), RPAR(*) + * It must set the YDOT array to f(t,y), the right-hand side of the ODE + * system, as function of T = t and the array Y = y. Here Y and YDOT + * are distributed vectors. IPAR and RPAR are arrays of integer and real user + * data, respectively as passed to FCVMALLOC. + * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred, + * and IER < 0 if an unrecoverable error ocurred. + * + * (2s) Optional user-supplied dense Jacobian approximation routine: FCVDJAC + * As an option when using the DENSE linear solver, the user may supply a + * routine that computes a dense approximation of the system Jacobian + * J = df/dy. If supplied, it must have the following form: + * SUBROUTINE FCVDJAC (NEQ, T, Y, FY, DJAC, H, IPAR, RPAR, WK1, WK2, WK3, IER) + * DIMENSION Y(*), FY(*), DJAC(NEQ,*), IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*) + * Typically this routine will use only NEQ, T, Y, and DJAC. It must compute + * the Jacobian and store it columnwise in DJAC. + * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC. + * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred, + * and IER < 0 if an unrecoverable error ocurred. + * + * (3s) Optional user-supplied band Jacobian approximation routine: FCVBJAC + * As an option when using the BAND linear solver, the user may supply a + * routine that computes a band approximation of the system Jacobian + * J = df/dy. If supplied, it must have the following form: + * SUBROUTINE FCVBJAC (NEQ, MU, ML, MDIM, T, Y, FY, BJAC, H, + * 1 IPAR, RPAR, WK1, WK2, WK3, IER) + * DIMENSION Y(*), FY(*), BJAC(MDIM,*), IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*) + * Typically this routine will use only NEQ, MU, ML, T, Y, and BJAC. + * It must load the MDIM by N array BJAC with the Jacobian matrix at the + * current (t,y) in band form. Store in BJAC(k,j) the Jacobian element J(i,j) + * with k = i - j + MU + 1 (k = 1 ... ML+MU+1) and j = 1 ... N. + * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC. + * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred, + * and IER < 0 if an unrecoverable error ocurred. + * + * (4s) Optional user-supplied Lapack dense Jacobian routine: FCVLDJAC + * See the description for FCVDJAC. NOTE: the dense Jacobian matrix + * is NOT set to zero before calling the user's FCVLDJAC. + * + * (5s) Optional user-supplied Lapack band Jacobian routine: FCVLBJAC + * See the description for FCVBJAC. NOTE: the band Jacobian matrix + * is NOT set to zero before calling the user's FCVLBJAC. + * + * (6) Optional user-supplied Jacobian-vector product routine: FCVJTIMES + * As an option when using the SP* linear solver, the user may supply + * a routine that computes the product of the system Jacobian J = df/dy and + * a given vector v. If supplied, it must have the following form: + * SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, H, IPAR, RPAR, WORK, IER) + * DIMENSION V(*), FJV(*), Y(*), FY(*), IPAR(*), RPAR(*), WORK(*) + * Typically this routine will use only NEQ, T, Y, V, and FJV. It must + * compute the product vector Jv where the vector v is stored in V, and store + * the product in FJV. On return, set IER = 0 if FCVJTIMES was successful, + * and nonzero otherwise. + * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC. + * + * (7) Optional user-supplied error weight vector routine: FCVEWT + * As an option to providing the relative and absolute tolerances, the user + * may supply a routine that computes the weights used in the WRMS norms. + * If supplied, it must have the following form: + * SUBROUTINE FCVEWT (Y, EWT, IPAR, RPAR, IER) + * DIMENSION Y(*), EWT(*), IPAR(*), RPAR(*) + * It must store the error weights in EWT, given the current solution vector Y. + * On return, set IER = 0 if successful, and nonzero otherwise. + * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC. + * + * ----------------------------------------------------------------------------- + * + * (8) Initialization: FNVINITS / FNVINITP , FCVMALLOC, FCVREINIT + * + * (8.1s) To initialize the serial machine environment, the user must make + * the following call: + * CALL FNVINITS (1, NEQ, IER) + * where the first argument is the CVODE solver ID. The other arguments are: + * NEQ = size of vectors + * IER = return completion flag. Values are 0 = success, -1 = failure. + * + * (8.1p) To initialize the parallel machine environment, the user must make + * the following call: + * CALL FNVINITP (1, NLOCAL, NGLOBAL, IER) + * The arguments are: + * NLOCAL = local size of vectors on this processor + * NGLOBAL = the system size, and the global size of vectors (the sum + * of all values of NLOCAL) + * IER = return completion flag. Values are 0 = success, -1 = failure. + * Note: If MPI was initialized by the user, the communicator must be + * set to MPI_COMM_WORLD. If not, this routine initializes MPI and sets + * the communicator equal to MPI_COMM_WORLD. + * + * (8.2) To set various problem and solution parameters and allocate + * internal memory, make the following call: + * CALL FCVMALLOC(T0, Y0, METH, ITMETH, IATOL, RTOL, ATOL, + * 1 IOUT, ROUT, IPAR, RPAR, IER) + * The arguments are: + * T0 = initial value of t + * Y0 = array of initial conditions + * METH = basic integration method: 1 = Adams (nonstiff), 2 = BDF (stiff) + * ITMETH = nonlinear iteration method: 1=functional iteration, 2=Newton iter. + * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array. + * If IATOL = 3, then the user must supply a routine FCVEWT to compute + * the error weight vector. + * RTOL = relative tolerance (scalar) + * ATOL = absolute tolerance (scalar or array) + * IOUT = array of length 21 for integer optional outputs + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * ROUT = array of length 6 for real optional outputs + * IPAR = array with user integer data + * (declare as INTEGER*4 or INTEGER*8 according to C type long int) + * RPAR = array with user real data + * IER = return completion flag. Values are 0 = SUCCESS, and -1 = failure. + * See printed message for details in case of failure. + * + * The user data arrays IPAR and RPAR are passed unmodified to all subsequent + * calls to user-provided routines. Modifications to either array inside a + * user-provided routine will be propagated. Using these two arrays, the user + * can dispense with Common blocks to pass data betwen user-provided routines. + * + * The optional outputs are: + * LENRW = IOUT( 1) from CVodeGetWorkSpace + * LENIW = IOUT( 2) from CVodeGetWorkSpace + * NST = IOUT( 3) from CVodeGetNumSteps + * NFE = IOUT( 4) from CVodeGetNumRhsEvals + * NETF = IOUT( 5) from CVodeGetNumErrTestFails + * NCFN = IOUT( 6) from CVodeGetNumNonlinSolvConvFails + * NNI = IOUT( 7) from CVodeGetNumNonlinSolvIters + * NSETUPS = IOUT( 8) from CVodeGetNumLinSolvSetups + * QU = IOUT( 9) from CVodeGetLastOrder + * QCUR = IOUT(10) from CVodeGetCurrentOrder + * NOR = IOUT(11) from CVodeGetNumStabLimOrderReds + * NGE = IOUT(12) from CVodeGetNumGEvals + * + * H0U = ROUT( 1) from CVodeGetActualInitStep + * HU = ROUT( 2) from CVodeGetLastStep + * HCUR = ROUT( 3) from CVodeGetCurrentStep + * TCUR = ROUT( 4) from CVodeGetCurrentTime + * TOLSF = ROUT( 5) from CVodeGetTolScaleFactor + * UROUND = ROUT( 6) from UNIT_ROUNDOFF + * See the CVODE manual for details. + * + * If the user program includes the FCVEWT routine for the evaluation of the + * error weights, the following call must be made + * CALL FCVEWTSET(FLAG, IER) + * with FLAG = 1 to specify that FCVEWT is provided. + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * (8.3) To re-initialize the CVODE solver for the solution of a new problem + * of the same size as one already solved, make the following call: + * CALL FCVREINIT(T0, Y0, IATOL, RTOL, ATOL, IER) + * The arguments have the same names and meanings as those of FCVMALLOC, + * except that METH and ITMETH have been omitted from the argument list + * (being unchanged for the new problem). + * FCVREINIT performs the same initializations as FCVMALLOC, but does no memory + * allocation, using instead the existing internal memory created by the + * previous FCVMALLOC call. The call to specify the linear system solution + * method may or may not be needed; see paragraph (7) below. + * + * (8.4) To set various integer optional inputs, make the folowing call: + * CALL FCVSETIIN(KEY, VALUE, IER) + * to set the integer value VAL to the optional input specified by the + * quoted character string KEY. + * KEY is one of the following: MAX_ORD, MAX_NSTEPS, MAX_ERRFAIL, MAX_NITERS, + * MAX_CONVFAIL, HNIL_WARNS, STAB_LIM. + * + * To set various real optional inputs, make the folowing call: + * CALL FCVSETRIN(KEY, VALUE, IER) + * to set the real value VAL to the optional input specified by the + * quoted character string KEY. + * KEY is one of the following: INIT_STEP, MAX_STEP, MIN_STEP, STOP_TIME, + * NLCONV_COEF. + * + * FCVSETIIN and FCVSETRIN return IER = 0 if successful and IER < 0 if an + * error occured. + * + * ----------------------------------------------------------------------------- + * + * (9) Specification of linear system solution method. + * In the case of a stiff system, the implicit BDF method involves the solution + * of linear systems related to the Jacobian J = df/dy of the ODE system. + * CVODE presently includes four choices for the treatment of these systems, + * and the user of FCVODE must call a routine with a specific name to make the + * desired choice. + * + * (9.1) Diagonal approximate Jacobian. + * This choice is appropriate when the Jacobian can be well approximated by + * a diagonal matrix. The user must make the call: + * CALL FCVDIAG(IER) + * IER is an error return flag: 0 = success, negative value = error. + * There is no additional user-supplied routine. + * + * Optional outputs specific to the DIAG case are: + * LENRWLS = IOUT(13) from CVDiagGetWorkSpace + * LENIWLS = IOUT(14) from CVDiagGetWorkSpace + * LSTF = IOUT(15) from CVDiagGetLastFlag + * NFELS = IOUT(16) from CVDiagGetNumRhsEvals + * See the CVODE manual for descriptions. + * + * (9.2s) DENSE treatment of the linear system. + * The user must make the call + * CALL FCVDENSE(NEQ, IER) + * The argument is: + * IER = error return flag: 0 = success , negative value = an error occured + * + * If the user program includes the FCVDJAC routine for the evaluation of the + * dense approximation to the Jacobian, the following call must be made + * CALL FCVDENSESETJAC(FLAG, IER) + * with FLAG = 1 to specify that FCVDJAC is provided. (FLAG = 0 specifies + * using the internal finite differences approximation to the Jacobian.) + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * Optional outputs specific to the DENSE case are: + * LENRWLS = IOUT(13) from CVDenseGetWorkSpace + * LENIWLS = IOUT(14) from CVDenseGetWorkSpace + * LSTF = IOUT(15) from CVDenseGetLastFlag + * NFELS = IOUT(16) from CVDenseGetNumRhsEvals + * NJED = IOUT(17) from CVDenseGetNumJacEvals + * See the CVODE manual for descriptions. + * + * (9.3s) BAND treatment of the linear system + * The user must make the call + * CALL FCVBAND(NEQ, MU, ML, IER) + * The arguments are: + * MU = upper bandwidth + * ML = lower bandwidth + * IER = error return flag: 0 = success , negative value = an error occured + * + * If the user program includes the FCVBJAC routine for the evaluation of the + * band approximation to the Jacobian, the following call must be made + * CALL FCVBANDSETJAC(FLAG, IER) + * with FLAG = 1 to specify that FCVBJAC is provided. (FLAG = 0 specifies + * using the internal finite differences approximation to the Jacobian.) + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * Optional outputs specific to the BAND case are: + * LENRWLS = IOUT(13) from CVBandGetWorkSpace + * LENIWLS = IOUT(14) from CVBandGetWorkSpace + * LSTF = IOUT(15) from CVBandGetLastFlag + * NFELS = IOUT(16) from CVBandGetNumRhsEvals + * NJEB = IOUT(17) from CVBandGetNumJacEvals + * See the CVODE manual for descriptions. + * + * (9.4s) LAPACK dense treatment of the linear system + * The user must make the call + * CALL FCVLAPACKDENSE(NEQ, IER) + * and, optionally + * CALL FCVLAPACKDENSESETJAC(FLAG, IER) + * with FLAG=1 if the user provides the function FCVLDJAC. + * See (9.2s) for more details. + * + * (9.5s) LAPACK band treatment of the linear system + * The user must make the call + * CALL FCVLAPACKBAND(NEQ, IER) + * and, optionally + * CALL FCVLAPACKBANDSETJAC(FLAG, IER) + * with FLAG=1 if the user provides the function FCVLBJAC. + * See (9.3s) + * + * (9.6) SPGMR treatment of the linear systems. + * For the Scaled Preconditioned GMRES solution of the linear systems, + * the user must make the following call: + * CALL FCVSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER) + * The arguments are: + * IPRETYPE = preconditioner type: + * 0 = none + * 1 = left only + * 2 = right only + * 3 = both sides + * IGSTYPE = Gram-schmidt process type: + * 1 = modified G-S + * 2 = classical G-S. + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * DELT = linear convergence tolerance factor; 0.0 indicates default. + * IER = error return flag: 0 = success; negative value = an error occured + * + * + * Optional outputs specific to the SPGMR case are: + * LENRWLS = IOUT(13) from CVSpgmrGetWorkSpace + * LENIWLS = IOUT(14) from CVSpgmrGetWorkSpace + * LSTF = IOUT(15) from CVSpgmrGetLastFlag + * NFELS = IOUT(16) from CVSpgmrGetRhsEvals + * NJTV = IOUT(17) from CVSpgmrGetJtimesEvals + * NPE = IOUT(18) from CVSpgmrGetPrecEvals + * NPS = IOUT(19) from CVSpgmrGetPrecSolves + * NLI = IOUT(20) from CVSpgmrGetLinIters + * NCFL = IOUT(21) from CVSpgmrGetConvFails + * See the CVODE manual for descriptions. + * + * If a sequence of problems of the same size is being solved using the + * SPGMR linear solver, then following the call to FCVREINIT, a call to the + * FCVSPGMRREINIT routine is needed if any of IPRETYPE, IGSTYPE, DELT is + * being changed. In that case, call FCVSPGMRREINIT as follows: + * CALL FCVSPGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER) + * The arguments have the same meanings as for FCVSPGMR. If MAXL is being + * changed, then call FCVSPGMR instead. + * + * (9.7) SPBCG treatment of the linear systems. + * For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems, + * the user must make the following call: + * CALL FCVSPBCG(IPRETYPE, MAXL, DELT, IER) + * The arguments are: + * IPRETYPE = preconditioner type: + * 0 = none + * 1 = left only + * 2 = right only + * 3 = both sides + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * DELT = linear convergence tolerance factor; 0.0 indicates default. + * IER = error return flag: 0 = success; negative value = an error occured + * + * Optional outputs specific to the SPBCG case are: + * LENRWLS = IOUT(13) from CVSpbcgGetWorkSpace + * LENIWLS = IOUT(14) from CVSpbcgGetWorkSpace + * LSTF = IOUT(15) from CVSpbcgGetLastFlag + * NFELS = IOUT(16) from CVSpbcgGetRhsEvals + * NJTV = IOUT(17) from CVSpbcgGetJtimesEvals + * NPE = IOUT(18) from CVSpbcgGetPrecEvals + * NPS = IOUT(19) from CVSpbcgGetPrecSolves + * NLI = IOUT(20) from CVSpbcgGetLinIters + * NCFL = IOUT(21) from CVSpbcgGetConvFails + * See the CVODE manual for descriptions. + * + * If a sequence of problems of the same size is being solved using the + * SPBCG linear solver, then following the call to FCVREINIT, a call to the + * FCVSPBCGREINIT routine is needed if any of its arguments is + * being changed. The call is: + * CALL FCVSPBCGREINIT(IPRETYPE, MAXL, DELT, IER) + * The arguments have the same meanings as for FCVSPBCG. + * + * (9.8) SPTFQMR treatment of the linear systems. + * For the Scaled Preconditioned TFQMR solution of the linear systems, + * the user must make the following call: + * CALL FCVSPTFQMR(IPRETYPE, MAXL, DELT, IER) + * The arguments are: + * IPRETYPE = preconditioner type: + * 0 = none + * 1 = left only + * 2 = right only + * 3 = both sides + * MAXL = maximum Krylov subspace dimension; 0 indicates default. + * DELT = linear convergence tolerance factor; 0.0 indicates default. + * IER = error return flag: 0 = success; negative value = an error occured + * + * Optional outputs specific to the SPTFQMR case are: + * LENRWLS = IOUT(13) from CVSptfqmrGetWorkSpace + * LENIWLS = IOUT(14) from CVSptfqmrGetWorkSpace + * LSTF = IOUT(15) from CVSptfqmrGetLastFlag + * NFELS = IOUT(16) from CVSptfqmrGetRhsEvals + * NJTV = IOUT(17) from CVSptfqmrGetJtimesEvals + * NPE = IOUT(18) from CVSptfqmrGetPrecEvals + * NPS = IOUT(19) from CVSptfqmrGetPrecSolves + * NLI = IOUT(20) from CVSptfqmrGetLinIters + * NCFL = IOUT(21) from CVSptfqmrGetConvFails + * See the CVODE manual for descriptions. + * + * If a sequence of problems of the same size is being solved using the + * SPTFQMR linear solver, then following the call to FCVREINIT, a call to the + * FCVSPTFQMRREINIT routine is needed if any of its arguments is + * being changed. The call is: + * CALL FCVSPTFQMRREINIT(IPRETYPE, MAXL, DELT, IER) + * The arguments have the same meanings as for FCVSPTFQMR. + * + * (9.9) Usage of user-supplied routines for the Krylov solvers + * + * If the user program includes the FCVJTIMES routine for the evaluation of the + * Jacobian vector product, the following call must be made + * CALL FCVSPILSSETJAC(FLAG, IER) + * with FLAG = 1 to specify that FCVJTIMES is provided. (FLAG = 0 specifies + * using and internal finite difference approximation to this product.) + * The return flag IER is 0 if successful, and nonzero otherwise. + * + * Usage of the user-supplied routines FCVPSOL and FCVPSET for solution of the + * preconditioner linear system requires the following call: + * CALL FCVSPILSSETPREC(FLAG, IER) + * with FLAG = 1. The return flag IER is 0 if successful, nonzero otherwise. + * The user-supplied routine FCVPSOL must have the form: + * SUBROUTINE FCVPSOL (T,Y,FY,R,Z,GAMMA,DELTA,LR,IPAR,RPAR,VT,IER) + * DIMENSION Y(*), FY(*), VT(*), R(*), Z(*), IPAR(*), RPAR(*) + * Typically this routine will use only NEQ, T, Y, GAMMA, R, LR, and Z. It + * must solve the preconditioner linear system Pz = r, where r = R is input, + * and store the solution z in Z. Here P is the left preconditioner if LR = 1 + * and the right preconditioner if LR = 2. The preconditioner (or the product + * of the left and right preconditioners if both are nontrivial) should be an + * approximation to the matrix I - GAMMA*J (I = identity, J = Jacobian). + * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC. + * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred, + * and IER < 0 if an unrecoverable error ocurred. + * + * ----------------------------------------------------------------------------- + * + * (10) The integrator: FCVODE + * Carrying out the integration is accomplished by making calls as follows: + * CALL FCVODE (TOUT, T, Y, ITASK, IER) + * The arguments are: + * TOUT = next value of t at which a solution is desired (input) + * T = value of t reached by the solver on output + * Y = array containing the computed solution on output + * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate) + * 2 = one-step mode (return after each internal step taken) + * 3 = normal tstop mode (like 1, but integration never proceeds past + * TSTOP, which must be specified through a call to FCVSETRIN + * using the key 'STOP_TIME') + * 4 = one step tstop (like 2, but integration never goes past TSTOP) + * IER = completion flag: 0 = success, 1 = tstop return, 2 = root return, + * values -1 ... -10 are various failure modes (see CVODE manual). + * The current values of the optional outputs are available in IOUT and ROUT. + * + * ----------------------------------------------------------------------------- + * + * (11) Computing solution derivatives: FCVDKY + * To obtain a derivative of the solution, of order up to the current method + * order, make the following call: + * CALL FCVDKY (T, K, DKY, IER) + * The arguments are: + * T = value of t at which solution derivative is desired, in [TCUR-HU,TCUR]. + * K = derivative order (0 .le. K .le. QU) + * DKY = array containing computed K-th derivative of y on return + * IER = return flag: = 0 for success, < 0 for illegal argument. + * + * ----------------------------------------------------------------------------- + * + * (12) Memory freeing: FCVFREE + * To free the internal memory created by the calls to FCVMALLOC and + * FNVINITS or FNVINITP, make the call + * CALL FCVFREE + * + * ============================================================================= + */ + +#ifndef _FCVODE_H +#define _FCVODE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* header files */ + +#include +#include /* definition of type DlsMat */ +#include /* definition of type N_Vector */ +#include /* definition of type realtype */ + +/* Definitions of interface function names */ + +#if defined(SUNDIALS_F77_FUNC) + +#define FCV_MALLOC SUNDIALS_F77_FUNC(fcvmalloc, FCVMALLOC) +#define FCV_REINIT SUNDIALS_F77_FUNC(fcvreinit, FCVREINIT) +#define FCV_SETIIN SUNDIALS_F77_FUNC(fcvsetiin, FCVSETIIN) +#define FCV_SETRIN SUNDIALS_F77_FUNC(fcvsetrin, FCVSETRIN) +#define FCV_EWTSET SUNDIALS_F77_FUNC(fcvewtset, FCVEWTSET) +#define FCV_DIAG SUNDIALS_F77_FUNC(fcvdiag, FCVDIAG) +#define FCV_DENSE SUNDIALS_F77_FUNC(fcvdense, FCVDENSE) +#define FCV_DENSESETJAC SUNDIALS_F77_FUNC(fcvdensesetjac, FCVDENSESETJAC) +#define FCV_BAND SUNDIALS_F77_FUNC(fcvband, FCVBAND) +#define FCV_BANDSETJAC SUNDIALS_F77_FUNC(fcvbandsetjac, FCVBANDSETJAC) +#define FCV_LAPACKDENSE SUNDIALS_F77_FUNC(fcvlapackdense, FCVLAPACKDENSE) +#define FCV_LAPACKDENSESETJAC SUNDIALS_F77_FUNC(fcvlapackdensesetjac, FCVLAPACKDENSESETJAC) +#define FCV_LAPACKBAND SUNDIALS_F77_FUNC(fcvlapackband, FCVLAPACKBAND) +#define FCV_LAPACKBANDSETJAC SUNDIALS_F77_FUNC(fcvlapackbandsetjac, FCVLAPACKBANDSETJAC) +#define FCV_SPTFQMR SUNDIALS_F77_FUNC(fcvsptfqmr, FCVSPTFQMR) +#define FCV_SPTFQMRREINIT SUNDIALS_F77_FUNC(fcvsptfqmrreinit, FCVSPTFQMRREINIT) +#define FCV_SPBCG SUNDIALS_F77_FUNC(fcvspbcg, FCVSPBCG) +#define FCV_SPBCGREINIT SUNDIALS_F77_FUNC(fcvspbcgreinit, FCVSPBCGREINIT) +#define FCV_SPGMR SUNDIALS_F77_FUNC(fcvspgmr, FCVSPGMR) +#define FCV_SPGMRREINIT SUNDIALS_F77_FUNC(fcvspgmrreinit, FCVSPGMRREINIT) +#define FCV_SPILSSETJAC SUNDIALS_F77_FUNC(fcvspilssetjac, FCVSPILSSETJAC) +#define FCV_SPILSSETPREC SUNDIALS_F77_FUNC(fcvspilssetprec, FCVSPILSSETPREC) +#define FCV_CVODE SUNDIALS_F77_FUNC(fcvode, FCVODE) +#define FCV_DKY SUNDIALS_F77_FUNC(fcvdky, FCVDKY) +#define FCV_FREE SUNDIALS_F77_FUNC(fcvfree, FCVFREE) +#define FCV_FUN SUNDIALS_F77_FUNC(fcvfun, FCVFUN) +#define FCV_DJAC SUNDIALS_F77_FUNC(fcvdjac, FCVDJAC) +#define FCV_BJAC SUNDIALS_F77_FUNC(fcvbjac, FCVBJAC) +#define FCV_PSOL SUNDIALS_F77_FUNC(fcvpsol, FCVPSOL) +#define FCV_PSET SUNDIALS_F77_FUNC(fcvpset, FCVPSET) +#define FCV_JTIMES SUNDIALS_F77_FUNC(fcvjtimes, FCVJTIMES) +#define FCV_EWT SUNDIALS_F77_FUNC(fcvewt, FCVEWT) +#define FCV_GETERRWEIGHTS SUNDIALS_F77_FUNC(fcvgeterrweights, FCVGETERRWEIGHTS) +#define FCV_GETESTLOCALERR SUNDIALS_F77_FUNC(fcvgetestlocalerr, FCVGETESTLOCALERR) + +#else + +#define FCV_MALLOC fcvmalloc_ +#define FCV_REINIT fcvreinit_ +#define FCV_SETIIN fcvsetiin_ +#define FCV_SETRIN fcvsetrin_ +#define FCV_EWTSET fcvewtset_ +#define FCV_DIAG fcvdiag_ +#define FCV_DENSE fcvdense_ +#define FCV_DENSESETJAC fcvdensesetjac_ +#define FCV_BAND fcvband_ +#define FCV_BANDSETJAC fcvbandsetjac_ +#define FCV_LAPACKDENSE fcvlapackdense_ +#define FCV_LAPACKDENSESETJAC fcvlapackdensesetjac_ +#define FCV_LAPACKBAND fcvlapackband_ +#define FCV_LAPACKBANDSETJAC fcvlapackbandsetjac_ +#define FCV_SPTFQMR fcvsptfqmr_ +#define FCV_SPTFQMRREINIT fcvsptfqmrreinit_ +#define FCV_SPBCG fcvspbcg_ +#define FCV_SPBCGREINIT fcvspbcgreinit_ +#define FCV_SPGMR fcvspgmr_ +#define FCV_SPGMRREINIT fcvspgmrreinit_ +#define FCV_SPILSSETJAC fcvspilssetjac_ +#define FCV_SPILSSETPREC fcvspilssetprec_ +#define FCV_CVODE fcvode_ +#define FCV_DKY fcvdky_ +#define FCV_FREE fcvfree_ +#define FCV_FUN fcvfun_ +#define FCV_DJAC fcvdjac_ +#define FCV_BJAC fcvbjac_ +#define FCV_PSOL fcvpsol_ +#define FCV_PSET fcvpset_ +#define FCV_JTIMES fcvjtimes_ +#define FCV_EWT fcvewt_ +#define FCV_GETERRWEIGHTS fcvgeterrweights_ +#define FCV_GETESTLOCALERR fcvgetestlocalerr_ + +#endif + + /* Type for user data */ + + typedef struct { + realtype *rpar; + long int *ipar; + } *FCVUserData; + + /* Prototypes of exported functions */ + + void FCV_MALLOC(realtype *t0, realtype *y0, + int *meth, int *itmeth, int *iatol, + realtype *rtol, realtype *atol, + long int *iout, realtype *rout, + long int *ipar, realtype *rpar, + int *ier); + + void FCV_REINIT(realtype *t0, realtype *y0, + int *iatol, realtype *rtol, realtype *atol, + int *ier); + + void FCV_SETIIN(char key_name[], long int *ival, int *ier, int key_len); + + void FCV_SETRIN(char key_name[], realtype *rval, int *ier, int key_len); + + void FCV_EWTSET(int *flag, int *ier); + + void FCV_DIAG(int *ier); + + void FCV_DENSE(long int *neq, int *ier); + void FCV_DENSESETJAC(int *flag, int *ier); + + void FCV_BAND(long int *neq, long int *mupper, long int *mlower, int *ier); + void FCV_BANDSETJAC(int *flag, int *ier); + + void FCV_LAPACKDENSE(int *neq, int *ier); + void FCV_LAPACKDENSESETJAC(int *flag, int *ier); + void FCV_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier); + void FCV_LAPACKBANDSETJAC(int *flag, int *ier); + + void FCV_SPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier); + void FCV_SPGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier); + + void FCV_SPBCG(int *pretype, int *maxl, realtype *delt, int *ier); + void FCV_SPBCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier); + + void FCV_SPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier); + void FCV_SPTFQMRREINIT(int *pretype, int *maxl, realtype *delt, int *ier); + + void FCV_SPILSSETJAC(int *flag, int *ier); + void FCV_SPILSSETPREC(int *flag, int *ier); + + void FCV_CVODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier); + + void FCV_DKY(realtype *t, int *k, realtype *dky, int *ier); + + void FCV_GETERRWEIGHTS(realtype *eweight, int *ier); + void FCV_GETESTLOCALERR(realtype *ele, int *ier); + + void FCV_FREE(void); + + + /* Prototypes: Functions Called by the CVODE Solver */ + + int FCVf(realtype t, N_Vector y, N_Vector ydot, void *user_data); + + int FCVDenseJac(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + + int FCVBandJac(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat J, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + + int FCVLapackDenseJac(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + int FCVLapackBandJac(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + + int FCVPSet(realtype tn, N_Vector y,N_Vector fy, booleantype jok, + booleantype *jcurPtr, realtype gamma, void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); + + int FCVPSol(realtype tn, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *user_data, N_Vector vtemp); + + int FCVJtimes(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *user_data, N_Vector work); + + int FCVEwtSet(N_Vector y, N_Vector ewt, void *user_data); + + /* Declarations for global variables shared amongst various routines */ + + extern N_Vector F2C_CVODE_vec; /* defined in FNVECTOR module */ + + extern void *CV_cvodemem; /* defined in fcvode.c */ + extern long int *CV_iout; /* defined in fcvode.c */ + extern realtype *CV_rout; /* defined in fcvode.c */ + extern int CV_nrtfn; /* defined in fcvode.c */ + extern int CV_ls; /* defined in fcvode.c */ + + /* Linear solver IDs */ + + enum { CV_LS_DENSE = 1, CV_LS_BAND = 2, CV_LS_DIAG = 3, + CV_LS_LAPACKDENSE = 4, CV_LS_LAPACKBAND = 5, + CV_LS_SPGMR = 6, CV_LS_SPBCG = 7, CV_LS_SPTFQMR = 8 }; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvpreco.c b/dep/cvode-2.7.0/cvode/fcmix/fcvpreco.c new file mode 100644 index 00000000..eb4203ea --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvpreco.c @@ -0,0 +1,136 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:28:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh, Radu Serban and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * The C function FCVPSet is to interface between the CVSP* + * module and the user-supplied preconditioner setup routine FCVPSET. + * Note the use of the generic name FCV_PSET below. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global vars.*/ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +#include + +/*********************************************************************/ + +/* Prototype of the Fortran routines */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + + extern void FCV_PSET(realtype*, realtype*, realtype*, /* T, Y, FY */ + booleantype*, booleantype*, /* JOK, JCUR */ + realtype*, realtype*, /* GAMMA, H */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, realtype*, realtype*, /* W1, W2, W3 */ + int*); /* IER */ + + extern void FCV_PSOL(realtype*, realtype*, realtype*, /* T, Y, FY */ + realtype*, realtype*, /* R, Z */ + realtype*, realtype*, /* GAMMA, DELTA */ + int*, /* LR */ + long int*, realtype*, /* IPAR, RPAR */ + realtype*, /* WRK */ + int*); /* IER */ + +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_SPILSSETPREC(int *flag, int *ier) +{ + CVodeMem cv_mem; + + if (*flag == 0) { + *ier = CVSpilsSetPreconditioner(CV_cvodemem, NULL, NULL); + } else { + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVSpilsSetPreconditioner(CV_cvodemem, FCVPSet, FCVPSol); + } +} + +/***************************************************************************/ + +/* C function FCVPSet to interface between CVODE and a Fortran subroutine + FCVPSET for setup of a Krylov preconditioner. + Addresses of t, y, fy, jok, gamma, h, vtemp1, vtemp2, vtemp3, and the + address jcurPtr are passed to FCVPSET, using the routine + N_VGetArrayPointer from NVECTOR. + A return flag ier from FCVPSET is returned by FCVPSet. + Auxiliary data is assumed to be communicated by common blocks. */ + +int FCVPSet(realtype t, N_Vector y, N_Vector fy, booleantype jok, + booleantype *jcurPtr, realtype gamma, + void *user_data, + N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) +{ + int ier = 0; + realtype *ydata, *fydata, *v1data, *v2data, *v3data; + realtype h; + FCVUserData CV_userdata; + + CVodeGetLastStep(CV_cvodemem, &h); + + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + v1data = N_VGetArrayPointer(vtemp1); + v2data = N_VGetArrayPointer(vtemp2); + v3data = N_VGetArrayPointer(vtemp3); + + CV_userdata = (FCVUserData) user_data; + + FCV_PSET(&t, ydata, fydata, &jok, jcurPtr, &gamma, &h, + CV_userdata->ipar, CV_userdata->rpar, + v1data, v2data, v3data, &ier); + + return(ier); +} + +/***************************************************************************/ + +/* C function FCVPSol to interface between CVODE and a Fortran subroutine + FCVPSOL for solution of a Krylov preconditioner. + Addresses of t, y, fy, gamma, delta, lr, vtemp, r, and z are + passed to FCVPSOL, using the routine N_VGetArrayPointer from NVECTOR. + A return flag ier from FCVPSOL is returned by FCVPSol. + Auxiliary data is assumed to be communicated by Common blocks. */ + +int FCVPSol(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *user_data, N_Vector vtemp) +{ + int ier = 0; + realtype *ydata, *fydata, *vtdata, *rdata, *zdata; + FCVUserData CV_userdata; + + ydata = N_VGetArrayPointer(y); + fydata = N_VGetArrayPointer(fy); + vtdata = N_VGetArrayPointer(vtemp); + rdata = N_VGetArrayPointer(r); + zdata = N_VGetArrayPointer(z); + + CV_userdata = (FCVUserData) user_data; + + FCV_PSOL(&t, ydata, fydata, rdata, zdata, &gamma, &delta, &lr, + CV_userdata->ipar, CV_userdata->rpar, vtdata, &ier); + + return(ier); +} diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvroot.c b/dep/cvode-2.7.0/cvode/fcmix/fcvroot.c new file mode 100644 index 00000000..1317f198 --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvroot.c @@ -0,0 +1,86 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/30 19:28:59 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * The FCVROOT module contains the routines necessary to use + * the rootfinding feature of the CVODE module and to interface + * with the user-supplied Fortran subroutine. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fcvode.h" /* actual fn. names, prototypes and global variables */ +#include "fcvroot.h" /* prototypes of interfaces to CVODE */ +#include "cvode_impl.h" /* definition of CVodeMem type */ + +/***************************************************************************/ + +/* Prototype of the Fortran routine */ + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + extern void FCV_ROOTFN(realtype *, realtype*, realtype*, /* T, Y, G */ + long int*, realtype*, /* IPAR, RPAR */ + int *ier); /* IER */ +#ifdef __cplusplus +} +#endif + +/***************************************************************************/ + +void FCV_ROOTINIT(int *nrtfn, int *ier) +{ + CVodeMem cv_mem; + + cv_mem = (CVodeMem) CV_cvodemem; + *ier = CVodeRootInit(CV_cvodemem, *nrtfn, (CVRootFn) FCVrootfunc); + CV_nrtfn = *nrtfn; + + return; +} + +/***************************************************************************/ + +void FCV_ROOTINFO(int *nrtfn, int *info, int *ier) +{ + *ier = CVodeGetRootInfo(CV_cvodemem, info); + return; +} + +/***************************************************************************/ + +void FCV_ROOTFREE(void) +{ + CVodeRootInit(CV_cvodemem, 0, NULL); + + return; +} + +/***************************************************************************/ + +int FCVrootfunc(realtype t, N_Vector y, realtype *gout, void *user_data) +{ + int ier; + realtype *ydata; + FCVUserData CV_userdata; + + ydata = N_VGetArrayPointer(y); + + CV_userdata = (FCVUserData) user_data; + + FCV_ROOTFN(&t, ydata, gout, CV_userdata->ipar, CV_userdata->rpar, &ier); + + return(ier); +} + diff --git a/dep/cvode-2.7.0/cvode/fcmix/fcvroot.h b/dep/cvode-2.7.0/cvode/fcmix/fcvroot.h new file mode 100644 index 00000000..5733189e --- /dev/null +++ b/dep/cvode-2.7.0/cvode/fcmix/fcvroot.h @@ -0,0 +1,140 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.5 $ + * $Date: 2010/12/15 19:40:08 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the Fortran interface include file for the rootfinding + * feature of CVODE. + * ----------------------------------------------------------------- + */ + +/* + * ============================================================================== + * + * FCVROOT Interface Package + * + * The FCVROOT interface package allows programs written in FORTRAN to + * use the rootfinding feature of the CVODE solver module. + * + * The user-callable functions constituting the FCVROOT package are the + * following: FCVROOTINIT, FCVROOTINFO, and FCVROOTFREE. The corresponding + * CVODE subroutine called by each interface function is given below. + * + * ----------------- ----------------------- + * | FCVROOT routine | | CVODE function called | + * ----------------- ----------------------- + * FCVROOTINIT -> CVodeRootInit + * FCVROOTINFO -> CVodeGetRootInfo + * FCVROOTFREE -> CVodeRootInit + * + * FCVROOTFN is a user-supplied subroutine defining the functions whose + * roots are sought. + * + * ============================================================================== + * + * Usage of the FCVROOT Interface Package + * + * 1. In order to use the rootfinding feature of the CVODE package the user must + * define the following subroutine: + * + * SUBROUTINE FCVROOTFN (T, Y, G, IPAR, RPAR, IER) + * DIMENSION Y(*), G(*), IPAR(*), RPAR(*) + * + * The arguments are: + * T = independent variable value t [input] + * Y = dependent variable vector y [input] + * G = function values g(t,y) [output] + * IPAR, RPAR = user (integer and real) data [input/output] + * IER = return flag (0 for success, a non-zero value if an error occurred.) + * + * 2. After calling FCVMALLOC but prior to calling FCVODE, the user must + * allocate and initialize memory for the FCVROOT module by making the + * following call: + * + * CALL FCVROOTINIT (NRTFN, IER) + * + * The arguments are: + * NRTFN = total number of root functions [input] + * IER = return completion flag (0 = success, -1 = CVODE memory NULL and + * -11 memory allocation error) [output] + * + * 3. After calling FCVODE, to see whether a root was found, test the FCVODE + * return flag IER. The value IER = 2 means one or more roots were found. + * + * 4. If a root was found, and if NRTFN > 1, then to determine which root + * functions G(*) were found to have a root, make the following call: + * CALL FCVROOTINFO (NRTFN, INFO, IER) + * The arguments are: + * NRTFN = total number of root functions [input] + * INFO = integer array of length NRTFN, with values 0 or 1 [output] + * For i = 1,...,NRTFN, G(i) was found to have a root if INFO(i) = 1. + * IER = completion flag (0 = success, negative = failure) + * + * 5. The total number of calls made to the root function (FCVROOTFN), NGE, + * can be obtained from IOUT(12). + * + * If the FCVODE/CVODE memory block is reinitialized to solve a different + * problem via a call to FCVREINIT, then the counter variable NGE is cleared + * (reset to zero). + * + * 6. To free the memory resources allocated by a prior call to FCVROOTINIT make + * the following call: + * CALL FCVROOTFREE + * See the CVODE documentation for additional information. + * + * ============================================================================== + */ + +#ifndef _FCVROOT_H +#define _FCVROOT_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* header files */ + +#include /* definition of type N_Vector */ +#include /* definition of SUNDIALS type realtype */ + +/* Definitions of interface function names */ + +#if defined(SUNDIALS_F77_FUNC) + +#define FCV_ROOTINIT SUNDIALS_F77_FUNC(fcvrootinit, FCVROOTINIT) +#define FCV_ROOTINFO SUNDIALS_F77_FUNC(fcvrootinfo, FCVROOTINFO) +#define FCV_ROOTFREE SUNDIALS_F77_FUNC(fcvrootfree, FCVROOTFREE) +#define FCV_ROOTFN SUNDIALS_F77_FUNC(fcvrootfn, FCVROOTFN) + +#else + +#define FCV_ROOTINIT fcvrootinit_ +#define FCV_ROOTINFO fcvrootinfo_ +#define FCV_ROOTFREE fcvrootfree_ +#define FCV_ROOTFN fcvrootfn_ + +#endif + +/* Prototypes of exported function */ + +void FCV_ROOTINIT(int *nrtfn, int *ier); +void FCV_ROOTINFO(int *nrtfn, int *info, int *ier); +void FCV_ROOTFREE(void); + +/* Prototype of function called by CVODE module */ + +int FCVrootfunc(realtype t, N_Vector y, realtype *gout, void *user_data); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode.h b/dep/cvode-2.7.0/include/cvode/cvode.h new file mode 100644 index 00000000..e7832567 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode.h @@ -0,0 +1,790 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.13 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban + * and Dan Shumaker @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the interface file for the main CVODE integrator. + * ----------------------------------------------------------------- + * + * CVODE is used to solve numerically the ordinary initial value + * problem: + * + * y' = f(t,y), + * y(t0) = y0, + * + * where t0, y0 in R^N, and f: R x R^N -> R^N are given. + * + * ----------------------------------------------------------------- + */ + +#ifndef _CVODE_H +#define _CVODE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + +/* + * ================================================================= + * C V O D E C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Enumerations for inputs to CVodeCreate and CVode. + * ----------------------------------------------------------------- + * Symbolic constants for the lmm and iter parameters to CVodeCreate + * and the input parameter itask to CVode, are given below. + * + * lmm: The user of the CVODE package specifies whether to use the + * CV_ADAMS (Adams-Moulton) or CV_BDF (Backward Differentiation + * Formula) linear multistep method. The BDF method is + * recommended for stiff problems, and the CV_ADAMS method is + * recommended for nonstiff problems. + * + * iter: At each internal time step, a nonlinear equation must + * be solved. The user can specify either CV_FUNCTIONAL + * iteration, which does not require linear algebra, or a + * CV_NEWTON iteration, which requires the solution of linear + * systems. In the CV_NEWTON case, the user also specifies a + * CVODE linear solver. CV_NEWTON is recommended in case of + * stiff problems. + * + * itask: The itask input parameter to CVode indicates the job + * of the solver for the next user step. The CV_NORMAL + * itask is to have the solver take internal steps until + * it has reached or just passed the user specified tout + * parameter. The solver then interpolates in order to + * return an approximate value of y(tout). The CV_ONE_STEP + * option tells the solver to just take one internal step + * and return the solution at the point reached by that step. + * ----------------------------------------------------------------- + */ + +/* lmm */ +#define CV_ADAMS 1 +#define CV_BDF 2 + +/* iter */ +#define CV_FUNCTIONAL 1 +#define CV_NEWTON 2 + +/* itask */ +#define CV_NORMAL 1 +#define CV_ONE_STEP 2 + +/* + * ---------------------------------------- + * CVODE return flags + * ---------------------------------------- + */ + +#define CV_SUCCESS 0 +#define CV_TSTOP_RETURN 1 +#define CV_ROOT_RETURN 2 + +#define CV_WARNING 99 + +#define CV_TOO_MUCH_WORK -1 +#define CV_TOO_MUCH_ACC -2 +#define CV_ERR_FAILURE -3 +#define CV_CONV_FAILURE -4 + +#define CV_LINIT_FAIL -5 +#define CV_LSETUP_FAIL -6 +#define CV_LSOLVE_FAIL -7 +#define CV_RHSFUNC_FAIL -8 +#define CV_FIRST_RHSFUNC_ERR -9 +#define CV_REPTD_RHSFUNC_ERR -10 +#define CV_UNREC_RHSFUNC_ERR -11 +#define CV_RTFUNC_FAIL -12 + +#define CV_MEM_FAIL -20 +#define CV_MEM_NULL -21 +#define CV_ILL_INPUT -22 +#define CV_NO_MALLOC -23 +#define CV_BAD_K -24 +#define CV_BAD_T -25 +#define CV_BAD_DKY -26 +#define CV_TOO_CLOSE -27 + +/* + * ================================================================= + * F U N C T I O N T Y P E S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Type : CVRhsFn + * ----------------------------------------------------------------- + * The f function which defines the right hand side of the ODE + * system y' = f(t,y) must have type CVRhsFn. + * f takes as input the independent variable value t, and the + * dependent variable vector y. It stores the result of f(t,y) + * in the vector ydot. The y and ydot arguments are of type + * N_Vector. + * (Allocation of memory for ydot is handled within CVODE) + * The user_data parameter is the same as the user_data + * parameter set by the user through the CVodeSetUserData routine. + * This user-supplied pointer is passed to the user's f function + * every time it is called. + * + * A CVRhsFn should return 0 if successful, a negative value if + * an unrecoverable error occured, and a positive value if a + * recoverable error (e.g. invalid y values) occured. + * If an unrecoverable occured, the integration is halted. + * If a recoverable error occured, then (in most cases) CVODE + * will try to correct and retry. + * ----------------------------------------------------------------- + */ + +typedef int (*CVRhsFn)(realtype t, N_Vector y, + N_Vector ydot, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVRootFn + * ----------------------------------------------------------------- + * A function g, which defines a set of functions g_i(t,y) whose + * roots are sought during the integration, must have type CVRootFn. + * The function g takes as input the independent variable value + * t, and the dependent variable vector y. It stores the nrtfn + * values g_i(t,y) in the realtype array gout. + * (Allocation of memory for gout is handled within CVODE.) + * The user_data parameter is the same as that passed by the user + * to the CVodeSetUserData routine. This user-supplied pointer is + * passed to the user's g function every time it is called. + * + * A CVRootFn should return 0 if successful or a non-zero value + * if an error occured (in which case the integration will be halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVRootFn)(realtype t, N_Vector y, realtype *gout, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVEwtFn + * ----------------------------------------------------------------- + * A function e, which sets the error weight vector ewt, must have + * type CVEwtFn. + * The function e takes as input the current dependent variable y. + * It must set the vector of error weights used in the WRMS norm: + * + * ||y||_WRMS = sqrt [ 1/N * sum ( ewt_i * y_i)^2 ] + * + * Typically, the vector ewt has components: + * + * ewt_i = 1 / (reltol * |y_i| + abstol_i) + * + * The user_data parameter is the same as that passed by the user + * to the CVodeSetUserData routine. This user-supplied pointer is + * passed to the user's e function every time it is called. + * A CVEwtFn e must return 0 if the error weight vector has been + * successfuly set and a non-zero value otherwise. + * ----------------------------------------------------------------- + */ + +typedef int (*CVEwtFn)(N_Vector y, N_Vector ewt, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVErrHandlerFn + * ----------------------------------------------------------------- + * A function eh, which handles error messages, must have type + * CVErrHandlerFn. + * The function eh takes as input the error code, the name of the + * module reporting the error, the error message, and a pointer to + * user data, the same as that passed to CVodeSetUserData. + * + * All error codes are negative, except CV_WARNING which indicates + * a warning (the solver continues). + * + * A CVErrHandlerFn has no return value. + * ----------------------------------------------------------------- + */ + +typedef void (*CVErrHandlerFn)(int error_code, + const char *module, const char *function, + char *msg, void *user_data); + +/* + * ================================================================= + * U S E R - C A L L A B L E R O U T I N E S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVodeCreate + * ----------------------------------------------------------------- + * CVodeCreate creates an internal memory block for a problem to + * be solved by CVODE. + * + * lmm is the type of linear multistep method to be used. + * The legal values are CV_ADAMS and CV_BDF (see previous + * description). + * + * iter is the type of iteration used to solve the nonlinear + * system that arises during each internal time step. + * The legal values are CV_FUNCTIONAL and CV_NEWTON. + * + * If successful, CVodeCreate returns a pointer to initialized + * problem memory. This pointer should be passed to CVodeInit. + * If an initialization error occurs, CVodeCreate prints an error + * message to standard err and returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter); + +/* + * ----------------------------------------------------------------- + * Integrator optional input specification functions + * ----------------------------------------------------------------- + * The following functions can be called to set optional inputs + * to values other than the defaults given below: + * + * Function | Optional input / [ default value ] + * ----------------------------------------------------------------- + * | + * CVodeSetErrHandlerFn | user-provided ErrHandler function. + * | [internal] + * | + * CVodeSetErrFile | the file pointer for an error file + * | where all CVODE warning and error + * | messages will be written if the default + * | internal error handling function is used. + * | This parameter can be stdout (standard + * | output), stderr (standard error), or a + * | file pointer (corresponding to a user + * | error file opened for writing) returned + * | by fopen. + * | If not called, then all messages will + * | be written to the standard error stream. + * | [stderr] + * | + * CVodeSetUserData | a pointer to user data that will be + * | passed to the user's f function every + * | time f is called. + * | [NULL] + * | + * CVodeSetMaxOrd | maximum lmm order to be used by the + * | solver. + * | [12 for Adams , 5 for BDF] + * | + * CVodeSetMaxNumSteps | maximum number of internal steps to be + * | taken by the solver in its attempt to + * | reach tout. + * | [500] + * | + * CVodeSetMaxHnilWarns | maximum number of warning messages + * | issued by the solver that t+h==t on the + * | next internal step. A value of -1 means + * | no such messages are issued. + * | [10] + * | + * CVodeSetStabLimDet | flag to turn on/off stability limit + * | detection (TRUE = on, FALSE = off). + * | When BDF is used and order is 3 or + * | greater, CVsldet is called to detect + * | stability limit. If limit is detected, + * | the order is reduced. + * | [FALSE] + * | + * CVodeSetInitStep | initial step size. + * | [estimated by CVODE] + * | + * CVodeSetMinStep | minimum absolute value of step size + * | allowed. + * | [0.0] + * | + * CVodeSetMaxStep | maximum absolute value of step size + * | allowed. + * | [infinity] + * | + * CVodeSetStopTime | the independent variable value past + * | which the solution is not to proceed. + * | [infinity] + * | + * CVodeSetMaxErrTestFails | Maximum number of error test failures + * | in attempting one step. + * | [7] + * | + * CVodeSetMaxNonlinIters | Maximum number of nonlinear solver + * | iterations at one solution. + * | [3] + * | + * CVodeSetMaxConvFails | Maximum number of convergence failures + * | allowed in attempting one step. + * | [10] + * | + * CVodeSetNonlinConvCoef | Coefficient in the nonlinear + * | convergence test. + * | [0.1] + * | + * ----------------------------------------------------------------- + * | + * CVodeSetIterType | Changes the current nonlinear iteration + * | type. + * | [set by CVodecreate] + * | + * ----------------------------------------------------------------- + * | + * CVodeSetRootDirection | Specifies the direction of zero + * | crossings to be monitored + * | [both directions] + * | + * CVodeSetNoInactiveRootWarn | disable warning about possible + * | g==0 at beginning of integration + * | + * ----------------------------------------------------------------- + + * ----------------------------------------------------------------- + * Return flag: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory is NULL + * CV_ILL_INPUT if an argument has an illegal value + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSetErrHandlerFn(void *cvode_mem, CVErrHandlerFn ehfun, void *eh_data); +SUNDIALS_EXPORT int CVodeSetErrFile(void *cvode_mem, FILE *errfp); +SUNDIALS_EXPORT int CVodeSetUserData(void *cvode_mem, void *user_data); +SUNDIALS_EXPORT int CVodeSetMaxOrd(void *cvode_mem, int maxord); +SUNDIALS_EXPORT int CVodeSetMaxNumSteps(void *cvode_mem, long int mxsteps); +SUNDIALS_EXPORT int CVodeSetMaxHnilWarns(void *cvode_mem, int mxhnil); +SUNDIALS_EXPORT int CVodeSetStabLimDet(void *cvode_mem, booleantype stldet); +SUNDIALS_EXPORT int CVodeSetInitStep(void *cvode_mem, realtype hin); +SUNDIALS_EXPORT int CVodeSetMinStep(void *cvode_mem, realtype hmin); +SUNDIALS_EXPORT int CVodeSetMaxStep(void *cvode_mem, realtype hmax); +SUNDIALS_EXPORT int CVodeSetStopTime(void *cvode_mem, realtype tstop); +SUNDIALS_EXPORT int CVodeSetMaxErrTestFails(void *cvode_mem, int maxnef); +SUNDIALS_EXPORT int CVodeSetMaxNonlinIters(void *cvode_mem, int maxcor); +SUNDIALS_EXPORT int CVodeSetMaxConvFails(void *cvode_mem, int maxncf); +SUNDIALS_EXPORT int CVodeSetNonlinConvCoef(void *cvode_mem, realtype nlscoef); + +SUNDIALS_EXPORT int CVodeSetIterType(void *cvode_mem, int iter); + +SUNDIALS_EXPORT int CVodeSetRootDirection(void *cvode_mem, int *rootdir); +SUNDIALS_EXPORT int CVodeSetNoInactiveRootWarn(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Function : CVodeInit + * ----------------------------------------------------------------- + * CVodeInit allocates and initializes memory for a problem to + * to be solved by CVODE. + * + * cvode_mem is pointer to CVODE memory returned by CVodeCreate. + * + * f is the name of the C function defining the right-hand + * side function in y' = f(t,y). + * + * t0 is the initial value of t. + * + * y0 is the initial condition vector y(t0). + * + * Return flag: + * CV_SUCCESS if successful + * CV_MEM_NULL if the cvode memory was NULL + * CV_MEM_FAIL if a memory allocation failed + * CV_ILL_INPUT f an argument has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0); + +/* + * ----------------------------------------------------------------- + * Function : CVodeReInit + * ----------------------------------------------------------------- + * CVodeReInit re-initializes CVode for the solution of a problem, + * where a prior call to CVodeInit has been made with the same + * problem size N. CVodeReInit performs the same input checking + * and initializations that CVodeInit does. + * But it does no memory allocation, assuming that the existing + * internal memory is sufficient for the new problem. + * + * The use of CVodeReInit requires that the maximum method order, + * maxord, is no larger for the new problem than for the problem + * specified in the last call to CVodeInit. This condition is + * automatically fulfilled if the multistep method parameter lmm + * is unchanged (or changed from CV_ADAMS to CV_BDF) and the default + * value for maxord is specified. + * + * All of the arguments to CVodeReInit have names and meanings + * identical to those of CVodeInit. + * + * The return value of CVodeReInit is equal to CV_SUCCESS = 0 if + * there were no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL (i.e., + * CVodeCreate has not been called). + * CV_NO_MALLOC indicating that cvode_mem has not been + * allocated (i.e., CVodeInit has not been + * called). + * CV_ILL_INPUT indicating an input argument was illegal + * (including an attempt to increase maxord). + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0); + +/* + * ----------------------------------------------------------------- + * Functions : CVodeSStolerances + * CVodeSVtolerances + * CVodeWFtolerances + * ----------------------------------------------------------------- + * + * These functions specify the integration tolerances. One of them + * MUST be called before the first call to CVode. + * + * CVodeSStolerances specifies scalar relative and absolute tolerances. + * CVodeSVtolerances specifies scalar relative tolerance and a vector + * absolute tolerance (a potentially different absolute tolerance + * for each vector component). + * CVodeWFtolerances specifies a user-provides function (of type CVEwtFn) + * which will be called to set the error weight vector. + * + * The tolerances reltol and abstol define a vector of error weights, + * ewt, with components + * ewt[i] = 1/(reltol*abs(y[i]) + abstol) (in the SS case), or + * ewt[i] = 1/(reltol*abs(y[i]) + abstol[i]) (in the SV case). + * This vector is used in all error and convergence tests, which + * use a weighted RMS norm on all error-like vectors v: + * WRMSnorm(v) = sqrt( (1/N) sum(i=1..N) (v[i]*ewt[i])^2 ), + * where N is the problem dimension. + * + * The return value of these functions is equal to CV_SUCCESS = 0 if + * there were no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL (i.e., + * CVodeCreate has not been called). + * CV_NO_MALLOC indicating that cvode_mem has not been + * allocated (i.e., CVodeInit has not been + * called). + * CV_ILL_INPUT indicating an input argument was illegal + * (e.g. a negative tolerance) + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol); +SUNDIALS_EXPORT int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol); +SUNDIALS_EXPORT int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun); + +/* + * ----------------------------------------------------------------- + * Function : CVodeRootInit + * ----------------------------------------------------------------- + * CVodeRootInit initializes a rootfinding problem to be solved + * during the integration of the ODE system. It must be called + * after CVodeCreate, and before CVode. The arguments are: + * + * cvode_mem = pointer to CVODE memory returned by CVodeCreate. + * + * nrtfn = number of functions g_i, an int >= 0. + * + * g = name of user-supplied function, of type CVRootFn, + * defining the functions g_i whose roots are sought. + * + * If a new problem is to be solved with a call to CVodeReInit, + * where the new problem has no root functions but the prior one + * did, then call CVodeRootInit with nrtfn = 0. + * + * The return value of CVodeRootInit is CV_SUCCESS = 0 if there were + * no errors; otherwise it is a negative int equal to: + * CV_MEM_NULL indicating cvode_mem was NULL, or + * CV_MEM_FAIL indicating a memory allocation failed. + * (including an attempt to increase maxord). + * CV_ILL_INPUT indicating nrtfn > 0 but g = NULL. + * In case of an error return, an error message is also printed. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g); + +/* + * ----------------------------------------------------------------- + * Function : CVode + * ----------------------------------------------------------------- + * CVode integrates the ODE over an interval in t. + * If itask is CV_NORMAL, then the solver integrates from its + * current internal t value to a point at or beyond tout, then + * interpolates to t = tout and returns y(tout) in the user- + * allocated vector yout. If itask is CV_ONE_STEP, then the solver + * takes one internal time step and returns in yout the value of + * y at the new internal time. In this case, tout is used only + * during the first call to CVode to determine the direction of + * integration and the rough scale of the t variable. If tstop is + * enabled (through a call to CVodeSetStopTime), then CVode returns + * the solution at tstop. Once the integrator returns at a tstop + * time, any future testing for tstop is disabled (and can be + * reenabled only though a new call to CVodeSetStopTime). + * The time reached by the solver is placed in (*tret). The + * user is responsible for allocating the memory for this value. + * + * cvode_mem is the pointer to CVODE memory returned by + * CVodeCreate. + * + * tout is the next time at which a computed solution is desired. + * + * yout is the computed solution vector. In CV_NORMAL mode with no + * errors and no roots found, yout=y(tout). + * + * tret is a pointer to a real location. CVode sets (*tret) to + * the time reached by the solver and returns + * yout=y(*tret). + * + * itask is CV_NORMAL or CV_ONE_STEP. These two modes are described above. + * + * Here is a brief description of each return value: + * + * CV_SUCCESS: CVode succeeded and no roots were found. + * + * CV_ROOT_RETURN: CVode succeeded, and found one or more roots. + * If nrtfn > 1, call CVodeGetRootInfo to see + * which g_i were found to have a root at (*tret). + * + * CV_TSTOP_RETURN: CVode succeeded and returned at tstop. + * + * CV_MEM_NULL: The cvode_mem argument was NULL. + * + * CV_NO_MALLOC: cvode_mem was not allocated. + * + * CV_ILL_INPUT: One of the inputs to CVode is illegal. This + * includes the situation when a component of the + * error weight vectors becomes < 0 during + * internal time-stepping. It also includes the + * situation where a root of one of the root + * functions was found both at t0 and very near t0. + * The ILL_INPUT flag will also be returned if the + * linear solver routine CV--- (called by the user + * after calling CVodeCreate) failed to set one of + * the linear solver-related fields in cvode_mem or + * if the linear solver's init routine failed. In + * any case, the user should see the printed + * error message for more details. + * + * CV_TOO_MUCH_WORK: The solver took mxstep internal steps but + * could not reach tout. The default value for + * mxstep is MXSTEP_DEFAULT = 500. + * + * CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy + * demanded by the user for some internal step. + * + * CV_ERR_FAILURE: Error test failures occurred too many times + * (= MXNEF = 7) during one internal time step or + * occurred with |h| = hmin. + * + * CV_CONV_FAILURE: Convergence test failures occurred too many + * times (= MXNCF = 10) during one internal time + * step or occurred with |h| = hmin. + * + * CV_LINIT_FAIL: The linear solver's initialization function + * failed. + * + * CV_LSETUP_FAIL: The linear solver's setup routine failed in an + * unrecoverable manner. + * + * CV_LSOLVE_FAIL: The linear solver's solve routine failed in an + * unrecoverable manner. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVode(void *cvode_mem, realtype tout, N_Vector yout, + realtype *tret, int itask); + +/* + * ----------------------------------------------------------------- + * Function : CVodeGetDky + * ----------------------------------------------------------------- + * CVodeGetDky computes the kth derivative of the y function at + * time t, where tn-hu <= t <= tn, tn denotes the current + * internal time reached, and hu is the last internal step size + * successfully used by the solver. The user may request + * k=0, 1, ..., qu, where qu is the order last used. The + * derivative vector is returned in dky. This vector must be + * allocated by the caller. It is only legal to call this + * function after a successful return from CVode. + * + * cvode_mem is the pointer to CVODE memory returned by + * CVodeCreate. + * + * t is the time at which the kth derivative of y is evaluated. + * The legal range for t is [tn-hu,tn] as described above. + * + * k is the order of the derivative of y to be computed. The + * legal range for k is [0,qu] as described above. + * + * dky is the output derivative vector [((d/dy)^k)y](t). + * + * The return value for CVodeGetDky is one of: + * + * CV_SUCCESS: CVodeGetDky succeeded. + * + * CV_BAD_K: k is not in the range 0, 1, ..., qu. + * + * CV_BAD_T: t is not in the interval [tn-hu,tn]. + * + * CV_BAD_DKY: The dky argument was NULL. + * + * CV_MEM_NULL: The cvode_mem argument was NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky); + +/* + * ----------------------------------------------------------------- + * Integrator optional output extraction functions + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the main integrator. + * ----------------------------------------------------------------- + * CVodeGetWorkSpace returns the CVODE real and integer workspaces + * CVodeGetNumSteps returns the cumulative number of internal + * steps taken by the solver + * CVodeGetNumRhsEvals returns the number of calls to the user's + * f function + * CVodeGetNumLinSolvSetups returns the number of calls made to + * the linear solver's setup routine + * CVodeGetNumErrTestFails returns the number of local error test + * failures that have occured + * CVodeGetLastOrder returns the order used during the last + * internal step + * CVodeGetCurrentOrder returns the order to be used on the next + * internal step + * CVodeGetNumStabLimOrderReds returns the number of order + * reductions due to stability limit + * detection + * CVodeGetActualInitStep returns the actual initial step size + * used by CVODE + * CVodeGetLastStep returns the step size for the last internal + * step + * CVodeGetCurrentStep returns the step size to be attempted on + * the next internal step + * CVodeGetCurrentTime returns the current internal time reached + * by the solver + * CVodeGetTolScaleFactor returns a suggested factor by which the + * user's tolerances should be scaled when + * too much accuracy has been requested for + * some internal step + * CVodeGetErrWeights returns the current error weight vector. + * The user must allocate space for eweight. + * CVodeGetEstLocalErrors returns the vector of estimated local + * errors. The user must allocate space + * for ele. + * CVodeGetNumGEvals returns the number of calls to the user's + * g function (for rootfinding) + * CVodeGetRootInfo returns the indices for which g_i was found to + * have a root. The user must allocate space for + * rootsfound. For i = 0 ... nrtfn-1, + * rootsfound[i] = 1 if g_i has a root, and = 0 if not. + * + * CVodeGet* return values: + * CV_SUCCESS if succesful + * CV_MEM_NULL if the cvode memory was NULL + * CV_NO_SLDET if stability limit was not turned on + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw); +SUNDIALS_EXPORT int CVodeGetNumSteps(void *cvode_mem, long int *nsteps); +SUNDIALS_EXPORT int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals); +SUNDIALS_EXPORT int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups); +SUNDIALS_EXPORT int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails); +SUNDIALS_EXPORT int CVodeGetLastOrder(void *cvode_mem, int *qlast); +SUNDIALS_EXPORT int CVodeGetCurrentOrder(void *cvode_mem, int *qcur); +SUNDIALS_EXPORT int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred); +SUNDIALS_EXPORT int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused); +SUNDIALS_EXPORT int CVodeGetLastStep(void *cvode_mem, realtype *hlast); +SUNDIALS_EXPORT int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur); +SUNDIALS_EXPORT int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur); +SUNDIALS_EXPORT int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfac); +SUNDIALS_EXPORT int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight); +SUNDIALS_EXPORT int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele); +SUNDIALS_EXPORT int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals); +SUNDIALS_EXPORT int CVodeGetRootInfo(void *cvode_mem, int *rootsfound); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following functions provides the + * optional outputs in one group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, + long int *nfevals, long int *nlinsetups, + long int *netfails, int *qlast, + int *qcur, realtype *hinused, realtype *hlast, + realtype *hcur, realtype *tcur); + +/* + * ----------------------------------------------------------------- + * Nonlinear solver optional output extraction functions + * ----------------------------------------------------------------- + * The following functions can be called to get optional outputs + * and statistics related to the nonlinear solver. + * ----------------------------------------------------------------- + * CVodeGetNumNonlinSolvIters returns the number of nonlinear + * solver iterations performed. + * CVodeGetNumNonlinSolvConvFails returns the number of nonlinear + * convergence failures. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters); +SUNDIALS_EXPORT int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails); + +/* + * ----------------------------------------------------------------- + * As a convenience, the following function provides the + * nonlinear solver optional outputs in a group. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters, + long int *nncfails); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVODE return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVodeGetReturnFlagName(long int flag); + +/* + * ----------------------------------------------------------------- + * Function : CVodeFree + * ----------------------------------------------------------------- + * CVodeFree frees the problem memory cvode_mem allocated by + * CVodeCreate and CVodeInit. Its only argument is the pointer + * cvode_mem returned by CVodeCreate. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void CVodeFree(void **cvode_mem); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_band.h b/dep/cvode-2.7.0/include/cvode/cvode_band.h new file mode 100644 index 00000000..7da3be9e --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_band.h @@ -0,0 +1,61 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODE band linear solver, CVBAND. + * ----------------------------------------------------------------- + */ + +#ifndef _CVBAND_H +#define _CVBAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : CVBand + * ----------------------------------------------------------------- + * A call to the CVBand function links the main CVODE integrator + * with the CVBAND linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian + * approximation. + * + * mlower is the lower bandwidth of the band Jacobian + * approximation. + * + * The return value of CVBand is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the cvode memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing or + * if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBand(void *cvode_mem, long int N, long int mupper, long int mlower); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_bandpre.h b/dep/cvode-2.7.0/include/cvode/cvode_bandpre.h new file mode 100644 index 00000000..0e152449 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_bandpre.h @@ -0,0 +1,141 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVBANDPRE module, which + * provides a banded difference quotient Jacobian-based + * preconditioner and solver routines for use with CVSPGMR, + * CVSPBCG, or CVSPTFQMR. + * + * Summary: + * These routines provide a band matrix preconditioner based on + * difference quotients of the ODE right-hand side function f. + * The user supplies parameters + * mu = upper half-bandwidth (number of super-diagonals) + * ml = lower half-bandwidth (number of sub-diagonals) + * The routines generate a band matrix of bandwidth ml + mu + 1 + * and use this to form a preconditioner for use with the Krylov + * linear solver in CVSP*. Although this matrix is intended to + * approximate the Jacobian df/dy, it may be a very crude + * approximation. The true Jacobian need not be banded, or its + * true bandwith may be larger than ml + mu + 1, as long as the + * banded approximation generated here is sufficiently accurate + * to speed convergence as a preconditioner. + * + * Usage: + * The following is a summary of the usage of this module. + * Details of the calls to CVodeCreate, CVodeMalloc, CVSp*, + * and CVode are available in the User Guide. + * To use these routines, the sequence of calls in the user + * main program should be as follows: + * + * #include + * #include + * ... + * Set y0 + * ... + * cvode_mem = CVodeCreate(...); + * ier = CVodeMalloc(...); + * ... + * flag = CVSptfqmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpgmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpbcg(cvode_mem, pretype, maxl); + * ... + * flag = CVBandPrecInit(cvode_mem, N, mu, ml); + * ... + * flag = CVode(...); + * ... + * Free y0 + * ... + * CVodeFree(&cvode_mem); + * + * Notes: + * (1) Include this file for the CVBandPrecData type definition. + * (2) In the CVBandPrecAlloc call, the arguments N is the + * problem dimension. + * (3) In the CVBPSp* call, the user is free to specify + * the input pretype and the optional input maxl. + * ----------------------------------------------------------------- + */ + +#ifndef _CVBANDPRE_H +#define _CVBANDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + + +/* + * ----------------------------------------------------------------- + * Function : CVBandPrecInit + * ----------------------------------------------------------------- + * CVBandPrecInit allocates and initializes the BANDPRE preconditioner + * module. This functino must be called AFTER one of the SPILS linear + * solver modules has been attached to the CVODE integrator. + * + * The parameters of CVBandPrecInit are as follows: + * + * cvode_mem is the pointer to CVODE memory returned by CVodeCreate. + * + * N is the problem size. + * + * mu is the upper half bandwidth. + * + * ml is the lower half bandwidth. + * + * The return value of CVBandPrecInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * CVSPILS_MEM_FAIL if a memory allocation request failed + * + * NOTE: The band preconditioner assumes a serial implementation + * of the NVECTOR package. Therefore, CVBandPrecInit will + * first test for a compatible N_Vector internal + * representation by checking for required functions. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml); + +/* + * ----------------------------------------------------------------- + * Optional output functions : CVBandPrecGet* + * ----------------------------------------------------------------- + * CVBandPrecGetWorkSpace returns the real and integer work space used + * by CVBANDPRE. + * CVBandPrecGetNumRhsEvals returns the number of calls made from + * CVBANDPRE to the user's right-hand side + * routine f. + * + * The return value of CVBandPrecGet* is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_bbdpre.h b/dep/cvode-2.7.0/include/cvode/cvode_bbdpre.h new file mode 100644 index 00000000..d350c874 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_bbdpre.h @@ -0,0 +1,268 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Michael Wittman, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVBBDPRE module, for a + * band-block-diagonal preconditioner, i.e. a block-diagonal + * matrix with banded blocks, for use with CVSPGMR/CVSPBCG/CVSPTFQMR, + * and the parallel implementation of the NVECTOR module. + * + * Summary: + * + * These routines provide a preconditioner matrix that is + * block-diagonal with banded blocks. The blocking corresponds + * to the distribution of the dependent variable vector y among + * the processors. Each preconditioner block is generated from + * the Jacobian of the local part (on the current processor) of a + * given function g(t,y) approximating f(t,y). The blocks are + * generated by a difference quotient scheme on each processor + * independently. This scheme utilizes an assumed banded + * structure with given half-bandwidths, mudq and mldq. + * However, the banded Jacobian block kept by the scheme has + * half-bandwiths mukeep and mlkeep, which may be smaller. + * + * The user's calling program should have the following form: + * + * #include + * #include + * ... + * void *cvode_mem; + * ... + * Set y0 + * ... + * cvode_mem = CVodeCreate(...); + * ier = CVodeMalloc(...); + * ... + * flag = CVSpgmr(cvode_mem, pretype, maxl); + * -or- + * flag = CVSpbcg(cvode_mem, pretype, maxl); + * -or- + * flag = CVSptfqmr(cvode_mem, pretype, maxl); + * ... + * flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq, + * mukeep, mlkeep, dqrely, gloc, cfn); + * ... + * ier = CVode(...); + * ... + * CVodeFree(&cvode_mem); + * + * Free y0 + * + * The user-supplied routines required are: + * + * f = function defining the ODE right-hand side f(t,y). + * + * gloc = function defining the approximation g(t,y). + * + * cfn = function to perform communication need for gloc. + * + * Notes: + * + * 1) This header file is included by the user for the definition + * of the CVBBDData type and for needed function prototypes. + * + * 2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq + * to be used in the difference quotient calculation of the + * approximate Jacobian. They need not be the true + * half-bandwidths of the Jacobian of the local block of g, + * when smaller values may provide a greater efficiency. + * Also, the half-bandwidths mukeep and mlkeep of the retained + * banded approximate Jacobian block may be even smaller, + * to reduce storage and computation costs further. + * For all four half-bandwidths, the values need not be the + * same on every processor. + * + * 3) The actual name of the user's f function is passed to + * CVodeInit, and the names of the user's gloc and cfn + * functions are passed to CVBBDPrecInit. + * + * 4) The pointer to the user-defined data block user_data, which is + * set through CVodeSetUserData is also available to the user in + * gloc and cfn. + * + * 5) Optional outputs specific to this module are available by + * way of routines listed below. These include work space sizes + * and the cumulative number of gloc calls. The costs + * associated with this module also include nsetups banded LU + * factorizations, nlinsetups cfn calls, and npsolves banded + * backsolve calls, where nlinsetups and npsolves are + * integrator/CVSPGMR/CVSPBCG/CVSPTFQMR optional outputs. + * ----------------------------------------------------------------- + */ + +#ifndef _CVBBDPRE_H +#define _CVBBDPRE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Type : CVLocalFn + * ----------------------------------------------------------------- + * The user must supply a function g(t,y) which approximates the + * right-hand side function f for the system y'=f(t,y), and which + * is computed locally (without interprocess communication). + * (The case where g is mathematically identical to f is allowed.) + * The implementation of this function must have type CVLocalFn. + * + * This function takes as input the local vector size Nlocal, the + * independent variable value t, the local real dependent + * variable vector y, and a pointer to the user-defined data + * block user_data. It is to compute the local part of g(t,y) and + * store this in the vector g. + * (Allocation of memory for y and g is handled within the + * preconditioner module.) + * The user_data parameter is the same as that specified by the user + * through the CVodeSetFdata routine. + * + * A CVLocalFn should return 0 if successful, a positive value if + * a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVLocalFn)(long int Nlocal, realtype t, N_Vector y, + N_Vector g, void *user_data); + +/* + * ----------------------------------------------------------------- + * Type : CVCommFn + * ----------------------------------------------------------------- + * The user may supply a function of type CVCommFn which performs + * all interprocess communication necessary to evaluate the + * approximate right-hand side function described above. + * + * This function takes as input the local vector size Nlocal, + * the independent variable value t, the dependent variable + * vector y, and a pointer to the user-defined data block user_data. + * The user_data parameter is the same as that specified by the user + * through the CVodeSetUserData routine. The CVCommFn cfn is + * expected to save communicated data in space defined within the + * structure user_data. Note: A CVCommFn cfn does not have a return value. + * + * Each call to the CVCommFn cfn is preceded by a call to the + * CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any + * communications done by f if relevant to the evaluation of g. + * If all necessary communication was done by f, the user can + * pass NULL for cfn in CVBBDPrecInit (see below). + * + * A CVCommFn should return 0 if successful, a positive value if + * a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVCommFn)(long int Nlocal, realtype t, N_Vector y, + void *user_data); + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecInit + * ----------------------------------------------------------------- + * CVBBDPrecInit allocates and initializes the BBD preconditioner. + * + * The parameters of CVBBDPrecInit are as follows: + * + * cvode_mem is the pointer to the integrator memory. + * + * Nlocal is the length of the local block of the vectors y etc. + * on the current processor. + * + * mudq, mldq are the upper and lower half-bandwidths to be used + * in the difference quotient computation of the local + * Jacobian block. + * + * mukeep, mlkeep are the upper and lower half-bandwidths of the + * retained banded approximation to the local Jacobian + * block. + * + * dqrely is an optional input. It is the relative increment + * in components of y used in the difference quotient + * approximations. To specify the default, pass 0. + * The default is dqrely = sqrt(unit roundoff). + * + * gloc is the name of the user-supplied function g(t,y) that + * approximates f and whose local Jacobian blocks are + * to form the preconditioner. + * + * cfn is the name of the user-defined function that performs + * necessary interprocess communication for the + * execution of gloc. + * + * The return value of CVBBDPrecInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * CVSPILS_MEM_FAIL if a memory allocation request failed + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem, long int Nlocal, + long int mudq, long int mldq, + long int mukeep, long int mlkeep, + realtype dqrely, + CVLocalFn gloc, CVCommFn cfn); + +/* + * ----------------------------------------------------------------- + * Function : CVBBDPrecReInit + * ----------------------------------------------------------------- + * CVBBDPrecReInit re-initializes the BBDPRE module when solving a + * sequence of problems of the same size with CVSPGMR/CVBBDPRE or + * CVSPBCG/CVBBDPRE or CVSPTFQMR/CVBBDPRE provided there is no change + * in Nlocal, mukeep, or mlkeep. After solving one problem, and after + * calling CVodeReInit to re-initialize the integrator for a subsequent + * problem, call CVBBDPrecReInit. + * + * All arguments have the same names and meanings as those + * of CVBBDPrecInit. + * + * The return value of CVBBDPrecReInit is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem, long int mudq, long int mldq, + realtype dqrely); + +/* + * ----------------------------------------------------------------- + * BBDPRE optional output extraction routines + * ----------------------------------------------------------------- + * CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work space + * sizes. + * CVBBDPrecGetNumGfnEvals returns the number of calls to gfn. + * + * The return value of CVBBDPrecGet* is one of: + * CVSPILS_SUCCESS if no errors occurred + * CVSPILS_MEM_NULL if the integrator memory is NULL + * CVSPILS_LMEM_NULL if the linear solver memory is NULL + * CVSPILS_PMEM_NULL if the preconditioner memory is NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_dense.h b/dep/cvode-2.7.0/include/cvode/cvode_dense.h new file mode 100644 index 00000000..0a59ec9c --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_dense.h @@ -0,0 +1,54 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODE dense linear solver, CVDENSE. + * ----------------------------------------------------------------- + */ + +#ifndef _CVDENSE_H +#define _CVDENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function: CVDense + * ----------------------------------------------------------------- + * A call to the CVDense function links the main integrator with + * the CVDENSE linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * The return value of CVDense is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the cvode memory was NULL + * CVDLS_MEM_FAIL if there was a memory allocation failure + * CVDLS_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDense(void *cvode_mem, long int N); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_diag.h b/dep/cvode-2.7.0/include/cvode/cvode_diag.h new file mode 100644 index 00000000..1b4c93d8 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_diag.h @@ -0,0 +1,106 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODE diagonal linear solver, CVDIAG. + * ----------------------------------------------------------------- + */ + +#ifndef _CVDIAG_H +#define _CVDIAG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Function : CVDiag + * ----------------------------------------------------------------- + * A call to the CVDiag function links the main integrator with + * the CVDIAG linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * The return value of CVDiag is one of: + * CVDIAG_SUCCESS if successful + * CVDIAG_MEM_NULL if the cvode memory was NULL + * CVDIAG_MEM_FAIL if there was a memory allocation failure + * CVDIAG_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiag(void *cvode_mem); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVDIAG linear solver + * ----------------------------------------------------------------- + * + * CVDiagGetWorkSpace returns the real and integer workspace used + * by CVDIAG. + * CVDiagGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * Note: The number of diagonal approximate + * Jacobians formed is equal to the number of + * CVDiagSetup calls. This number is available + * through CVodeGetNumLinSolvSetups. + * CVDiagGetLastFlag returns the last error flag set by any of + * the CVDIAG interface functions. + * + * The return value of CVDiagGet* is one of: + * CVDIAG_SUCCESS if successful + * CVDIAG_MEM_NULL if the cvode memory was NULL + * CVDIAG_LMEM_NULL if the cvdiag memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDiagGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVDiagGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVDiagGetLastFlag(void *cvode_mem, long int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVDIAG return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVDiagGetReturnFlagName(long int flag); + +/* + * ----------------------------------------------------------------- + * CVDIAG return values + * ----------------------------------------------------------------- + */ + +#define CVDIAG_SUCCESS 0 +#define CVDIAG_MEM_NULL -1 +#define CVDIAG_LMEM_NULL -2 +#define CVDIAG_ILL_INPUT -3 +#define CVDIAG_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define CVDIAG_INV_FAIL -5 +#define CVDIAG_RHSFUNC_UNRECVR -6 +#define CVDIAG_RHSFUNC_RECVR -7 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_direct.h b/dep/cvode-2.7.0/include/cvode/cvode_direct.h new file mode 100644 index 00000000..224e5ce4 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_direct.h @@ -0,0 +1,285 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Common header file for the direct linear solvers in CVODE. + * ----------------------------------------------------------------- + */ + +#ifndef _CVDLS_H +#define _CVDLS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ================================================================= + * C V D I R E C T C O N S T A N T S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * CVDLS return values + * ----------------------------------------------------------------- + */ + +#define CVDLS_SUCCESS 0 +#define CVDLS_MEM_NULL -1 +#define CVDLS_LMEM_NULL -2 +#define CVDLS_ILL_INPUT -3 +#define CVDLS_MEM_FAIL -4 + +/* Additional last_flag values */ + +#define CVDLS_JACFUNC_UNRECVR -5 +#define CVDLS_JACFUNC_RECVR -6 + +/* + * ================================================================= + * F U N C T I O N T Y P E S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Type: CVDlsDenseJacFn + * ----------------------------------------------------------------- + * + * A dense Jacobian approximation function Jac must be of type + * CVDlsDenseJacFn. Its parameters are: + * + * N is the problem size. + * + * Jac is the dense matrix (of type DlsMat) that will be loaded + * by a CVDlsDenseJacFn with an approximation to the Jacobian + * matrix J = (df_i/dy_j) at the point (t,y). + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to CVodeSetFdata. + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated for + * vectors of length N which can be used by a CVDlsDenseJacFn + * as temporary storage or work space. + * + * A CVDlsDenseJacFn should return 0 if successful, a positive + * value if a recoverable error occurred, and a negative value if + * an unrecoverable error occurred. + * + * ----------------------------------------------------------------- + * + * NOTE: The following are two efficient ways to load a dense Jac: + * (1) (with macros - no explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = DENSE_COL(Jac,j); + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * (2) (without macros - explicit data structure references) + * for (j=0; j < Neq; j++) { + * col_j = (Jac->data)[j]; + * for (i=0; i < Neq; i++) { + * generate J_ij = the (i,j)th Jacobian element + * col_j[i] = J_ij; + * } + * } + * A third way, using the DENSE_ELEM(A,i,j) macro, is much less + * efficient in general. It is only appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively + * (see cvode.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h. + * + * ----------------------------------------------------------------- + */ + + +typedef int (*CVDlsDenseJacFn)(long int N, realtype t, + N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type: CVDlsBandJacFn + * ----------------------------------------------------------------- + * + * A band Jacobian approximation function Jac must have the + * prototype given below. Its parameters are: + * + * N is the length of all vector arguments. + * + * mupper is the upper half-bandwidth of the approximate banded + * Jacobian. This parameter is the same as the mupper parameter + * passed by the user to the linear solver initialization function. + * + * mlower is the lower half-bandwidth of the approximate banded + * Jacobian. This parameter is the same as the mlower parameter + * passed by the user to the linear solver initialization function. + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * Jac is the band matrix (of type DlsMat) that will be loaded + * by a CVDlsBandJacFn with an approximation to the Jacobian matrix + * Jac = (df_i/dy_j) at the point (t,y). + * Three efficient ways to load J are: + * + * (1) (with macros - no explicit data structure references) + * for (j=0; j < n; j++) { + * col_j = BAND_COL(Jac,j); + * for (i=j-mupper; i <= j+mlower; i++) { + * generate J_ij = the (i,j)th Jacobian element + * BAND_COL_ELEM(col_j,i,j) = J_ij; + * } + * } + * + * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro) + * for (j=0; j < n; j++) { + * col_j = BAND_COL(Jac,j); + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * + * (3) (without macros - explicit data structure references) + * offset = Jac->smu; + * for (j=0; j < n; j++) { + * col_j = ((Jac->data)[j])+offset; + * for (k=-mupper; k <= mlower; k++) { + * generate J_ij = the (i,j)th Jacobian element, i=j+k + * col_j[k] = J_ij; + * } + * } + * Caution: Jac->smu is generally NOT the same as mupper. + * + * The BAND_ELEM(A,i,j) macro is appropriate for use in small + * problems in which efficiency of access is NOT a major concern. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to CVodeSetFdata. + * + * NOTE: If the user's Jacobian routine needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively + * (see cvode.h). The unit roundoff is available as + * UNIT_ROUNDOFF defined in sundials_types.h + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated for + * vectors of length N which can be used by a CVDlsBandJacFn + * as temporary storage or work space. + * + * A CVDlsBandJacFn should return 0 if successful, a positive value + * if a recoverable error occurred, and a negative value if an + * unrecoverable error occurred. + * ----------------------------------------------------------------- + */ + +typedef int (*CVDlsBandJacFn)(long int N, long int mupper, long int mlower, + realtype t, N_Vector y, N_Vector fy, + DlsMat Jac, void *user_data, + N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +/* + * ================================================================= + * E X P O R T E D F U N C T I O N S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Optional inputs to the CVDLS linear solver + * ----------------------------------------------------------------- + * + * CVDlsSetDenseJacFn specifies the dense Jacobian approximation + * routine to be used for a direct dense linear solver. + * + * CVDlsSetBandJacFn specifies the band Jacobian approximation + * routine to be used for a direct band linear solver. + * + * By default, a difference quotient approximation, supplied with + * the solver is used. + * + * The return value is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODE memory was NULL + * CVDLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac); +SUNDIALS_EXPORT int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVDLS linear solver + * ----------------------------------------------------------------- + * + * CVDlsGetWorkSpace returns the real and integer workspace used + * by the direct linear solver. + * CVDlsGetNumJacEvals returns the number of calls made to the + * Jacobian evaluation routine jac. + * CVDlsGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * evaluation. + * CVDlsGetLastFlag returns the last error flag set by any of + * the CVDLS interface functions. + * + * The return value of CVDlsGet* is one of: + * CVDLS_SUCCESS if successful + * CVDLS_MEM_NULL if the CVODE memory was NULL + * CVDLS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals); +SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem, long int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVDLS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVDlsGetReturnFlagName(long int flag); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_lapack.h b/dep/cvode-2.7.0/include/cvode/cvode_lapack.h new file mode 100644 index 00000000..e0e8d74d --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_lapack.h @@ -0,0 +1,86 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * Header file for the CVODE dense linear solver CVLAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _CVLAPACK_H +#define _CVLAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ================================================================= + * E X P O R T E D F U N C T I O N S + * ================================================================= + */ + +/* + * ----------------------------------------------------------------- + * Function : CVLapackDense + * ----------------------------------------------------------------- + * A call to the CVLapackDense function links the main integrator + * with the CVLAPACK linear solver using dense Jacobians. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * The return value of CVLapackDense is one of: + * CVLAPACK_SUCCESS if successful + * CVLAPACK_MEM_NULL if the CVODE memory was NULL + * CVLAPACK_MEM_FAIL if there was a memory allocation failure + * CVLAPACK_ILL_INPUT if a required vector operation is missing + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackDense(void *cvode_mem, int N); + +/* + * ----------------------------------------------------------------- + * Function : CVLapackBand + * ----------------------------------------------------------------- + * A call to the CVLapackBand function links the main integrator + * with the CVLAPACK linear solver using banded Jacobians. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * N is the size of the ODE system. + * + * mupper is the upper bandwidth of the band Jacobian approximation. + * + * mlower is the lower bandwidth of the band Jacobian approximation. + * + * The return value of CVLapackBand is one of: + * CVLAPACK_SUCCESS if successful + * CVLAPACK_MEM_NULL if the CVODE memory was NULL + * CVLAPACK_MEM_FAIL if there was a memory allocation failure + * CVLAPACK_ILL_INPUT if a required vector operation is missing or + * if a bandwidth has an illegal value. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_spbcgs.h b/dep/cvode-2.7.0/include/cvode/cvode_spbcgs.h new file mode 100644 index 00000000..278acf86 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_spbcgs.h @@ -0,0 +1,67 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODE scaled preconditioned + * Bi-CGSTAB linear solver, CVSPBCG. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSPBCG_H +#define _CVSPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : CVSpbcg + * ----------------------------------------------------------------- + * A call to the CVSpbcg function links the main CVODE integrator + * with the CVSPBCG linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in iterative.h. These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPBCG solver. Pass 0 to + * use the default value CVSPBCG_MAXL=5. + * + * The return value of CVSpbcg is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvode_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpbcg(void *cvode_mem, int pretype, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_spgmr.h b/dep/cvode-2.7.0/include/cvode/cvode_spgmr.h new file mode 100644 index 00000000..2b8499c7 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_spgmr.h @@ -0,0 +1,69 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODE scaled preconditioned GMRES + * linear solver, CVSPGMR. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSPGMR_H +#define _CVSPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : CVSpgmr + * ----------------------------------------------------------------- + * A call to the CVSpgmr function links the main CVODE integrator + * with the CVSPGMR linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in sundials_iterative.h. + * These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPGMR solver. Pass 0 to + * use the default value CVSPGMR_MAXL=5. + * + * The return value of CVSpgmr is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvode_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpgmr(void *cvode_mem, int pretype, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_spils.h b/dep/cvode-2.7.0/include/cvode/cvode_spils.h new file mode 100644 index 00000000..531bd0b8 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_spils.h @@ -0,0 +1,365 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.10 $ + * $Date: 2010/12/01 22:10:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the common header file for the Scaled, Preconditioned + * Iterative Linear Solvers in CVODE. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSPILS_H +#define _CVSPILS_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + + +/* + * ----------------------------------------------------------------- + * CVSPILS return values + * ----------------------------------------------------------------- + */ + +#define CVSPILS_SUCCESS 0 +#define CVSPILS_MEM_NULL -1 +#define CVSPILS_LMEM_NULL -2 +#define CVSPILS_ILL_INPUT -3 +#define CVSPILS_MEM_FAIL -4 +#define CVSPILS_PMEM_NULL -5 + +/* + * ----------------------------------------------------------------- + * CVSPILS solver constants + * ----------------------------------------------------------------- + * CVSPILS_MAXL : default value for the maximum Krylov + * dimension + * + * CVSPILS_MSBPRE : maximum number of steps between + * preconditioner evaluations + * + * CVSPILS_DGMAX : maximum change in gamma between + * preconditioner evaluations + * + * CVSPILS_EPLIN : default value for factor by which the + * tolerance on the nonlinear iteration is + * multiplied to get a tolerance on the linear + * iteration + * ----------------------------------------------------------------- + */ + +#define CVSPILS_MAXL 5 +#define CVSPILS_MSBPRE 50 +#define CVSPILS_DGMAX RCONST(0.2) +#define CVSPILS_EPLIN RCONST(0.05) + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSetupFn + * ----------------------------------------------------------------- + * The user-supplied preconditioner setup function PrecSetup and + * the user-supplied preconditioner solve function PrecSolve + * together must define left and right preconditoner matrices + * P1 and P2 (either of which may be trivial), such that the + * product P1*P2 is an approximation to the Newton matrix + * M = I - gamma*J. Here J is the system Jacobian J = df/dy, + * and gamma is a scalar proportional to the integration step + * size h. The solution of systems P z = r, with P = P1 or P2, + * is to be carried out by the PrecSolve function, and PrecSetup + * is to do any necessary setup operations. + * + * The user-supplied preconditioner setup function PrecSetup + * is to evaluate and preprocess any Jacobian-related data + * needed by the preconditioner solve function PrecSolve. + * This might include forming a crude approximate Jacobian, + * and performing an LU factorization on the resulting + * approximation to M. This function will not be called in + * advance of every call to PrecSolve, but instead will be called + * only as often as necessary to achieve convergence within the + * Newton iteration. If the PrecSolve function needs no + * preparation, the PrecSetup function can be NULL. + * + * For greater efficiency, the PrecSetup function may save + * Jacobian-related data and reuse it, rather than generating it + * from scratch. In this case, it should use the input flag jok + * to decide whether to recompute the data, and set the output + * flag *jcurPtr accordingly. + * + * Each call to the PrecSetup function is preceded by a call to + * the RhsFn f with the same (t,y) arguments. Thus the PrecSetup + * function can use any auxiliary data that is computed and + * saved by the f function and made accessible to PrecSetup. + * + * A function PrecSetup must have the prototype given below. + * Its parameters are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector, + * namely the predicted value of y(t). + * + * fy is the vector f(t,y). + * + * jok is an input flag indicating whether Jacobian-related + * data needs to be recomputed, as follows: + * jok == FALSE means recompute Jacobian-related data + * from scratch. + * jok == TRUE means that Jacobian data, if saved from + * the previous PrecSetup call, can be reused + * (with the current value of gamma). + * A Precset call with jok == TRUE can only occur after + * a call with jok == FALSE. + * + * jcurPtr is a pointer to an output integer flag which is + * to be set by PrecSetup as follows: + * Set *jcurPtr = TRUE if Jacobian data was recomputed. + * Set *jcurPtr = FALSE if Jacobian data was not recomputed, + * but saved data was reused. + * + * gamma is the scalar appearing in the Newton matrix. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp1, tmp2, and tmp3 are pointers to memory allocated + * for N_Vectors which can be used by + * CVSpilsPrecSetupFn as temporary storage or + * work space. + * + * NOTE: If the user's preconditioner needs other quantities, + * they are accessible as follows: hcur (the current stepsize) + * and ewt (the error weight vector) are accessible through + * CVodeGetCurrentStep and CVodeGetErrWeights, respectively). + * The unit roundoff is available as UNIT_ROUNDOFF defined in + * sundials_types.h. + * + * Returned value: + * The value to be returned by the PrecSetup function is a flag + * indicating whether it was successful. This value should be + * 0 if successful, + * > 0 for a recoverable error (step will be retried), + * < 0 for an unrecoverable error (integration is halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSetupFn)(realtype t, N_Vector y, N_Vector fy, + booleantype jok, booleantype *jcurPtr, + realtype gamma, void *user_data, + N_Vector tmp1, N_Vector tmp2, + N_Vector tmp3); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsPrecSolveFn + * ----------------------------------------------------------------- + * The user-supplied preconditioner solve function PrecSolve + * is to solve a linear system P z = r in which the matrix P is + * one of the preconditioner matrices P1 or P2, depending on the + * type of preconditioning chosen. + * + * A function PrecSolve must have the prototype given below. + * Its parameters are as follows: + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable vector. + * + * fy is the vector f(t,y). + * + * r is the right-hand side vector of the linear system. + * + * z is the output vector computed by PrecSolve. + * + * gamma is the scalar appearing in the Newton matrix. + * + * delta is an input tolerance for use by PSolve if it uses + * an iterative method in its solution. In that case, + * the residual vector Res = r - P z of the system + * should be made less than delta in weighted L2 norm, + * i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta. + * Note: the error weight vector ewt can be obtained + * through a call to the routine CVodeGetErrWeights. + * + * lr is an input flag indicating whether PrecSolve is to use + * the left preconditioner P1 or right preconditioner + * P2: lr = 1 means use P1, and lr = 2 means use P2. + * + * user_data is a pointer to user data - the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp is a pointer to memory allocated for an N_Vector + * which can be used by PSolve for work space. + * + * Returned value: + * The value to be returned by the PrecSolve function is a flag + * indicating whether it was successful. This value should be + * 0 if successful, + * positive for a recoverable error (step will be retried), + * negative for an unrecoverable error (integration is halted). + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsPrecSolveFn)(realtype t, N_Vector y, N_Vector fy, + N_Vector r, N_Vector z, + realtype gamma, realtype delta, + int lr, void *user_data, N_Vector tmp); + +/* + * ----------------------------------------------------------------- + * Type : CVSpilsJacTimesVecFn + * ----------------------------------------------------------------- + * The user-supplied function jtimes is to generate the product + * J*v for given v, where J is the Jacobian df/dy, or an + * approximation to it, and v is a given vector. It should return + * 0 if successful a positive value for a recoverable error or + * a negative value for an unrecoverable failure. + * + * A function jtimes must have the prototype given below. Its + * parameters are as follows: + * + * v is the N_Vector to be multiplied by J. + * + * Jv is the output N_Vector containing J*v. + * + * t is the current value of the independent variable. + * + * y is the current value of the dependent variable + * vector. + * + * fy is the vector f(t,y). + * + * user_data is a pointer to user data, the same as the user_data + * parameter passed to the CVodeSetUserData function. + * + * tmp is a pointer to memory allocated for an N_Vector + * which can be used by Jtimes for work space. + * ----------------------------------------------------------------- + */ + +typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t, + N_Vector y, N_Vector fy, + void *user_data, N_Vector tmp); + + + +/* + * ----------------------------------------------------------------- + * Optional inputs to the CVSPILS linear solver + * ----------------------------------------------------------------- + * + * CVSpilsSetPrecType resets the type of preconditioner, pretype, + * from the value previously set. + * This must be one of PREC_NONE, PREC_LEFT, + * PREC_RIGHT, or PREC_BOTH. + * + * CVSpilsSetGSType specifies the type of Gram-Schmidt + * orthogonalization to be used. This must be one of + * the two enumeration constants MODIFIED_GS or + * CLASSICAL_GS defined in iterative.h. These correspond + * to using modified Gram-Schmidt and classical + * Gram-Schmidt, respectively. + * Default value is MODIFIED_GS. + * + * CVSpilsSetMaxl resets the maximum Krylov subspace size, maxl, + * from the value previously set. + * An input value <= 0, gives the default value. + * + * CVSpilsSetEpsLin specifies the factor by which the tolerance on + * the nonlinear iteration is multiplied to get a + * tolerance on the linear iteration. + * Default value is 0.05. + * + * CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve functions. + * Default is NULL for both arguments (no preconditioning) + * + * CVSpilsSetJacTimesVecFn specifies the jtimes function. Default is to + * use an internal finite difference approximation routine. + * + * The return value of CVSpilsSet* is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_LMEM_NULL if the linear solver memory was NULL + * CVSPILS_ILL_INPUT if an input has an illegal value + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsSetPrecType(void *cvode_mem, int pretype); +SUNDIALS_EXPORT int CVSpilsSetGSType(void *cvode_mem, int gstype); +SUNDIALS_EXPORT int CVSpilsSetMaxl(void *cvode_mem, int maxl); +SUNDIALS_EXPORT int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac); +SUNDIALS_EXPORT int CVSpilsSetPreconditioner(void *cvode_mem, + CVSpilsPrecSetupFn pset, + CVSpilsPrecSolveFn psolve); +SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFn(void *cvode_mem, + CVSpilsJacTimesVecFn jtv); + +/* + * ----------------------------------------------------------------- + * Optional outputs from the CVSPILS linear solver + * ----------------------------------------------------------------- + * CVSpilsGetWorkSpace returns the real and integer workspace used + * by the SPILS module. + * + * CVSpilsGetNumPrecEvals returns the number of preconditioner + * evaluations, i.e. the number of calls made + * to PrecSetup with jok==FALSE. + * + * CVSpilsGetNumPrecSolves returns the number of calls made to + * PrecSolve. + * + * CVSpilsGetNumLinIters returns the number of linear iterations. + * + * CVSpilsGetNumConvFails returns the number of linear + * convergence failures. + * + * CVSpilsGetNumJtimesEvals returns the number of calls to jtimes. + * + * CVSpilsGetNumRhsEvals returns the number of calls to the user + * f routine due to finite difference Jacobian + * times vector evaluation. + * + * CVSpilsGetLastFlag returns the last error flag set by any of + * the CVSPILS interface functions. + * + * The return value of CVSpilsGet* is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_LMEM_NULL if the linear solver memory was NULL + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS); +SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals); +SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves); +SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters); +SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails); +SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals); +SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); +SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem, long int *flag); + +/* + * ----------------------------------------------------------------- + * The following function returns the name of the constant + * associated with a CVSPILS return flag + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT char *CVSpilsGetReturnFlagName(long int flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/cvode/cvode_sptfqmr.h b/dep/cvode-2.7.0/include/cvode/cvode_sptfqmr.h new file mode 100644 index 00000000..c19e67b6 --- /dev/null +++ b/dep/cvode-2.7.0/include/cvode/cvode_sptfqmr.h @@ -0,0 +1,67 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2006/11/29 00:05:06 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the CVODE scaled preconditioned TFQMR + * linear solver, CVSPTFQMR. + * ----------------------------------------------------------------- + */ + +#ifndef _CVSPTFQMR_H +#define _CVSPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +/* + * ----------------------------------------------------------------- + * Function : CVSptfqmr + * ----------------------------------------------------------------- + * A call to the CVSptfqmr function links the main CVODE integrator + * with the CVSPTFQMR linear solver. + * + * cvode_mem is the pointer to the integrator memory returned by + * CVodeCreate. + * + * pretype is the type of user preconditioning to be done. + * This must be one of the four enumeration constants + * PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined + * in iterative.h. These correspond to no preconditioning, + * left preconditioning only, right preconditioning + * only, and both left and right preconditioning, + * respectively. + * + * maxl is the maximum Krylov dimension. This is an + * optional input to the CVSPTFQMR solver. Pass 0 to + * use the default value CVSPILS_MAXL=5. + * + * The return value of CVSptfqmr is one of: + * CVSPILS_SUCCESS if successful + * CVSPILS_MEM_NULL if the cvode memory was NULL + * CVSPILS_MEM_FAIL if there was a memory allocation failure + * CVSPILS_ILL_INPUT if a required vector operation is missing + * The above constants are defined in cvode_spils.h + * + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int CVSptfqmr(void *cvode_mem, int pretype, int maxl); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/nvector/nvector_parallel.h b/dep/cvode-2.7.0/include/nvector/nvector_parallel.h new file mode 100644 index 00000000..f8a006ca --- /dev/null +++ b/dep/cvode-2.7.0/include/nvector/nvector_parallel.h @@ -0,0 +1,314 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the main header file for the MPI-enabled implementation + * of the NVECTOR module. + * + * Part I contains declarations specific to the parallel + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to efficiently + * use the type N_Vector without making explicit references to the + * underlying data structure. + * + * Part III contains the prototype for the constructor + * N_VNew_Parallel as well as implementation-specific prototypes + * for various useful vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be + * found in the header file sundials_nvector.h. + * + * - The definition of the type realtype can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type booleantype. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Parallel(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_PARALLEL_H +#define _NVECTOR_PARALLEL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +#include + + +/* + * ----------------------------------------------------------------- + * PART I: PARALLEL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* define MPI data types */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_FLOAT + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_DOUBLE + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +#define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE + +#endif + +#define PVEC_INTEGER_MPI_TYPE MPI_LONG + +/* parallel implementation of the N_Vector 'content' structure + contains the global and local lengths of the vector, a pointer + to an array of 'realtype components', the MPI communicator, + and a flag indicating ownership of the data */ + +struct _N_VectorContent_Parallel { + long int local_length; /* local vector length */ + long int global_length; /* global vector length */ + booleantype own_data; /* ownership of data */ + realtype *data; /* local data array */ + MPI_Comm comm; /* pointer to MPI communicator */ +}; + +typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_P, NV_DATA_P, NV_OWN_DATA_P, + * NV_LOCLENGTH_P, NV_GLOBLENGTH_P,NV_COMM_P, and NV_Ith_P + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int v_len, s_len, i; + * + * (1) NV_CONTENT_P + * + * This routines gives access to the contents of the parallel + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_P(v) sets v_cont to be + * a pointer to the parallel N_Vector content structure. + * + * (2) NV_DATA_P, NV_OWN_DATA_P, NV_LOCLENGTH_P, NV_GLOBLENGTH_P, + * and NV_COMM_P + * + * These routines give access to the individual parts of + * the content structure of a parallel N_Vector. + * + * The assignment v_data = NV_DATA_P(v) sets v_data to be + * a pointer to the first component of the local data for + * the vector v. The assignment NV_DATA_P(v) = data_v sets + * the component array of v to be data_V by storing the + * pointer data_v. + * + * The assignment v_llen = NV_LOCLENGTH_P(v) sets v_llen to + * be the length of the local part of the vector v. The call + * NV_LOCLENGTH_P(v) = llen_v sets the local length + * of v to be llen_v. + * + * The assignment v_glen = NV_GLOBLENGTH_P(v) sets v_glen to + * be the global length of the vector v. The call + * NV_GLOBLENGTH_P(v) = glen_v sets the global length of v to + * be glen_v. + * + * The assignment v_comm = NV_COMM_P(v) sets v_comm to be the + * MPI communicator of the vector v. The assignment + * NV_COMM_C(v) = comm_v sets the MPI communicator of v to be + * comm_v. + * + * (3) NV_Ith_P + * + * In the following description, the components of the + * local part of an N_Vector are numbered 0..n-1, where n + * is the local length of (the local part of) v. + * + * The assignment r = NV_Ith_P(v,i) sets r to be the value + * of the ith component of the local part of the vector v. + * The assignment NV_Ith_P(v,i) = r sets the value of the + * ith local component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_P(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_P(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_P(v) ( (N_VectorContent_Parallel)(v->content) ) + +#define NV_LOCLENGTH_P(v) ( NV_CONTENT_P(v)->local_length ) + +#define NV_GLOBLENGTH_P(v) ( NV_CONTENT_P(v)->global_length ) + +#define NV_OWN_DATA_P(v) ( NV_CONTENT_P(v)->own_data ) + +#define NV_DATA_P(v) ( NV_CONTENT_P(v)->data ) + +#define NV_COMM_P(v) ( NV_CONTENT_P(v)->comm ) + +#define NV_Ith_P(v,i) ( NV_DATA_P(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_parallel + * + * CONSTRUCTORS: + * N_VNew_Parallel + * N_VNewEmpty_Parallel + * N_VMake_Parallel + * N_VCloneVectorArray_Parallel + * N_VCloneVectorArrayEmpty_Parallel + * DESTRUCTORS: + * N_VDestroy_Parallel + * N_VDestroyVectorArray_Parallel + * OTHER: + * N_VPrint_Parallel + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Parallel + * ----------------------------------------------------------------- + * This function creates and allocates memory for a parallel vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Parallel(MPI_Comm comm, + long int local_length, + long int global_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Parallel + * ----------------------------------------------------------------- + * This function creates a new parallel N_Vector with an empty + * (NULL) data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, + long int local_length, + long int global_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Parallel + * ----------------------------------------------------------------- + * This function creates and allocates memory for a parallel vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Parallel(MPI_Comm comm, + long int local_length, + long int global_length, + realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Parallel + * ----------------------------------------------------------------- + * This function creates an array of 'count' PARALLEL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Parallel(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Parallel + * ----------------------------------------------------------------- + * This function creates an array of 'count' PARALLEL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Parallel(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Parallel + * ----------------------------------------------------------------- + * This function frees an array of N_Vector created with + * N_VCloneVectorArray_Parallel or N_VCloneVectorArrayEmpty_Parallel. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Parallel + * ----------------------------------------------------------------- + * This function prints the content of a parallel vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Parallel(N_Vector v); + +/* + * ----------------------------------------------------------------- + * parallel implementations of the vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Parallel(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Parallel(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Parallel(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Parallel(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Parallel(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Parallel(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Parallel(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Parallel(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Parallel(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/nvector/nvector_serial.h b/dep/cvode-2.7.0/include/nvector/nvector_serial.h new file mode 100644 index 00000000..4301a686 --- /dev/null +++ b/dep/cvode-2.7.0/include/nvector/nvector_serial.h @@ -0,0 +1,265 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the serial implementation of the + * NVECTOR module. + * + * Part I contains declarations specific to the serial + * implementation of the supplied NVECTOR module. + * + * Part II defines accessor macros that allow the user to + * efficiently use the type N_Vector without making explicit + * references to the underlying data structure. + * + * Part III contains the prototype for the constructor N_VNew_Serial + * as well as implementation-specific prototypes for various useful + * vector operations. + * + * Notes: + * + * - The definition of the generic N_Vector structure can be found + * in the header file sundials_nvector.h. + * + * - The definition of the type 'realtype' can be found in the + * header file sundials_types.h, and it may be changed (at the + * configuration stage) according to the user's needs. + * The sundials_types.h file also contains the definition + * for the type 'booleantype'. + * + * - N_Vector arguments to arithmetic vector operations need not + * be distinct. For example, the following call: + * + * N_VLinearSum_Serial(a,x,b,y,y); + * + * (which stores the result of the operation a*x+b*y in y) + * is legal. + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_SERIAL_H +#define _NVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * PART I: SERIAL implementation of N_Vector + * ----------------------------------------------------------------- + */ + +/* serial implementation of the N_Vector 'content' structure + contains the length of the vector, a pointer to an array + of 'realtype' components, and a flag indicating ownership of + the data */ + +struct _N_VectorContent_Serial { + long int length; + booleantype own_data; + realtype *data; +}; + +typedef struct _N_VectorContent_Serial *N_VectorContent_Serial; + +/* + * ----------------------------------------------------------------- + * PART II: macros NV_CONTENT_S, NV_DATA_S, NV_OWN_DATA_S, + * NV_LENGTH_S, and NV_Ith_S + * ----------------------------------------------------------------- + * In the descriptions below, the following user declarations + * are assumed: + * + * N_Vector v; + * long int i; + * + * (1) NV_CONTENT_S + * + * This routines gives access to the contents of the serial + * vector N_Vector. + * + * The assignment v_cont = NV_CONTENT_S(v) sets v_cont to be + * a pointer to the serial N_Vector content structure. + * + * (2) NV_DATA_S NV_OWN_DATA_S and NV_LENGTH_S + * + * These routines give access to the individual parts of + * the content structure of a serial N_Vector. + * + * The assignment v_data = NV_DATA_S(v) sets v_data to be + * a pointer to the first component of v. The assignment + * NV_DATA_S(v) = data_V sets the component array of v to + * be data_v by storing the pointer data_v. + * + * The assignment v_len = NV_LENGTH_S(v) sets v_len to be + * the length of v. The call NV_LENGTH_S(v) = len_v sets + * the length of v to be len_v. + * + * (3) NV_Ith_S + * + * In the following description, the components of an + * N_Vector are numbered 0..n-1, where n is the length of v. + * + * The assignment r = NV_Ith_S(v,i) sets r to be the value of + * the ith component of v. The assignment NV_Ith_S(v,i) = r + * sets the value of the ith component of v to be r. + * + * Note: When looping over the components of an N_Vector v, it is + * more efficient to first obtain the component array via + * v_data = NV_DATA_S(v) and then access v_data[i] within the + * loop than it is to use NV_Ith_S(v,i) within the loop. + * ----------------------------------------------------------------- + */ + +#define NV_CONTENT_S(v) ( (N_VectorContent_Serial)(v->content) ) + +#define NV_LENGTH_S(v) ( NV_CONTENT_S(v)->length ) + +#define NV_OWN_DATA_S(v) ( NV_CONTENT_S(v)->own_data ) + +#define NV_DATA_S(v) ( NV_CONTENT_S(v)->data ) + +#define NV_Ith_S(v,i) ( NV_DATA_S(v)[i] ) + +/* + * ----------------------------------------------------------------- + * PART III: functions exported by nvector_serial + * + * CONSTRUCTORS: + * N_VNew_Serial + * N_VNewEmpty_Serial + * N_VMake_Serial + * N_VCloneVectorArray_Serial + * N_VCloneVectorArrayEmpty_Serial + * DESTRUCTORS: + * N_VDestroy_Serial + * N_VDestroyVectorArray_Serial + * OTHER: + * N_VPrint_Serial + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * Function : N_VNew_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VNewEmpty_Serial + * ----------------------------------------------------------------- + * This function creates a new serial N_Vector with an empty (NULL) + * data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length); + +/* + * ----------------------------------------------------------------- + * Function : N_VMake_Serial + * ----------------------------------------------------------------- + * This function creates and allocates memory for a serial vector + * with a user-supplied data array. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VMake_Serial(long int vec_length, realtype *v_data); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArray_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors by + * cloning a given vector w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VCloneVectorArrayEmpty_Serial + * ----------------------------------------------------------------- + * This function creates an array of 'count' SERIAL vectors each + * with an empty (NULL) data array by cloning w. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w); + +/* + * ----------------------------------------------------------------- + * Function : N_VDestroyVectorArray_Serial + * ----------------------------------------------------------------- + * This function frees an array of SERIAL vectors created with + * N_VCloneVectorArray_Serial or N_VCloneVectorArrayEmpty_Serial. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VDestroyVectorArray_Serial(N_Vector *vs, int count); + +/* + * ----------------------------------------------------------------- + * Function : N_VPrint_Serial + * ----------------------------------------------------------------- + * This function prints the content of a serial vector to stdout. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void N_VPrint_Serial(N_Vector v); + +/* + * ----------------------------------------------------------------- + * serial implementations of various useful vector operations + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Serial(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VClone_Serial(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Serial(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst_Serial(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd_Serial(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin_Serial(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm_Serial(N_Vector x); +SUNDIALS_EXPORT void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest_Serial(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_band.h b/dep/cvode-2.7.0/include/sundials/sundials_band.h new file mode 100644 index 00000000..a4d91093 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_band.h @@ -0,0 +1,154 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/01 22:17:18 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic BAND linear solver + * package, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of band solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for band matrix arguments. + * Routines that work with the type DlsMat begin with "Band". + * Routines that work with realtype ** begin with "band" + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_BAND_H +#define _SUNDIALS_BAND_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRF + * ----------------------------------------------------------------- + * Usage : ier = BandGBTRF(A, p); + * if (ier != 0) ... A is singular + * ----------------------------------------------------------------- + * BandGBTRF performs the LU factorization of the N by N band + * matrix A. This is done using standard Gaussian elimination + * with partial pivoting. + * + * A successful LU factorization leaves the "matrix" A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower triangular + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * triangular part of A contains the multipliers, I-L. + * + * BandGBTRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * Important Note: A must be allocated to accommodate the increase + * in upper bandwidth that occurs during factorization. If + * mathematically, A is a band matrix with upper bandwidth mu and + * lower bandwidth ml, then the upper triangular factor U can + * have upper bandwidth as big as smu = MIN(n-1,mu+ml). The lower + * triangular factor L has lower bandwidth ml. Allocate A with + * call A = BandAllocMat(N,mu,ml,smu), where mu, ml, and smu are + * as defined above. The user does not have to zero the "extra" + * storage allocated for the purpose of factorization. This will + * handled by the BandGBTRF routine. + * + * BandGBTRF is only a wrapper around bandGBTRF. All work is done + * in bandGBTRF works directly on the data in the DlsMat A (i.e., + * the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT long int BandGBTRF(DlsMat A, long int *p); +SUNDIALS_EXPORT long int bandGBTRF(realtype **a, long int n, long int mu, long int ml, + long int smu, long int *p); + +/* + * ----------------------------------------------------------------- + * Function : BandGBTRS + * ----------------------------------------------------------------- + * Usage : BandGBTRS(A, p, b); + * ----------------------------------------------------------------- + * BandGBTRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in BandGBTRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to BandGBTRF + * did not fail. + * + * BandGBTRS is only a wrapper around bandGBTRS which does all the + * work directly on the data in the DlsMat A (i.e., the field cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandGBTRS(DlsMat A, long int *p, realtype *b); +SUNDIALS_EXPORT void bandGBTRS(realtype **a, long int n, long int smu, long int ml, long int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Function : BandCopy + * ----------------------------------------------------------------- + * Usage : BandCopy(A, B, copymu, copyml); + * ----------------------------------------------------------------- + * BandCopy copies the submatrix with upper and lower bandwidths + * copymu, copyml of the N by N band matrix A into the N by N + * band matrix B. + * + * BandCopy is a wrapper around bandCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandCopy(DlsMat A, DlsMat B, long int copymu, long int copyml); +SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, long int n, long int a_smu, long int b_smu, + long int copymu, long int copyml); + +/* + * ----------------------------------------------------------------- + * Function: BandScale + * ----------------------------------------------------------------- + * Usage : BandScale(c, A); + * ----------------------------------------------------------------- + * A(i,j) <- c*A(i,j), j-(A->mu) <= i <= j+(A->ml). + * + * BandScale is a wrapper around bandScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void BandScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, long int n, long int mu, long int ml, long int smu); + +/* + * ----------------------------------------------------------------- + * Function: bandAddIdentity + * ----------------------------------------------------------------- + * bandAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void bandAddIdentity(realtype **a, long int n, long int smu); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_config.in b/dep/cvode-2.7.0/include/sundials/sundials_config.in new file mode 100644 index 00000000..8a10b7ec --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_config.in @@ -0,0 +1,76 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/15 22:45:17 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * SUNDIALS configuration header file + *------------------------------------------------------------------ + */ + +/* Define SUNDIALS version number */ +#define SUNDIALS_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* FCMIX: Define Fortran name-mangling macro for C identifiers. + * Depending on the inferred scheme, one of the following six + * macros will be defined: + * #define SUNDIALS_F77_FUNC(name,NAME) name + * #define SUNDIALS_F77_FUNC(name,NAME) name ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) name ## __ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _ + * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __ + */ +@F77_MANGLE_MACRO1@ + +/* FCMIX: Define Fortran name-mangling macro for C identifiers + * which contain underscores. + */ +@F77_MANGLE_MACRO2@ + +/* Define precision of SUNDIALS data type 'realtype' + * Depending on the precision level, one of the following + * three macros will be defined: + * #define SUNDIALS_SINGLE_PRECISION 1 + * #define SUNDIALS_DOUBLE_PRECISION 1 + * #define SUNDIALS_EXTENDED_PRECISION 1 + */ +@PRECISION_LEVEL@ + +/* Use generic math functions + * If it was decided that generic math functions can be used, then + * #define SUNDIALS_USE_GENERIC_MATH + */ +@GENERIC_MATH_LIB@ + +/* Blas/Lapack available + * If working libraries for Blas/lapack support were found, then + * #define SUNDIALS_BLAS_LAPACK 1 + * otherwise + * #define SUNDIALS_BLAS_LAPACK 0 + */ +@BLAS_LAPACK_MACRO@ + +/* FNVECTOR: Allow user to specify different MPI communicator + * If it was found that the MPI implementation supports MPI_Comm_f2c, then + * #define SUNDIALS_MPI_COMM_F2C 1 + * otherwise + * #define SUNDIALS_MPI_COMM_F2C 0 + */ +@F77_MPI_COMM_F2C@ + +/* Mark SUNDIALS API functions for export/import + * When building shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllexport) + * When linking to shared SUNDIALS libraries under Windows, use + * #define SUNDIALS_EXPORT __declspec(dllimport) + * In all other cases (other platforms or static libraries under + * Windows), the SUNDIALS_EXPORT macro is empty + */ +@SUNDIALS_EXPORT@ diff --git a/dep/cvode-2.7.0/include/sundials/sundials_dense.h b/dep/cvode-2.7.0/include/sundials/sundials_dense.h new file mode 100644 index 00000000..f2ddeb0c --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_dense.h @@ -0,0 +1,187 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.8 $ + * $Date: 2010/12/01 22:17:18 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of DENSE matrix + * operations, based on the DlsMat type defined in sundials_direct.h. + * + * There are two sets of dense solver routines listed in + * this file: one set uses type DlsMat defined below and the + * other set uses the type realtype ** for dense matrix arguments. + * Routines that work with the type DlsMat begin with "Dense". + * Routines that work with realtype** begin with "dense". + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DENSE_H +#define _SUNDIALS_DENSE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Functions: DenseGETRF and DenseGETRS + * ----------------------------------------------------------------- + * DenseGETRF performs the LU factorization of the M by N dense + * matrix A. This is done using standard Gaussian elimination + * with partial (row) pivoting. Note that this applies only + * to matrices with M >= N and full column rank. + * + * A successful LU factorization leaves the matrix A and the + * pivot array p with the following information: + * + * (1) p[k] contains the row number of the pivot element chosen + * at the beginning of elimination step k, k=0, 1, ..., N-1. + * + * (2) If the unique LU factorization of A is given by PA = LU, + * where P is a permutation matrix, L is a lower trapezoidal + * matrix with all 1's on the diagonal, and U is an upper + * triangular matrix, then the upper triangular part of A + * (including its diagonal) contains U and the strictly lower + * trapezoidal part of A contains the multipliers, I-L. + * + * For square matrices (M=N), L is unit lower triangular. + * + * DenseGETRF returns 0 if successful. Otherwise it encountered + * a zero diagonal element during the factorization. In this case + * it returns the column index (numbered from one) at which + * it encountered the zero. + * + * DenseGETRS solves the N-dimensional system A x = b using + * the LU factorization in A and the pivot information in p + * computed in DenseGETRF. The solution x is returned in b. This + * routine cannot fail if the corresponding call to DenseGETRF + * did not fail. + * DenseGETRS does NOT check for a square matrix! + * + * ----------------------------------------------------------------- + * DenseGETRF and DenseGETRS are simply wrappers around denseGETRF + * and denseGETRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT long int DenseGETRF(DlsMat A, long int *p); +SUNDIALS_EXPORT void DenseGETRS(DlsMat A, long int *p, realtype *b); + +SUNDIALS_EXPORT long int denseGETRF(realtype **a, long int m, long int n, long int *p); +SUNDIALS_EXPORT void denseGETRS(realtype **a, long int n, long int *p, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DensePOTRF and DensePOTRS + * ----------------------------------------------------------------- + * DensePOTRF computes the Cholesky factorization of a real symmetric + * positive definite matrix A. + * ----------------------------------------------------------------- + * DensePOTRS solves a system of linear equations A*X = B with a + * symmetric positive definite matrix A using the Cholesky factorization + * A = L*L**T computed by DensePOTRF. + * + * ----------------------------------------------------------------- + * DensePOTRF and DensePOTRS are simply wrappers around densePOTRF + * and densePOTRS, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT long int DensePOTRF(DlsMat A); +SUNDIALS_EXPORT void DensePOTRS(DlsMat A, realtype *b); + +SUNDIALS_EXPORT long int densePOTRF(realtype **a, long int m); +SUNDIALS_EXPORT void densePOTRS(realtype **a, long int m, realtype *b); + +/* + * ----------------------------------------------------------------- + * Functions : DenseGEQRF and DenseORMQR + * ----------------------------------------------------------------- + * DenseGEQRF computes a QR factorization of a real M-by-N matrix A: + * A = Q * R (with M>= N). + * + * DenseGEQRF requires a temporary work vector wrk of length M. + * ----------------------------------------------------------------- + * DenseORMQR computes the product w = Q * v where Q is a real + * orthogonal matrix defined as the product of k elementary reflectors + * + * Q = H(1) H(2) . . . H(k) + * + * as returned by DenseGEQRF. Q is an M-by-N matrix, v is a vector + * of length N and w is a vector of length M (with M>=N). + * + * DenseORMQR requires a temporary work vector wrk of length M. + * + * ----------------------------------------------------------------- + * DenseGEQRF and DenseORMQR are simply wrappers around denseGEQRF + * and denseORMQR, respectively, which perform all the work by + * directly accessing the data in the DlsMat A (i.e. the field cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk); +SUNDIALS_EXPORT int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, + realtype *wrk); + +SUNDIALS_EXPORT int denseGEQRF(realtype **a, long int m, long int n, realtype *beta, realtype *v); +SUNDIALS_EXPORT int denseORMQR(realtype **a, long int m, long int n, realtype *beta, + realtype *v, realtype *w, realtype *wrk); + +/* + * ----------------------------------------------------------------- + * Function : DenseCopy + * ----------------------------------------------------------------- + * DenseCopy copies the contents of the M-by-N matrix A into the + * M-by-N matrix B. + * + * DenseCopy is a wrapper around denseCopy which accesses the data + * in the DlsMat A and B (i.e. the fields cols) + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseCopy(DlsMat A, DlsMat B); +SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, long int m, long int n); + +/* + * ----------------------------------------------------------------- + * Function: DenseScale + * ----------------------------------------------------------------- + * DenseScale scales the elements of the M-by-N matrix A by the + * constant c and stores the result back in A. + * + * DenseScale is a wrapper around denseScale which performs the actual + * scaling by accessing the data in the DlsMat A (i.e. the field + * cols). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DenseScale(realtype c, DlsMat A); +SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, long int m, long int n); + + +/* + * ----------------------------------------------------------------- + * Function: denseAddIdentity + * ----------------------------------------------------------------- + * denseAddIdentity adds the identity matrix to the n-by-n matrix + * stored in the realtype** arrays. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void denseAddIdentity(realtype **a, long int n); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_direct.h b/dep/cvode-2.7.0/include/sundials/sundials_direct.h new file mode 100644 index 00000000..da99f2b8 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_direct.h @@ -0,0 +1,336 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2010/12/22 22:18:49 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains definitions and declarations for use by + * generic direct linear solvers for Ax = b. It defines types for + * dense and banded matrices and corresponding accessor macros. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_DIRECT_H +#define _SUNDIALS_DIRECT_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ================================================================= + * C O N S T A N T S + * ================================================================= + */ + +/* + * SUNDIALS_DENSE: dense matrix + * SUNDIALS_BAND: banded matrix + */ + +#define SUNDIALS_DENSE 1 +#define SUNDIALS_BAND 2 + +/* + * ================================================================== + * Type definitions + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Type : DlsMat + * ----------------------------------------------------------------- + * The type DlsMat is defined to be a pointer to a structure + * with various sizes, a data field, and an array of pointers to + * the columns which defines a dense or band matrix for use in + * direct linear solvers. The M and N fields indicates the number + * of rows and columns, respectively. The data field is a one + * dimensional array used for component storage. The cols field + * stores the pointers in data for the beginning of each column. + * ----------------------------------------------------------------- + * For DENSE matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_DENSE + * M - number of rows + * N - number of columns + * ldim - leading dimension (ldim >= M) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*N + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The elements of a dense matrix are stored columnwise (i.e columns + * are stored one on top of the other in memory). + * If A is of type DlsMat, then the (i,j)th element of A (with + * 0 <= i < M and 0 <= j < N) is given by (A->data)[j*n+i]. + * + * The DENSE_COL and DENSE_ELEM macros below allow a user to access + * efficiently individual matrix elements without writing out explicit + * data structure references and without knowing too much about the + * underlying element storage. The only storage assumption needed is + * that elements are stored columnwise and that a pointer to the + * jth column of elements can be obtained via the DENSE_COL macro. + * ----------------------------------------------------------------- + * For BAND matrices, the relevant fields in DlsMat are: + * type = SUNDIALS_BAND + * M - number of rows + * N - number of columns + * mu - upper bandwidth, 0 <= mu <= min(M,N) + * ml - lower bandwidth, 0 <= ml <= min(M,N) + * s_mu - storage upper bandwidth, mu <= s_mu <= N-1. + * The dgbtrf routine writes the LU factors into the storage + * for A. The upper triangular factor U, however, may have + * an upper bandwidth as big as MIN(N-1,mu+ml) because of + * partial pivoting. The s_mu field holds the upper + * bandwidth allocated for A. + * ldim - leading dimension (ldim >= s_mu) + * data - pointer to a contiguous block of realtype variables + * ldata - length of the data array =ldim*(s_mu+ml+1) + * cols - array of pointers. cols[j] points to the first element + * of the j-th column of the matrix in the array data. + * + * The BAND_COL, BAND_COL_ELEM, and BAND_ELEM macros below allow a + * user to access individual matrix elements without writing out + * explicit data structure references and without knowing too much + * about the underlying element storage. The only storage assumption + * needed is that elements are stored columnwise and that a pointer + * into the jth column of elements can be obtained via the BAND_COL + * macro. The BAND_COL_ELEM macro selects an element from a column + * which has already been isolated via BAND_COL. The macro + * BAND_COL_ELEM allows the user to avoid the translation + * from the matrix location (i,j) to the index in the array returned + * by BAND_COL at which the (i,j)th element is stored. + * ----------------------------------------------------------------- + */ + +typedef struct _DlsMat { + int type; + long int M; + long int N; + long int ldim; + long int mu; + long int ml; + long int s_mu; + realtype *data; + long int ldata; + realtype **cols; +} *DlsMat; + +/* + * ================================================================== + * Data accessor macros + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * DENSE_COL and DENSE_ELEM + * ----------------------------------------------------------------- + * + * DENSE_COL(A,j) references the jth column of the M-by-N dense + * matrix A, 0 <= j < N. The type of the expression DENSE_COL(A,j) + * is (realtype *). After the assignment in the usage above, col_j + * may be treated as an array indexed from 0 to M-1. The (i,j)-th + * element of A is thus referenced by col_j[i]. + * + * DENSE_ELEM(A,i,j) references the (i,j)th element of the dense + * M-by-N matrix A, 0 <= i < M ; 0 <= j < N. + * + * ----------------------------------------------------------------- + */ + +#define DENSE_COL(A,j) ((A->cols)[j]) +#define DENSE_ELEM(A,i,j) ((A->cols)[j][i]) + +/* + * ----------------------------------------------------------------- + * BAND_COL, BAND_COL_ELEM, and BAND_ELEM + * ----------------------------------------------------------------- + * + * BAND_COL(A,j) references the diagonal element of the jth column + * of the N by N band matrix A, 0 <= j <= N-1. The type of the + * expression BAND_COL(A,j) is realtype *. The pointer returned by + * the call BAND_COL(A,j) can be treated as an array which is + * indexed from -(A->mu) to (A->ml). + * + * BAND_COL_ELEM references the (i,j)th entry of the band matrix A + * when used in conjunction with BAND_COL. The index (i,j) should + * satisfy j-(A->mu) <= i <= j+(A->ml). + * + * BAND_ELEM(A,i,j) references the (i,j)th element of the M-by-N + * band matrix A, where 0 <= i,j <= N-1. The location (i,j) should + * further satisfy j-(A->mu) <= i <= j+(A->ml). + * + * ----------------------------------------------------------------- + */ + +#define BAND_COL(A,j) (((A->cols)[j])+(A->s_mu)) +#define BAND_COL_ELEM(col_j,i,j) (col_j[(i)-(j)]) +#define BAND_ELEM(A,i,j) ((A->cols)[j][(i)-(j)+(A->s_mu)]) + +/* + * ================================================================== + * Exported function prototypes (functions working on dlsMat) + * ================================================================== + */ + +/* + * ----------------------------------------------------------------- + * Function: NewDenseMat + * ----------------------------------------------------------------- + * NewDenseMat allocates memory for an M-by-N dense matrix and + * returns the storage allocated (type DlsMat). NewDenseMat + * returns NULL if the request for matrix storage cannot be + * satisfied. See the above documentation for the type DlsMat + * for matrix storage details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewDenseMat(long int M, long int N); + +/* + * ----------------------------------------------------------------- + * Function: NewBandMat + * ----------------------------------------------------------------- + * NewBandMat allocates memory for an M-by-N band matrix + * with upper bandwidth mu, lower bandwidth ml, and storage upper + * bandwidth smu. Pass smu as follows depending on whether A will + * be LU factored: + * + * (1) Pass smu = mu if A will not be factored. + * + * (2) Pass smu = MIN(N-1,mu+ml) if A will be factored. + * + * NewBandMat returns the storage allocated (type DlsMat) or + * NULL if the request for matrix storage cannot be satisfied. + * See the documentation for the type DlsMat for matrix storage + * details. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu); + +/* + * ----------------------------------------------------------------- + * Functions: DestroyMat + * ----------------------------------------------------------------- + * DestroyMat frees the memory allocated by NewDenseMat or NewBandMat + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyMat(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function: NewIntArray + * ----------------------------------------------------------------- + * NewIntArray allocates memory an array of N int's and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int *NewIntArray(int N); + +/* + * ----------------------------------------------------------------- + * Function: NewLintArray + * ----------------------------------------------------------------- + * NewLintArray allocates memory an array of N long int's and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT long int *NewLintArray(long int N); + +/* + * ----------------------------------------------------------------- + * Function: NewRealArray + * ----------------------------------------------------------------- + * NewRealArray allocates memory an array of N realtype and returns + * the pointer to the memory it allocates. If the request for + * memory storage cannot be satisfied, it returns NULL. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype *NewRealArray(long int N); + +/* + * ----------------------------------------------------------------- + * Function: DestroyArray + * ----------------------------------------------------------------- + * DestroyArray frees memory allocated by NewIntArray, NewLintArray, + * or NewRealArray. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void DestroyArray(void *p); + +/* + * ----------------------------------------------------------------- + * Function : AddIdentity + * ----------------------------------------------------------------- + * AddIdentity adds 1.0 to the main diagonal (A_ii, i=1,2,...,N-1) of + * the M-by-N matrix A (M>= N) and stores the result back in A. + * AddIdentity is typically used with square matrices. + * AddIdentity does not check for M >= N and therefore a segmentation + * fault will occur if M < N! + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void AddIdentity(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Function : SetToZero + * ----------------------------------------------------------------- + * SetToZero sets all the elements of the M-by-N matrix A to 0.0. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SetToZero(DlsMat A); + +/* + * ----------------------------------------------------------------- + * Functions: PrintMat + * ----------------------------------------------------------------- + * This function prints the M-by-N (dense or band) matrix A to + * standard output as it would normally appear on paper. + * It is intended as debugging tools with small values of M and N. + * The elements are printed using the %g/%lg/%Lg option. + * A blank line is printed before and after the matrix. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void PrintMat(DlsMat A); + + +/* + * ================================================================== + * Exported function prototypes (functions working on realtype**) + * ================================================================== + */ + +SUNDIALS_EXPORT realtype **newDenseMat(long int m, long int n); +SUNDIALS_EXPORT realtype **newBandMat(long int n, long int smu, long int ml); +SUNDIALS_EXPORT void destroyMat(realtype **a); +SUNDIALS_EXPORT int *newIntArray(int n); +SUNDIALS_EXPORT long int *newLintArray(long int n); +SUNDIALS_EXPORT realtype *newRealArray(long int m); +SUNDIALS_EXPORT void destroyArray(void *v); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_fnvector.h b/dep/cvode-2.7.0/include/sundials/sundials_fnvector.h new file mode 100644 index 00000000..bbc9a95e --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_fnvector.h @@ -0,0 +1,41 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:27:52 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector.h) contains definitions + * needed for the initialization of vector operations in Fortran. + * ----------------------------------------------------------------- + */ + + +#ifndef _FNVECTOR_H +#define _FNVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +/* SUNDIALS solver IDs */ + +#define FCMIX_CVODE 1 +#define FCMIX_IDA 2 +#define FCMIX_KINSOL 3 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_iterative.h b/dep/cvode-2.7.0/include/sundials/sundials_iterative.h new file mode 100644 index 00000000..5e7e4bf4 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_iterative.h @@ -0,0 +1,242 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This header file contains declarations intended for use by + * generic iterative solvers of Ax = b. The enumeration gives + * symbolic names for the type of preconditioning to be used. + * The function type declarations give the prototypes for the + * functions to be called within an iterative linear solver, that + * are responsible for + * multiplying A by a given vector v (ATimesFn), and + * solving the preconditioner equation Pz = r (PSolveFn). + * ----------------------------------------------------------------- + */ + +#ifndef _ITERATIVE_H +#define _ITERATIVE_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + + +/* + * ----------------------------------------------------------------- + * enum : types of preconditioning + * ----------------------------------------------------------------- + * PREC_NONE : The iterative linear solver should not use + * preconditioning. + * + * PREC_LEFT : The iterative linear solver uses preconditioning on + * the left only. + * + * PREC_RIGHT : The iterative linear solver uses preconditioning on + * the right only. + * + * PREC_BOTH : The iterative linear solver uses preconditioning on + * both the left and the right. + * ----------------------------------------------------------------- + */ + +enum { PREC_NONE, PREC_LEFT, PREC_RIGHT, PREC_BOTH }; + +/* + * ----------------------------------------------------------------- + * enum : types of Gram-Schmidt routines + * ----------------------------------------------------------------- + * MODIFIED_GS : The iterative solver uses the modified + * Gram-Schmidt routine ModifiedGS listed in this + * file. + * + * CLASSICAL_GS : The iterative solver uses the classical + * Gram-Schmidt routine ClassicalGS listed in this + * file. + * ----------------------------------------------------------------- + */ + +enum { MODIFIED_GS = 1, CLASSICAL_GS = 2 }; + +/* + * ----------------------------------------------------------------- + * Type: ATimesFn + * ----------------------------------------------------------------- + * An ATimesFn multiplies Av and stores the result in z. The + * caller is responsible for allocating memory for the z vector. + * The parameter A_data is a pointer to any information about A + * which the function needs in order to do its job. The vector v + * is unchanged. An ATimesFn returns 0 if successful and a + * non-zero value if unsuccessful. + * ----------------------------------------------------------------- + */ + +typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z); + +/* + * ----------------------------------------------------------------- + * Type: PSolveFn + * ----------------------------------------------------------------- + * A PSolveFn solves the preconditioner equation Pz = r for the + * vector z. The caller is responsible for allocating memory for + * the z vector. The parameter P_data is a pointer to any + * information about P which the function needs in order to do + * its job. The parameter lr is input, and indicates whether P + * is to be taken as the left preconditioner or the right + * preconditioner: lr = 1 for left and lr = 2 for right. + * If preconditioning is on one side only, lr can be ignored. + * The vector r is unchanged. + * A PSolveFn returns 0 if successful and a non-zero value if + * unsuccessful. On a failure, a negative return value indicates + * an unrecoverable condition, while a positive value indicates + * a recoverable one, in which the calling routine may reattempt + * the solution after updating preconditioner data. + * ----------------------------------------------------------------- + */ + +typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr); + +/* + * ----------------------------------------------------------------- + * Function: ModifiedGS + * ----------------------------------------------------------------- + * ModifiedGS performs a modified Gram-Schmidt orthogonalization + * of the N_Vector v[k] against the p unit N_Vectors at + * v[k-1], v[k-2], ..., v[k-p]. + * + * v is an array of (k+1) N_Vectors v[i], i=0, 1, ..., k. + * v[k-1], v[k-2], ..., v[k-p] are assumed to have L2-norm + * equal to 1. + * + * h is the output k by k Hessenberg matrix of inner products. + * This matrix must be allocated row-wise so that the (i,j)th + * entry is h[i][j]. The inner products (v[i],v[k]), + * i=i0, i0+1, ..., k-1, are stored at h[i][k-1]. Here + * i0=MAX(0,k-p). + * + * k is the index of the vector in the v array that needs to be + * orthogonalized against previous vectors in the v array. + * + * p is the number of previous vectors in the v array against + * which v[k] is to be orthogonalized. + * + * new_vk_norm is a pointer to memory allocated by the caller to + * hold the Euclidean norm of the orthogonalized vector v[k]. + * + * If (k-p) < 0, then ModifiedGS uses p=k. The orthogonalized + * v[k] is NOT normalized and is stored over the old v[k]. Once + * the orthogonalization has been performed, the Euclidean norm + * of v[k] is stored in (*new_vk_norm). + * + * ModifiedGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm); + +/* + * ----------------------------------------------------------------- + * Function: ClassicalGS + * ----------------------------------------------------------------- + * ClassicalGS performs a classical Gram-Schmidt + * orthogonalization of the N_Vector v[k] against the p unit + * N_Vectors at v[k-1], v[k-2], ..., v[k-p]. The parameters v, h, + * k, p, and new_vk_norm are as described in the documentation + * for ModifiedGS. + * + * temp is an N_Vector which can be used as workspace by the + * ClassicalGS routine. + * + * s is a length k array of realtype which can be used as + * workspace by the ClassicalGS routine. + * + * ClassicalGS returns 0 to indicate success. It cannot fail. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s); + +/* + * ----------------------------------------------------------------- + * Function: QRfact + * ----------------------------------------------------------------- + * QRfact performs a QR factorization of the Hessenberg matrix H. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is the (n+1) by n Hessenberg matrix H to be factored. It is + * stored row-wise. + * + * q is an array of length 2*n containing the Givens rotations + * computed by this function. A Givens rotation has the form: + * | c -s | + * | s c |. + * The components of the Givens rotations are stored in q as + * (c, s, c, s, ..., c, s). + * + * job is a control flag. If job==0, then a new QR factorization + * is performed. If job!=0, then it is assumed that the first + * n-1 columns of h have already been factored and only the last + * column needs to be updated. + * + * QRfact returns 0 if successful. If a zero is encountered on + * the diagonal of the triangular factor R, then QRfact returns + * the equation number of the zero entry, where the equations are + * numbered from 1, not 0. If QRsol is subsequently called in + * this situation, it will return an error because it could not + * divide by the zero diagonal entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRfact(int n, realtype **h, realtype *q, int job); + +/* + * ----------------------------------------------------------------- + * Function: QRsol + * ----------------------------------------------------------------- + * QRsol solves the linear least squares problem + * + * min (b - H*x, b - H*x), x in R^n, + * + * where H is a Hessenberg matrix, and b is in R^(n+1). + * It uses the QR factors of H computed by QRfact. + * + * n is the problem size; the matrix H is (n+1) by n. + * + * h is a matrix (computed by QRfact) containing the upper + * triangular factor R of the original Hessenberg matrix H. + * + * q is an array of length 2*n (computed by QRfact) containing + * the Givens rotations used to factor H. + * + * b is the (n+1)-vector appearing in the least squares problem + * above. + * + * On return, b contains the solution x of the least squares + * problem, if QRsol was successful. + * + * QRsol returns a 0 if successful. Otherwise, a zero was + * encountered on the diagonal of the triangular factor R. + * In this case, QRsol returns the equation number (numbered + * from 1, not 0) of the zero entry. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int QRsol(int n, realtype **h, realtype *q, realtype *b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_lapack.h b/dep/cvode-2.7.0/include/sundials/sundials_lapack.h new file mode 100644 index 00000000..4af89df8 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_lapack.h @@ -0,0 +1,126 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.6 $ + * $Date: 2009/02/17 02:39:26 $ + * ----------------------------------------------------------------- + * Programmer: Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2006, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic package of direct matrix + * operations for use with BLAS/LAPACK. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALS_LAPACK_H +#define _SUNDIALS_LAPACK_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* + * ================================================================== + * Blas and Lapack functions + * ================================================================== + */ + +#if defined(SUNDIALS_F77_FUNC) + +#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY) +#define dscal_f77 SUNDIALS_F77_FUNC(dscal, DSCAL) +#define dgemv_f77 SUNDIALS_F77_FUNC(dgemv, DGEMV) +#define dtrsv_f77 SUNDIALS_F77_FUNC(dtrsv, DTRSV) +#define dsyrk_f77 SUNDIALS_F77_FUNC(dsyrk, DSKYR) + +#define dgbtrf_f77 SUNDIALS_F77_FUNC(dgbtrf, DGBTRF) +#define dgbtrs_f77 SUNDIALS_F77_FUNC(dgbtrs, DGBTRS) +#define dgetrf_f77 SUNDIALS_F77_FUNC(dgetrf, DGETRF) +#define dgetrs_f77 SUNDIALS_F77_FUNC(dgetrs, DGETRS) +#define dgeqp3_f77 SUNDIALS_F77_FUNC(dgeqp3, DGEQP3) +#define dgeqrf_f77 SUNDIALS_F77_FUNC(dgeqrf, DGEQRF) +#define dormqr_f77 SUNDIALS_F77_FUNC(dormqr, DORMQR) +#define dpotrf_f77 SUNDIALS_F77_FUNC(dpotrf, DPOTRF) +#define dpotrs_f77 SUNDIALS_F77_FUNC(dpotrs, DPOTRS) + +#else + +#define dcopy_f77 dcopy_ +#define dscal_f77 dscal_ +#define dgemv_f77 dgemv_ +#define dtrsv_f77 dtrsv_ +#define dsyrk_f77 dsyrk_ + +#define dgbtrf_f77 dgbtrf_ +#define dgbtrs_f77 dgbtrs_ +#define dgeqp3_f77 dgeqp3_ +#define dgeqrf_f77 dgeqrf_ +#define dgetrf_f77 dgetrf_ +#define dgetrs_f77 dgetrs_ +#define dormqr_f77 dormqr_ +#define dpotrf_f77 dpotrf_ +#define dpotrs_f77 dpotrs_ + +#endif + +/* Level-1 BLAS */ + +extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y); +extern void dscal_f77(int *n, const double *alpha, double *x, const int *inc_x); + +/* Level-2 BLAS */ + +extern void dgemv_f77(const char *trans, int *m, int *n, const double *alpha, const double *a, + int *lda, const double *x, int *inc_x, const double *beta, double *y, int *inc_y, + int len_trans); + +extern void dtrsv_f77(const char *uplo, const char *trans, const char *diag, const int *n, + const double *a, const int *lda, double *x, const int *inc_x, + int len_uplo, int len_trans, int len_diag); + +/* Level-3 BLAS */ + +extern void dsyrk_f77(const char *uplo, const char *trans, const int *n, const int *k, + const double *alpha, const double *a, const int *lda, const double *beta, + const double *c, const int *ldc, int len_uplo, int len_trans); + +/* LAPACK */ + +extern void dgbtrf_f77(const int *m, const int *n, const int *kl, const int *ku, + double *ab, int *ldab, int *ipiv, int *info); + +extern void dgbtrs_f77(const char *trans, const int *n, const int *kl, const int *ku, const int *nrhs, + double *ab, const int *ldab, int *ipiv, double *b, const int *ldb, + int *info, int len_trans); + + +extern void dgeqp3_f77(const int *m, const int *n, double *a, const int *lda, int *jpvt, double *tau, + double *work, const int *lwork, int *info); + +extern void dgeqrf_f77(const int *m, const int *n, double *a, const int *lda, double *tau, double *work, + const int *lwork, int *info); + +extern void dgetrf_f77(const int *m, const int *n, double *a, int *lda, int *ipiv, int *info); + +extern void dgetrs_f77(const char *trans, const int *n, const int *nrhs, double *a, const int *lda, + int *ipiv, double *b, const int *ldb, int *info, int len_trans); + + +extern void dormqr_f77(const char *side, const char *trans, const int *m, const int *n, const int *k, + double *a, const int *lda, double *tau, double *c, const int *ldc, + double *work, const int *lwork, int *info, int len_side, int len_trans); + +extern void dpotrf_f77(const char *uplo, const int *n, double *a, int *lda, int *info, int len_uplo); + +extern void dpotrs_f77(const char *uplo, const int *n, const int *nrhs, double *a, const int *lda, + double *b, const int *ldb, int * info, int len_uplo); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_math.h b/dep/cvode-2.7.0/include/sundials/sundials_math.h new file mode 100644 index 00000000..99de0856 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_math.h @@ -0,0 +1,139 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a simple C-language math library. The + * routines listed here work with the type realtype as defined in + * the header file sundials_types.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SUNDIALSMATH_H +#define _SUNDIALSMATH_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Macros : MIN and MAX + * ----------------------------------------------------------------- + * MIN(A,B) returns the minimum of A and B + * + * MAX(A,B) returns the maximum of A and B + * + * SQR(A) returns A^2 + * ----------------------------------------------------------------- + */ + +#ifndef MIN +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#endif + +#ifndef MAX +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#endif + +#ifndef SQR +#define SQR(A) ((A)*(A)) +#endif + +#ifndef ABS +#define ABS RAbs +#endif + +#ifndef SQRT +#define SQRT RSqrt +#endif + +#ifndef EXP +#define EXP RExp +#endif + +/* + * ----------------------------------------------------------------- + * Function : RPowerI + * ----------------------------------------------------------------- + * Usage : int exponent; + * realtype base, ans; + * ans = RPowerI(base,exponent); + * ----------------------------------------------------------------- + * RPowerI returns the value of base^exponent, where base is of type + * realtype and exponent is of type int. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerI(realtype base, int exponent); + +/* + * ----------------------------------------------------------------- + * Function : RPowerR + * ----------------------------------------------------------------- + * Usage : realtype base, exponent, ans; + * ans = RPowerR(base,exponent); + * ----------------------------------------------------------------- + * RPowerR returns the value of base^exponent, where both base and + * exponent are of type realtype. If base < ZERO, then RPowerR + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RPowerR(realtype base, realtype exponent); + +/* + * ----------------------------------------------------------------- + * Function : RSqrt + * ----------------------------------------------------------------- + * Usage : realtype sqrt_x; + * sqrt_x = RSqrt(x); + * ----------------------------------------------------------------- + * RSqrt(x) returns the square root of x. If x < ZERO, then RSqrt + * returns ZERO. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RSqrt(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RAbs (a.k.a. ABS) + * ----------------------------------------------------------------- + * Usage : realtype abs_x; + * abs_x = RAbs(x); + * ----------------------------------------------------------------- + * RAbs(x) returns the absolute value of x. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RAbs(realtype x); + +/* + * ----------------------------------------------------------------- + * Function : RExp (a.k.a. EXP) + * ----------------------------------------------------------------- + * Usage : realtype exp_x; + * exp_x = RExp(x); + * ----------------------------------------------------------------- + * RExp(x) returns e^x (base-e exponential function). + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT realtype RExp(realtype x); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_nvector.h b/dep/cvode-2.7.0/include/sundials/sundials_nvector.h new file mode 100644 index 00000000..6142b328 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_nvector.h @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for a generic NVECTOR package. + * It defines the N_Vector structure (_generic_N_Vector) which + * contains the following fields: + * - an implementation-dependent 'content' field which contains + * the description and actual data of the vector + * - an 'ops' filed which contains a structure listing operations + * acting on such vectors + * + * Part I of this file contains type declarations for the + * _generic_N_Vector and _generic_N_Vector_Ops structures, as well + * as references to pointers to such structures (N_Vector). + * + * Part II of this file contains the prototypes for the vector + * functions which operate on N_Vector. + * + * At a minimum, a particular implementation of an NVECTOR must + * do the following: + * - specify the 'content' field of N_Vector, + * - implement the operations on those N_Vectors, + * - provide a constructor routine for new vectors + * + * Additionally, an NVECTOR implementation may provide the following: + * - macros to access the underlying N_Vector data + * - a constructor for an array of N_Vectors + * - a constructor for an empty N_Vector (i.e., a new N_Vector with + * a NULL data pointer). + * - a routine to print the content of an N_Vector + * ----------------------------------------------------------------- + */ + +#ifndef _NVECTOR_H +#define _NVECTOR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Generic definition of N_Vector + * ----------------------------------------------------------------- + */ + +/* Forward reference for pointer to N_Vector_Ops object */ +typedef struct _generic_N_Vector_Ops *N_Vector_Ops; + +/* Forward reference for pointer to N_Vector object */ +typedef struct _generic_N_Vector *N_Vector; + +/* Define array of N_Vectors */ +typedef N_Vector *N_Vector_S; + +/* Structure containing function pointers to vector operations */ +struct _generic_N_Vector_Ops { + N_Vector (*nvclone)(N_Vector); + N_Vector (*nvcloneempty)(N_Vector); + void (*nvdestroy)(N_Vector); + void (*nvspace)(N_Vector, long int *, long int *); + realtype* (*nvgetarraypointer)(N_Vector); + void (*nvsetarraypointer)(realtype *, N_Vector); + void (*nvlinearsum)(realtype, N_Vector, realtype, N_Vector, N_Vector); + void (*nvconst)(realtype, N_Vector); + void (*nvprod)(N_Vector, N_Vector, N_Vector); + void (*nvdiv)(N_Vector, N_Vector, N_Vector); + void (*nvscale)(realtype, N_Vector, N_Vector); + void (*nvabs)(N_Vector, N_Vector); + void (*nvinv)(N_Vector, N_Vector); + void (*nvaddconst)(N_Vector, realtype, N_Vector); + realtype (*nvdotprod)(N_Vector, N_Vector); + realtype (*nvmaxnorm)(N_Vector); + realtype (*nvwrmsnorm)(N_Vector, N_Vector); + realtype (*nvwrmsnormmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvmin)(N_Vector); + realtype (*nvwl2norm)(N_Vector, N_Vector); + realtype (*nvl1norm)(N_Vector); + void (*nvcompare)(realtype, N_Vector, N_Vector); + booleantype (*nvinvtest)(N_Vector, N_Vector); + booleantype (*nvconstrmask)(N_Vector, N_Vector, N_Vector); + realtype (*nvminquotient)(N_Vector, N_Vector); +}; + +/* + * ----------------------------------------------------------------- + * A vector is a structure with an implementation-dependent + * 'content' field, and a pointer to a structure of vector + * operations corresponding to that implementation. + * ----------------------------------------------------------------- + */ + +struct _generic_N_Vector { + void *content; + struct _generic_N_Vector_Ops *ops; +}; + +/* + * ----------------------------------------------------------------- + * Functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VClone + * Creates a new vector of the same type as an existing vector. + * It does not copy the vector, but rather allocates storage for + * the new vector. + * + * N_VCloneEmpty + * Creates a new vector of the same type as an existing vector, + * but does not allocate storage. + * + * N_VDestroy + * Destroys a vector created with N_VClone. + * + * N_VSpace + * Returns space requirements for one N_Vector (type 'realtype' in + * lrw and type 'long int' in liw). + * + * N_VGetArrayPointer + * Returns a pointer to the data component of the given N_Vector. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the solver-specific interfaces to the dense and banded linear + * solvers, as well as the interfaces to the banded preconditioners + * distributed with SUNDIALS. + * + * N_VSetArrayPointer + * Overwrites the data field in the given N_Vector with a user-supplied + * array of type 'realtype'. + * NOTE: This function assumes that the internal data is stored + * as a contiguous 'realtype' array. This routine is only used in + * the interfaces to the dense linear solver. + * + * N_VLinearSum + * Performs the operation z = a*x + b*y + * + * N_VConst + * Performs the operation z[i] = c for i = 0, 1, ..., N-1 + * + * N_VProd + * Performs the operation z[i] = x[i]*y[i] for i = 0, 1, ..., N-1 + * + * N_VDiv + * Performs the operation z[i] = x[i]/y[i] for i = 0, 1, ..., N-1 + * + * N_VScale + * Performs the operation z = c*x + * + * N_VAbs + * Performs the operation z[i] = |x[i]| for i = 0, 1, ..., N-1 + * + * N_VInv + * Performs the operation z[i] = 1/x[i] for i = 0, 1, ..., N-1 + * This routine does not check for division by 0. It should be + * called only with an N_Vector x which is guaranteed to have + * all non-zero components. + * + * N_VAddConst + * Performs the operation z[i] = x[i] + b for i = 0, 1, ..., N-1 + * + * N_VDotProd + * Returns the dot product of two vectors: + * sum (i = 0 to N-1) {x[i]*y[i]} + * + * N_VMaxNorm + * Returns the maximum norm of x: + * max (i = 0 to N-1) ABS(x[i]) + * + * N_VWrmsNorm + * Returns the weighted root mean square norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})/N] + * + * N_VWrmsNormMask + * Returns the weighted root mean square norm of x with weight + * vector w, masked by the elements of id: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i]*msk[i])^2})/N] + * where msk[i] = 1.0 if id[i] > 0 and + * msk[i] = 0.0 if id[i] < 0 + * + * N_VMin + * Returns the smallest element of x: + * min (i = 0 to N-1) x[i] + * + * N_VWL2Norm + * Returns the weighted Euclidean L2 norm of x with weight + * vector w: + * sqrt [(sum (i = 0 to N-1) {(x[i]*w[i])^2})] + * + * N_VL1Norm + * Returns the L1 norm of x: + * sum (i = 0 to N-1) {ABS(x[i])} + * + * N_VCompare + * Performs the operation + * z[i] = 1.0 if ABS(x[i]) >= c i = 0, 1, ..., N-1 + * 0.0 otherwise + * + * N_VInvTest + * Performs the operation z[i] = 1/x[i] with a test for + * x[i] == 0.0 before inverting x[i]. + * This routine returns TRUE if all components of x are non-zero + * (successful inversion) and returns FALSE otherwise. + * + * N_VConstrMask + * Performs the operation : + * m[i] = 1.0 if constraint test fails for x[i] + * m[i] = 0.0 if constraint test passes for x[i] + * where the constraint tests are as follows: + * If c[i] = +2.0, then x[i] must be > 0.0. + * If c[i] = +1.0, then x[i] must be >= 0.0. + * If c[i] = -1.0, then x[i] must be <= 0.0. + * If c[i] = -2.0, then x[i] must be < 0.0. + * This routine returns a boolean FALSE if any element failed + * the constraint test, TRUE if all passed. It also sets a + * mask vector m, with elements equal to 1.0 where the + * corresponding constraint test failed, and equal to 0.0 + * where the constraint test passed. + * This routine is specialized in that it is used only for + * constraint checking. + * + * N_VMinQuotient + * Performs the operation : + * minq = min ( num[i]/denom[i]) over all i such that + * denom[i] != 0. + * This routine returns the minimum of the quotients obtained + * by term-wise dividing num[i] by denom[i]. A zero element + * in denom will be skipped. If no such quotients are found, + * then the large value BIG_REAL is returned. + * + * ----------------------------------------------------------------- + * + * The following table lists the vector functions used by + * different modules in SUNDIALS. The symbols in the table + * have the following meaning: + * S - called by the solver; + * D - called by the dense linear solver module + * B - called by the band linear solver module + * Di - called by the diagonal linear solver module + * I - called by the iterative linear solver module + * BP - called by the band preconditioner module + * BBDP - called by the band-block diagonal preconditioner module + * F - called by the Fortran-to-C interface + * + * ------------------------------------------------ + * MODULES + * NVECTOR ------------------------------------------------ + * FUNCTIONS CVODE/CVODES IDA KINSOL + * ----------------------------------------------------------------- + * N_VClone S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VCloneEmpty F F F + * ----------------------------------------------------------------- + * N_VDestroy S Di I S I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VSpace S S S + * ----------------------------------------------------------------- + * N_VGetArrayPointer D B BP BBDP F D B BBDP BBDP F + * ----------------------------------------------------------------- + * N_VSetArrayPointer D F D F + * ----------------------------------------------------------------- + * N_VLinearSum S D Di I S D I S I + * ----------------------------------------------------------------- + * N_VConst S I S I I + * ----------------------------------------------------------------- + * N_VProd S Di I S I S I + * ----------------------------------------------------------------- + * N_VDiv S Di I S I S I + * ----------------------------------------------------------------- + * N_VScale S D B Di I BP BBDP S D B I BBDP S I BBDP + * ----------------------------------------------------------------- + * N_VAbs S S S + * ----------------------------------------------------------------- + * N_VInv S Di S S + * ----------------------------------------------------------------- + * N_VAddConst S Di S + * ----------------------------------------------------------------- + * N_VDotProd I I I + * ----------------------------------------------------------------- + * N_VMaxNorm S S S + * ----------------------------------------------------------------- + * N_VWrmsNorm S D B I BP BBDP S + * ----------------------------------------------------------------- + * N_VWrmsNormMask S + * ----------------------------------------------------------------- + * N_VMin S S S + * ----------------------------------------------------------------- + * N_VWL2Norm S I + * ----------------------------------------------------------------- + * N_VL1Norm I + * ----------------------------------------------------------------- + * N_VCompare Di S + * ----------------------------------------------------------------- + * N_VInvTest Di + * ----------------------------------------------------------------- + * N_VConstrMask S S + * ----------------------------------------------------------------- + * N_VMinQuotient S S + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector N_VClone(N_Vector w); +SUNDIALS_EXPORT N_Vector N_VCloneEmpty(N_Vector w); +SUNDIALS_EXPORT void N_VDestroy(N_Vector v); +SUNDIALS_EXPORT void N_VSpace(N_Vector v, long int *lrw, long int *liw); +SUNDIALS_EXPORT realtype *N_VGetArrayPointer(N_Vector v); +SUNDIALS_EXPORT void N_VSetArrayPointer(realtype *v_data, N_Vector v); +SUNDIALS_EXPORT void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VConst(realtype c, N_Vector z); +SUNDIALS_EXPORT void N_VProd(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VDiv(N_Vector x, N_Vector y, N_Vector z); +SUNDIALS_EXPORT void N_VScale(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAbs(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VInv(N_Vector x, N_Vector z); +SUNDIALS_EXPORT void N_VAddConst(N_Vector x, realtype b, N_Vector z); +SUNDIALS_EXPORT realtype N_VDotProd(N_Vector x, N_Vector y); +SUNDIALS_EXPORT realtype N_VMaxNorm(N_Vector x); +SUNDIALS_EXPORT realtype N_VWrmsNorm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id); +SUNDIALS_EXPORT realtype N_VMin(N_Vector x); +SUNDIALS_EXPORT realtype N_VWL2Norm(N_Vector x, N_Vector w); +SUNDIALS_EXPORT realtype N_VL1Norm(N_Vector x); +SUNDIALS_EXPORT void N_VCompare(realtype c, N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VInvTest(N_Vector x, N_Vector z); +SUNDIALS_EXPORT booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m); +SUNDIALS_EXPORT realtype N_VMinQuotient(N_Vector num, N_Vector denom); + +/* + * ----------------------------------------------------------------- + * Additional functions exported by NVECTOR module + * ----------------------------------------------------------------- + */ + +/* + * ----------------------------------------------------------------- + * N_VCloneEmptyVectorArray + * Creates (by cloning 'w') an array of 'count' empty N_Vectors + * + * N_VCloneVectorArray + * Creates (by cloning 'w') an array of 'count' N_Vectors + * + * N_VDestroyVectorArray + * Frees memory for an array of 'count' N_Vectors that was + * created by a call to N_VCloneVectorArray + * + * These functions are used by the SPGMR iterative linear solver + * module and by the CVODES and IDAS solvers. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray(int count, N_Vector w); +SUNDIALS_EXPORT void N_VDestroyVectorArray(N_Vector *vs, int count); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_spbcgs.h b/dep/cvode-2.7.0/include/sundials/sundials_spbcgs.h new file mode 100644 index 00000000..d569d1dc --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_spbcgs.h @@ -0,0 +1,199 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled, + * preconditioned Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#ifndef _SPBCG_H +#define _SPBCG_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SpbcgMemRec and struct *SpbcgMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SpbcgMem denotes a pointer + * to a data structure of type struct SpbcgMemRec. The SpbcgMemRec + * structure contains numerous fields that must be accessed by the + * SPBCG linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * r vector (type N_Vector) which holds the scaled, preconditioned + * linear system residual + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * p, q, u and Ap vectors (type N_Vector) used for workspace by + * the SPBCG algorithm + * + * vtemp scratch vector (type N_Vector) used as temporary vector + * storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector r; + N_Vector p; + N_Vector q; + N_Vector u; + N_Vector Ap; + N_Vector vtemp; + +} SpbcgMemRec, *SpbcgMem; + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + * SpbcgMalloc allocates additional memory needed by the SPBCG + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SpbcgSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SpbcgMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + * SpbcgSolve solves the linear system Ax = b by means of a scaled + * preconditioned Bi-CGSTAB (SPBCG) iterative method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SpbcgMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPBCG_SUCCESS or SPBCG_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPBCG_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPBCG_SUCCESS or SPBCG_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SpbcgSolve */ + +#define SPBCG_SUCCESS 0 /* SPBCG algorithm converged */ +#define SPBCG_RES_REDUCED 1 /* SPBCG did NOT converge, but the + residual was reduced */ +#define SPBCG_CONV_FAIL 2 /* SPBCG algorithm failed to converge */ +#define SPBCG_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPBCG_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPBCG_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPBCG_MEM_NULL -1 /* mem argument is NULL */ +#define SPBCG_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPBCG_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPBCG_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + * SpbcgFree frees the memory allocated by a call to SpbcgMalloc. + * It is illegal to use the pointer mem after a call to SpbcgFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpbcgFree(SpbcgMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPBCG_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the vector r in the + * memory block of the SPBCG module. The argument mem is the + * memory pointer returned by SpbcgMalloc, of type SpbcgMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (r contains P_inverse F if nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPBCG_VTEMP(mem) (mem->r) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_spgmr.h b/dep/cvode-2.7.0/include/sundials/sundials_spgmr.h new file mode 100644 index 00000000..880c1c53 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_spgmr.h @@ -0,0 +1,296 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2011/06/23 00:17:51 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of SPGMR Krylov + * iterative linear solver. The SPGMR algorithm is based on the + * Scaled Preconditioned GMRES (Generalized Minimal Residual) + * method. + * + * The SPGMR algorithm solves a linear system A x = b. + * Preconditioning is allowed on the left, right, or both. + * Scaling is allowed on both sides, and restarts are also allowed. + * We denote the preconditioner and scaling matrices as follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as + * operators are required. + * + * In this notation, SPGMR applies the underlying GMRES method to + * the equivalent transformed system + * Abar xbar = bbar , where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) , + * bbar = S1 (P1-inverse) b , and xbar = S2 P2 x . + * + * The scaling matrices must be chosen so that vectors S1 + * P1-inverse b and S2 P2 x have dimensionless components. + * If preconditioning is done on the left only (P2 = I), by a + * matrix P, then S2 must be a scaling for x, while S1 is a + * scaling for P-inverse b, and so may also be taken as a scaling + * for x. Similarly, if preconditioning is done on the right only + * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is + * a scaling for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPGMR iterations is on the L2 norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPGMR solver involves supplying two routines + * and making three calls. The user-supplied routines are + * atimes (A_data, x, y) to compute y = A x, given x, + * and + * psolve (P_data, y, x, lr) + * to solve P1 x = y or P2 x = y for x, given y. + * The three user calls are: + * mem = SpgmrMalloc(lmax, vec_tmpl); + * to initialize memory, + * flag = SpgmrSolve(mem,A_data,x,b,..., + * P_data,s1,s2,atimes,psolve,...); + * to solve the system, and + * SpgmrFree(mem); + * to free the memory created by SpgmrMalloc. + * Complete details for specifying atimes and psolve and for the + * usage calls are given below and in sundials_iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPGMR_H +#define _SPGMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: SpgmrMemRec, SpgmrMem + * ----------------------------------------------------------------- + * SpgmrMem is a pointer to an SpgmrMemRec which contains + * the memory needed by SpgmrSolve. The SpgmrMalloc routine + * returns a pointer of type SpgmrMem which should then be passed + * in subsequent calls to SpgmrSolve. The SpgmrFree routine frees + * the memory allocated by SpgmrMalloc. + * + * l_max is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. + * + * V is the array of Krylov basis vectors v_1, ..., v_(l_max+1), + * stored in V[0], ..., V[l_max], where l_max is the second + * parameter to SpgmrMalloc. Each v_i is a vector of type + * N_Vector. + * + * Hes is the (l_max+1) x l_max Hessenberg matrix. It is stored + * row-wise so that the (i,j)th element is given by Hes[i][j]. + * + * givens is a length 2*l_max array which represents the + * Givens rotation matrices that arise in the algorithm. The + * Givens rotation matrices F_0, F_1, ..., F_j, where F_i is + * + * 1 + * 1 + * c_i -s_i <--- row i + * s_i c_i + * 1 + * 1 + * + * are represented in the givens vector as + * givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1, + * ..., givens[2j]=c_j, givens[2j+1]=s_j. + * + * xcor is a vector (type N_Vector) which holds the scaled, + * preconditioned correction to the initial guess. + * + * yg is a length (l_max+1) array of realtype used to hold "short" + * vectors (e.g. y and g). + * + * vtemp is a vector (type N_Vector) used as temporary vector + * storage during calculations. + * ----------------------------------------------------------------- + */ + +typedef struct _SpgmrMemRec { + + int l_max; + + N_Vector *V; + realtype **Hes; + realtype *givens; + N_Vector xcor; + realtype *yg; + N_Vector vtemp; + +} SpgmrMemRec, *SpgmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + * SpgmrMalloc allocates the memory used by SpgmrSolve. It + * returns a pointer of type SpgmrMem which the user of the + * SPGMR package should pass to SpgmrSolve. The parameter l_max + * is the maximum Krylov dimension that SpgmrSolve will be + * permitted to use. The parameter vec_tmpl is a pointer to an + * N_Vector used as a template to create new vectors by duplication. + * This routine returns NULL if there is a memory request failure. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + * SpgmrSolve solves the linear system Ax = b using the SPGMR + * method. The return values are given by the symbolic constants + * below. The first SpgmrSolve parameter is a pointer to memory + * allocated by a prior call to SpgmrMalloc. + * + * mem is the pointer returned by SpgmrMalloc to the structure + * containing the memory needed by SpgmrSolve. + * + * A_data is a pointer to information about the coefficient + * matrix A. This pointer is passed to the user-supplied function + * atimes. + * + * x is the initial guess x_0 upon entry and the solution + * N_Vector upon exit with return value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED. For all other return values, the output x + * is undefined. + * + * b is the right hand side N_Vector. It is undisturbed by this + * function. + * + * pretype is the type of preconditioning to be used. Its + * legal values are enumerated in sundials_iterative.h. These + * values are PREC_NONE=0, PREC_LEFT=1, PREC_RIGHT=2, and + * PREC_BOTH=3. + * + * gstype is the type of Gram-Schmidt orthogonalization to be + * used. Its legal values are enumerated in sundials_iterative.h. + * These values are MODIFIED_GS=0 and CLASSICAL_GS=1. + * + * delta is the tolerance on the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS, + * this residual satisfies || s1 P1_inv (b - Ax) ||_2 <= delta. + * + * max_restarts is the maximum number of times the algorithm is + * allowed to restart. + * + * P_data is a pointer to preconditioner information. This + * pointer is passed to the user-supplied function psolve. + * + * s1 is an N_Vector of positive scale factors for P1-inv b, where + * P1 is the left preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P1-inv b is required. + * + * s2 is an N_Vector of positive scale factors for P2 x, where + * P2 is the right preconditioner. (Not tested for positivity.) + * Pass NULL if no scaling on P2 x is required. + * + * atimes is the user-supplied function which performs the + * operation of multiplying A by a given vector. Its description + * is given in sundials_iterative.h. + * + * psolve is the user-supplied function which solves a + * preconditioner system Pz = r, where P is P1 or P2. Its full + * description is given in sundials_iterative.h. The psolve function + * will not be called if pretype is NONE; in that case, the user + * should pass NULL for psolve. + * + * res_norm is a pointer to the L2 norm of the scaled, + * preconditioned residual. On return with value SPGMR_SUCCESS or + * SPGMR_RES_REDUCED, (*res_norm) contains the value + * || s1 P1_inv (b - Ax) ||_2 for the computed solution x. + * For all other return values, (*res_norm) is undefined. The + * caller is responsible for allocating the memory (*res_norm) + * to be filled in by SpgmrSolve. + * + * nli is a pointer to the number of linear iterations done in + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nli) to be filled in by SpgmrSolve. + * + * nps is a pointer to the number of calls made to psolve during + * the execution of SpgmrSolve. The caller is responsible for + * allocating the memory (*nps) to be filled in by SpgmrSolve. + * + * Note: Repeated calls can be made to SpgmrSolve with varying + * input arguments. If, however, the problem size N or the + * maximum Krylov dimension l_max changes, then a call to + * SpgmrMalloc must be made to obtain new memory for SpgmrSolve + * to use. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, + int max_restarts, void *P_data, N_Vector s1, + N_Vector s2, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + + +/* Return values for SpgmrSolve */ + +#define SPGMR_SUCCESS 0 /* Converged */ +#define SPGMR_RES_REDUCED 1 /* Did not converge, but reduced + norm of residual */ +#define SPGMR_CONV_FAIL 2 /* Failed to converge */ +#define SPGMR_QRFACT_FAIL 3 /* QRfact found singular matrix */ +#define SPGMR_PSOLVE_FAIL_REC 4 /* psolve failed recoverably */ +#define SPGMR_ATIMES_FAIL_REC 5 /* atimes failed recoverably */ +#define SPGMR_PSET_FAIL_REC 6 /* pset faild recoverably */ + +#define SPGMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPGMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPGMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPGMR_GS_FAIL -4 /* Gram-Schmidt routine faiuled */ +#define SPGMR_QRSOL_FAIL -5 /* QRsol found singular R */ +#define SPGMR_PSET_FAIL_UNREC -6 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + * SpgmrMalloc frees the memory allocated by SpgmrMalloc. It is + * illegal to use the pointer mem after a call to SpgmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SpgmrFree(SpgmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro: SPGMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp in the + * memory block of the SPGMR module. The argument mem is the + * memory pointer returned by SpgmrMalloc, of type SpgmrMem, + * and the macro value is of type N_Vector. + * On a return from SpgmrSolve with *nli = 0, this vector + * contains the scaled preconditioned initial residual, + * s1 * P1_inverse * (b - A x_0). + * ----------------------------------------------------------------- + */ + +#define SPGMR_VTEMP(mem) (mem->vtemp) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_sptfqmr.h b/dep/cvode-2.7.0/include/sundials/sundials_sptfqmr.h new file mode 100644 index 00000000..65021014 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_sptfqmr.h @@ -0,0 +1,254 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2011/06/23 00:17:51 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the header file for the implementation of the scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * linear solver. + * + * The SPTFQMR algorithm solves a linear system of the form Ax = b. + * Preconditioning is allowed on the left (PREC_LEFT), right + * (PREC_RIGHT), or both (PREC_BOTH). Scaling is allowed on both + * sides. We denote the preconditioner and scaling matrices as + * follows: + * P1 = left preconditioner + * P2 = right preconditioner + * S1 = diagonal matrix of scale factors for P1-inverse b + * S2 = diagonal matrix of scale factors for P2 x + * The matrices A, P1, and P2 are not required explicitly; only + * routines that provide A, P1-inverse, and P2-inverse as operators + * are required. + * + * In this notation, SPTFQMR applies the underlying TFQMR method to + * the equivalent transformed system: + * Abar xbar = bbar, where + * Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse), + * bbar = S1 (P1-inverse) b, and + * xbar = S2 P2 x. + * + * The scaling matrices must be chosen so that vectors + * S1 P1-inverse b and S2 P2 x have dimensionless components. If + * preconditioning is done on the left only (P2 = I), by a matrix P, + * then S2 must be a scaling for x, while S1 is a scaling for + * P-inverse b, and so may also be taken as a scaling for x. + * Similarly, if preconditioning is done on the right only (P1 = I, + * P2 = P), then S1 must be a scaling for b, while S2 is a scaling + * for P x, and may also be taken as a scaling for b. + * + * The stopping test for the SPTFQMR iterations is on the L2-norm of + * the scaled preconditioned residual: + * || bbar - Abar xbar ||_2 < delta + * with an input test constant delta. + * + * The usage of this SPTFQMR solver involves supplying two routines + * and making three calls. The user-supplied routines are: + * atimes(A_data, x, y) to compute y = A x, given x, + * and + * psolve(P_data, y, x, lr) to solve P1 x = y or P2 x = y for x, + * given y. + * The three user calls are: + * mem = SptfqmrMalloc(lmax, vec_tmpl); + * to initialize memory + * flag = SptfqmrSolve(mem, A_data, x, b, pretype, delta, P_data, + * sx, sb, atimes, psolve, res_norm, nli, nps); + * to solve the system, and + * SptfqmrFree(mem); + * to free the memory allocated by SptfqmrMalloc(). + * Complete details for specifying atimes() and psolve() and for the + * usage calls are given in the paragraphs below and in the header + * file sundials_iterative.h. + * ----------------------------------------------------------------- + */ + +#ifndef _SPTFQMR_H +#define _SPTFQMR_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include + +/* + * ----------------------------------------------------------------- + * Types: struct SptfqmrMemRec and struct *SptfqmrMem + * ----------------------------------------------------------------- + * A variable declaration of type struct *SptfqmrMem denotes a pointer + * to a data structure of type struct SptfqmrMemRec. The SptfqmrMemRec + * structure contains numerous fields that must be accessed by the + * SPTFQMR linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * r_star vector (type N_Vector) which holds the initial scaled, + * preconditioned linear system residual + * + * q/d/v/p/u/r vectors (type N_Vector) used for workspace by + * the SPTFQMR algorithm + * + * vtemp1/vtemp2/vtemp3 scratch vectors (type N_Vector) used as + * temporary storage + * ----------------------------------------------------------------- + */ + +typedef struct { + + int l_max; + + N_Vector r_star; + N_Vector q; + N_Vector d; + N_Vector v; + N_Vector p; + N_Vector *r; + N_Vector u; + N_Vector vtemp1; + N_Vector vtemp2; + N_Vector vtemp3; + +} SptfqmrMemRec, *SptfqmrMem; + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + * SptfqmrMalloc allocates additional memory needed by the SPTFQMR + * linear solver module. + * + * l_max maximum Krylov subspace dimension that SptfqmrSolve will + * be permitted to use + * + * vec_tmpl implementation-specific template vector (type N_Vector) + * (created using either N_VNew_Serial or N_VNew_Parallel) + * + * If successful, SptfqmrMalloc returns a non-NULL memory pointer. If + * an error occurs, then a NULL pointer is returned. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl); + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + * SptfqmrSolve solves the linear system Ax = b by means of a scaled + * preconditioned Transpose-Free Quasi-Minimal Residual (SPTFQMR) + * method. + * + * mem pointer to an internal memory block allocated during a + * prior call to SptfqmrMalloc + * + * A_data pointer to a data structure containing information + * about the coefficient matrix A (passed to user-supplied + * function referenced by atimes (function pointer)) + * + * x vector (type N_Vector) containing initial guess x_0 upon + * entry, but which upon return contains an approximate solution + * of the linear system Ax = b (solution only valid if return + * value is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED) + * + * b vector (type N_Vector) set to the right-hand side vector b + * of the linear system (undisturbed by function) + * + * pretype variable (type int) indicating the type of + * preconditioning to be used (see sundials_iterative.h) + * + * delta tolerance on the L2 norm of the scaled, preconditioned + * residual (if return value == SPTFQMR_SUCCESS, then + * ||sb*P1_inv*(b-Ax)||_L2 <= delta) + * + * P_data pointer to a data structure containing preconditioner + * information (passed to user-supplied function referenced + * by psolve (function pointer)) + * + * sx vector (type N_Vector) containing positive scaling factors + * for x (pass sx == NULL if scaling NOT required) + * + * sb vector (type N_Vector) containing positive scaling factors + * for b (pass sb == NULL if scaling NOT required) + * + * atimes user-supplied routine responsible for computing the + * matrix-vector product Ax (see sundials_iterative.h) + * + * psolve user-supplied routine responsible for solving the + * preconditioned linear system Pz = r (ignored if + * pretype == PREC_NONE) (see sundials_iterative.h) + * + * res_norm pointer (type realtype*) to the L2 norm of the + * scaled, preconditioned residual (if return value + * is either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED, then + * *res_norm = ||sb*P1_inv*(b-Ax)||_L2, where x is + * the computed approximate solution, sb is the diagonal + * scaling matrix for the right-hand side b, and P1_inv + * is the inverse of the left-preconditioner matrix) + * + * nli pointer (type int*) to the total number of linear + * iterations performed + * + * nps pointer (type int*) to the total number of calls made + * to the psolve routine + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps); + +/* Return values for SptfqmrSolve */ + +#define SPTFQMR_SUCCESS 0 /* SPTFQMR algorithm converged */ +#define SPTFQMR_RES_REDUCED 1 /* SPTFQMR did NOT converge, but the + residual was reduced */ +#define SPTFQMR_CONV_FAIL 2 /* SPTFQMR algorithm failed to converge */ +#define SPTFQMR_PSOLVE_FAIL_REC 3 /* psolve failed recoverably */ +#define SPTFQMR_ATIMES_FAIL_REC 4 /* atimes failed recoverably */ +#define SPTFQMR_PSET_FAIL_REC 5 /* pset faild recoverably */ + +#define SPTFQMR_MEM_NULL -1 /* mem argument is NULL */ +#define SPTFQMR_ATIMES_FAIL_UNREC -2 /* atimes returned failure flag */ +#define SPTFQMR_PSOLVE_FAIL_UNREC -3 /* psolve failed unrecoverably */ +#define SPTFQMR_PSET_FAIL_UNREC -4 /* pset failed unrecoverably */ + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + * SptfqmrFree frees the memory allocated by a call to SptfqmrMalloc. + * It is illegal to use the pointer mem after a call to SptfqmrFree. + * ----------------------------------------------------------------- + */ + +SUNDIALS_EXPORT void SptfqmrFree(SptfqmrMem mem); + +/* + * ----------------------------------------------------------------- + * Macro : SPTFQMR_VTEMP + * ----------------------------------------------------------------- + * This macro provides access to the work vector vtemp1 in the + * memory block of the SPTFQMR module. The argument mem is the + * memory pointer returned by SptfqmrMalloc, of type SptfqmrMem, + * and the macro value is of type N_Vector. + * + * Note: Only used by IDA (vtemp1 contains P_inverse F if + * nli_inc == 0). + * ----------------------------------------------------------------- + */ + +#define SPTFQMR_VTEMP(mem) (mem->vtemp1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/include/sundials/sundials_types.h b/dep/cvode-2.7.0/include/sundials/sundials_types.h new file mode 100644 index 00000000..953f6e09 --- /dev/null +++ b/dep/cvode-2.7.0/include/sundials/sundials_types.h @@ -0,0 +1,122 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2006/11/29 00:05:07 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + *------------------------------------------------------------------ + * This header file exports two types: realtype and booleantype, + * as well as the constants TRUE and FALSE. + * + * Users should include the header file sundials_types.h in every + * program file and use the exported name realtype instead of + * float, double or long double. + * + * The constants SUNDIALS_SINGLE_PRECISION, SUNDIALS_DOUBLE_PRECISION + * and SUNDIALS_LONG_DOUBLE_PRECISION indicate the underlying data + * type of realtype. It is set at the configuration stage. + * + * The legal types for realtype are float, double and long double. + * + * The macro RCONST gives the user a convenient way to define + * real-valued constants. To use the constant 1.0, for example, + * the user should write the following: + * + * #define ONE RCONST(1.0) + * + * If realtype is defined as a double, then RCONST(1.0) expands + * to 1.0. If realtype is defined as a float, then RCONST(1.0) + * expands to 1.0F. If realtype is defined as a long double, + * then RCONST(1.0) expands to 1.0L. There is never a need to + * explicitly cast 1.0 to (realtype). + *------------------------------------------------------------------ + */ + +#ifndef _SUNDIALSTYPES_H +#define _SUNDIALSTYPES_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#ifndef _SUNDIALS_CONFIG_H +#define _SUNDIALS_CONFIG_H +#include +#endif + +#include + +/* + *------------------------------------------------------------------ + * Type realtype + * Macro RCONST + * Constants BIG_REAL, SMALL_REAL, and UNIT_ROUNDOFF + *------------------------------------------------------------------ + */ + +#if defined(SUNDIALS_SINGLE_PRECISION) + +typedef float realtype; +# define RCONST(x) x##F +# define BIG_REAL FLT_MAX +# define SMALL_REAL FLT_MIN +# define UNIT_ROUNDOFF FLT_EPSILON + +#elif defined(SUNDIALS_DOUBLE_PRECISION) + +typedef double realtype; +# define RCONST(x) x +# define BIG_REAL DBL_MAX +# define SMALL_REAL DBL_MIN +# define UNIT_ROUNDOFF DBL_EPSILON + +#elif defined(SUNDIALS_EXTENDED_PRECISION) + +typedef long double realtype; +# define RCONST(x) x##L +# define BIG_REAL LDBL_MAX +# define SMALL_REAL LDBL_MIN +# define UNIT_ROUNDOFF LDBL_EPSILON + +#endif + +/* + *------------------------------------------------------------------ + * Type : booleantype + *------------------------------------------------------------------ + * Constants : FALSE and TRUE + *------------------------------------------------------------------ + * ANSI C does not have a built-in boolean data type. Below is the + * definition for a new type called booleantype. The advantage of + * using the name booleantype (instead of int) is an increase in + * code readability. It also allows the programmer to make a + * distinction between int and boolean data. Variables of type + * booleantype are intended to have only the two values FALSE and + * TRUE which are defined below to be equal to 0 and 1, + * respectively. + *------------------------------------------------------------------ + */ + +#ifndef booleantype +#define booleantype int +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/nvec_ser/CMakeLists.txt b/dep/cvode-2.7.0/nvec_ser/CMakeLists.txt new file mode 100644 index 00000000..87cf3478 --- /dev/null +++ b/dep/cvode-2.7.0/nvec_ser/CMakeLists.txt @@ -0,0 +1,61 @@ +# --------------------------------------------------------------- +# $Revision: 1.3 $ +# $Date: 2009/02/17 02:58:48 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the serial NVECTOR library + +INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_SERIAL\n\")") + +# Add variable nvecserial_SOURCES with the sources for the NVECSERIAL lib +SET(nvecserial_SOURCES nvector_serial.c) + +# Add variable shared_SOURCES with the common SUNDIALS sources which will +# also be included in the NVECSERIAL library +SET(shared_SOURCES sundials_math.c) +ADD_PREFIX(${sundials_SOURCE_DIR}/sundials/ shared_SOURCES) + +# Add variable nvecserial_HEADERS with the exported NVECSERIAL header files +SET(nvecserial_HEADERS nvector_serial.h) +ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecserial_HEADERS) + +# Add source directory to include directories +INCLUDE_DIRECTORIES(.) + +# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY +ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY) + +# Rules for building and installing the static library: +ADD_LIBRARY(depnvec STATIC ${nvecserial_SOURCES} ${shared_SOURCES}) +INSTALL(TARGETS depnvec DESTINATION lib) + +# Install the NVECSERIAL header files +INSTALL(FILES ${nvecserial_HEADERS} DESTINATION include/dep/nvector) + +# If FCMIX is enabled, build and install the FNVECSERIAL library +IF(FCMIX_ENABLE AND F77_FOUND) + SET(fnvecserial_SOURCES fnvector_serial.c) + IF(BUILD_STATIC_LIBS) + ADD_LIBRARY(sundials_fnvecserial_static STATIC ${fnvecserial_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecserial_static + PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1) + INSTALL(TARGETS sundials_fnvecserial_static DESTINATION lib) + ENDIF(BUILD_STATIC_LIBS) + IF(BUILD_SHARED_LIBS) + ADD_LIBRARY(sundials_fnvecserial_shared ${fnvecserial_SOURCES}) + SET_TARGET_PROPERTIES(sundials_fnvecserial_shared + PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1) + SET_TARGET_PROPERTIES(sundials_fnvecserial_shared + PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}) + INSTALL(TARGETS sundials_fnvecserial_shared DESTINATION lib) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(FCMIX_ENABLE AND F77_FOUND) + +# +MESSAGE(STATUS "Added NVECTOR_SERIAL module") diff --git a/dep/cvode-2.7.0/nvec_ser/README b/dep/cvode-2.7.0/nvec_ser/README new file mode 100644 index 00000000..ab838a62 --- /dev/null +++ b/dep/cvode-2.7.0/nvec_ser/README @@ -0,0 +1,139 @@ + NVECTOR_SERIAL + Release 2.5.0, March 2012 + + +Serial implementation of the NVECTOR module for SUNDIALS. + +NVECTOR_SERIAL defines the content field of N_Vector to be a structure +containing the length of the vector, a pointer to the beginning of a +contiguous data array, and a boolean flag indicating ownership of the +data array. + +NVECTOR_SERIAL defines five macros to provide access to the content of +a serial N_Vector, several constructors for variables of type N_Vector, +a constructor for an array of variables of type N_Vector, and destructors +for N_Vector and N_Vector array. + +NVECTOR_SERIAL provides implementations for all vector operations defined +by the generic NVECTOR module in the table of operations. + + +A. Documentation +---------------- + +The serial NVECTOR implementation is fully described in the user documentation +for any of the SUNDIALS solvers [1-5]. A PDF file for the user guide for a +particular solver is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0," + LLNL technical report UCRL-MA-208108, December 2011. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.7.0," + LLNL technical report UCRL-MA-208111, December 2011. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.7.0," + LLNL technical report UCRL-MA-208112, December 2011. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.1.0," + LLNL technical report UCRL-SM-234051, December 2011. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.7.0," LLNL technical report UCRL-MA-208116, + December 2011. + + +D. Releases +----------- + +v. 2.5.0 - Mar. 2012 +v. 2.4.0 - May 2009 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) + + +E. Revision History +------------------- + +v. 2.4.0 (May 2009) ---> v. 2.5.0 (Mar. 2012) +--------------------------------------------- + +- Bug fix: + - consistently updated to using SUNDIALS_F77_FUNC in fcmix header files. + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (May 2009) +--------------------------------------------- + +- none + + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes related to the build system + - reorganized source tree. Header files in ${srcdir}/include/nvector; + sources in ${srcdir}/src/nvec_ser + - exported header files in ${includedir}/sundials + + +v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006) +--------------------------------------------- + +- none + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May 2005) +--------------------------------------------- + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Revised to correspond to new generic NVECTOR module + (see sundials/shared/README). +- Extended the list of user-callable functions provided by NVECTOR_SERIAL + outside the table of vector operations. +- Revised the F/C interface to use underscore flags for name mapping + and to use precision flag from configure. +- Revised F/C routine NVECTOR names for uniformity. diff --git a/dep/cvode-2.7.0/nvec_ser/fnvector_serial.c b/dep/cvode-2.7.0/nvec_ser/fnvector_serial.c new file mode 100644 index 00000000..8f83c80c --- /dev/null +++ b/dep/cvode-2.7.0/nvec_ser/fnvector_serial.c @@ -0,0 +1,147 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_serial.h) contains the + * implementation needed for the Fortran initialization of serial + * vector operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include "fnvector_serial.h" + +/* Define global vector variables */ + +N_Vector F2C_CVODE_vec; +N_Vector F2C_CVODE_vecQ; +N_Vector *F2C_CVODE_vecS; +N_Vector F2C_CVODE_vecB; +N_Vector F2C_CVODE_vecQB; + +N_Vector F2C_IDA_vec; +N_Vector F2C_IDA_vecQ; +N_Vector *F2C_IDA_vecS; +N_Vector F2C_IDA_vecB; +N_Vector F2C_IDA_vecQB; + +N_Vector F2C_KINSOL_vec; + +/* Fortran callable interfaces */ + +void FNV_INITS(int *code, long int *N, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vec = NULL; + F2C_CVODE_vec = N_VNewEmpty_Serial(*N); + if (F2C_CVODE_vec == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vec = NULL; + F2C_IDA_vec = N_VNewEmpty_Serial(*N); + if (F2C_IDA_vec == NULL) *ier = -1; + break; + case FCMIX_KINSOL: + F2C_KINSOL_vec = NULL; + F2C_KINSOL_vec = N_VNewEmpty_Serial(*N); + if (F2C_KINSOL_vec == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_Q(int *code, long int *Nq, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQ = NULL; + F2C_CVODE_vecQ = N_VNewEmpty_Serial(*Nq); + if (F2C_CVODE_vecQ == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQ = NULL; + F2C_IDA_vecQ = N_VNewEmpty_Serial(*Nq); + if (F2C_IDA_vecQ == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_B(int *code, long int *NB, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecB = NULL; + F2C_CVODE_vecB = N_VNewEmpty_Serial(*NB); + if (F2C_CVODE_vecB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecB = NULL; + F2C_IDA_vecB = N_VNewEmpty_Serial(*NB); + if (F2C_IDA_vecB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_QB(int *code, long int *NqB, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecQB = NULL; + F2C_CVODE_vecQB = N_VNewEmpty_Serial(*NqB); + if (F2C_CVODE_vecQB == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecQB = NULL; + F2C_IDA_vecQB = N_VNewEmpty_Serial(*NqB); + if (F2C_IDA_vecQB == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + +void FNV_INITS_S(int *code, int *Ns, int *ier) +{ + *ier = 0; + + switch(*code) { + case FCMIX_CVODE: + F2C_CVODE_vecS = NULL; + F2C_CVODE_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_CVODE_vec); + if (F2C_CVODE_vecS == NULL) *ier = -1; + break; + case FCMIX_IDA: + F2C_IDA_vecS = NULL; + F2C_IDA_vecS = (N_Vector *) N_VCloneVectorArrayEmpty_Serial(*Ns, F2C_IDA_vec); + if (F2C_IDA_vecS == NULL) *ier = -1; + break; + default: + *ier = -1; + } +} + + diff --git a/dep/cvode-2.7.0/nvec_ser/fnvector_serial.h b/dep/cvode-2.7.0/nvec_ser/fnvector_serial.h new file mode 100644 index 00000000..4f49b218 --- /dev/null +++ b/dep/cvode-2.7.0/nvec_ser/fnvector_serial.h @@ -0,0 +1,88 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.4 $ + * $Date: 2010/12/15 19:40:08 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This file (companion of nvector_serial.h) contains the + * definitions needed for the initialization of serial + * vector operations in Fortran. + * ----------------------------------------------------------------- + */ + +#ifndef _FNVECTOR_SERIAL_H +#define _FNVECTOR_SERIAL_H + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +#include +#include + +#if defined(SUNDIALS_F77_FUNC) +#define FNV_INITS SUNDIALS_F77_FUNC(fnvinits, FNVINITS) +#else +#define FNV_INITS fnvinits_ +#endif + +#if defined(SUNDIALS_F77_FUNC_) + +#define FNV_INITS_Q SUNDIALS_F77_FUNC_(fnvinits_q, FNVINITS_Q) +#define FNV_INITS_S SUNDIALS_F77_FUNC_(fnvinits_s, FNVINITS_S) +#define FNV_INITS_B SUNDIALS_F77_FUNC_(fnvinits_b, FNVINITS_B) +#define FNV_INITS_QB SUNDIALS_F77_FUNC_(fnvinits_qb, FNVINITS_QB) + +#else + +#define FNV_INITS_Q fnvinits_q_ +#define FNV_INITS_S fnvinits_s_ +#define FNV_INITS_B fnvinits_b_ +#define FNV_INITS_QB fnvinits_qb_ + +#endif + +/* Declarations of global variables */ + +extern N_Vector F2C_CVODE_vec; +extern N_Vector F2C_CVODE_vecQ; +extern N_Vector *F2C_CVODE_vecS; +extern N_Vector F2C_CVODE_vecB; +extern N_Vector F2C_CVODE_vecQB; + +extern N_Vector F2C_IDA_vec; +extern N_Vector F2C_IDA_vecQ; +extern N_Vector *F2C_IDA_vecS; +extern N_Vector F2C_IDA_vecB; +extern N_Vector F2C_IDA_vecQB; + +extern N_Vector F2C_KINSOL_vec; + +/* + * Prototypes of exported functions + * + * FNV_INITS - initializes serial vector operations for main problem + * FNV_INITS_Q - initializes serial vector operations for quadratures + * FNV_INITS_S - initializes serial vector operations for sensitivities + * FNV_INITS_B - initializes serial vector operations for adjoint problem + * FNV_INITS_QB - initializes serial vector operations for adjoint quadratures + * + */ + +void FNV_INITS(int *code, long int *neq, int *ier); +void FNV_INITS_Q(int *code, long int *Nq, int *ier); +void FNV_INITS_S(int *code, int *Ns, int *ier); +void FNV_INITS_B(int *code, long int *NB, int *ier); +void FNV_INITS_QB(int *code, long int *NqB, int *ier); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/cvode-2.7.0/nvec_ser/nvector_serial.c b/dep/cvode-2.7.0/nvec_ser/nvector_serial.c new file mode 100644 index 00000000..c890253e --- /dev/null +++ b/dep/cvode-2.7.0/nvec_ser/nvector_serial.c @@ -0,0 +1,1034 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:37 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban, + * and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a serial implementation + * of the NVECTOR package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define HALF RCONST(0.5) +#define ONE RCONST(1.0) +#define ONEPT5 RCONST(1.5) + +/* Private function prototypes */ +/* z=x */ +static void VCopy_Serial(N_Vector x, N_Vector z); +/* z=x+y */ +static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z); +/* z=x-y */ +static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z); +/* z=-x */ +static void VNeg_Serial(N_Vector x, N_Vector z); +/* z=c(x+y) */ +static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=c(x-y) */ +static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z); +/* z=ax+y */ +static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* z=ax-y */ +static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z); +/* y <- ax+y */ +static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y); +/* x <- ax */ +static void VScaleBy_Serial(realtype a, N_Vector x); + +/* + * ----------------------------------------------------------------- + * exported functions + * ----------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------------------- + * Function to create a new empty serial vector + */ + +N_Vector N_VNewEmpty_Serial(long int length) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Serial content; + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = N_VClone_Serial; + ops->nvcloneempty = N_VCloneEmpty_Serial; + ops->nvdestroy = N_VDestroy_Serial; + ops->nvspace = N_VSpace_Serial; + ops->nvgetarraypointer = N_VGetArrayPointer_Serial; + ops->nvsetarraypointer = N_VSetArrayPointer_Serial; + ops->nvlinearsum = N_VLinearSum_Serial; + ops->nvconst = N_VConst_Serial; + ops->nvprod = N_VProd_Serial; + ops->nvdiv = N_VDiv_Serial; + ops->nvscale = N_VScale_Serial; + ops->nvabs = N_VAbs_Serial; + ops->nvinv = N_VInv_Serial; + ops->nvaddconst = N_VAddConst_Serial; + ops->nvdotprod = N_VDotProd_Serial; + ops->nvmaxnorm = N_VMaxNorm_Serial; + ops->nvwrmsnormmask = N_VWrmsNormMask_Serial; + ops->nvwrmsnorm = N_VWrmsNorm_Serial; + ops->nvmin = N_VMin_Serial; + ops->nvwl2norm = N_VWL2Norm_Serial; + ops->nvl1norm = N_VL1Norm_Serial; + ops->nvcompare = N_VCompare_Serial; + ops->nvinvtest = N_VInvTest_Serial; + ops->nvconstrmask = N_VConstrMask_Serial; + ops->nvminquotient = N_VMinQuotient_Serial; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + content->length = length; + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create a new serial vector + */ + +N_Vector N_VNew_Serial(long int length) +{ + N_Vector v; + realtype *data; + + v = NULL; + v = N_VNewEmpty_Serial(length); + if (v == NULL) return(NULL); + + /* Create data */ + if (length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Serial(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_S(v) = TRUE; + NV_DATA_S(v) = data; + + } + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create a serial N_Vector with user data component + */ + +N_Vector N_VMake_Serial(long int length, realtype *v_data) +{ + N_Vector v; + + v = NULL; + v = N_VNewEmpty_Serial(length); + if (v == NULL) return(NULL); + + if (length > 0) { + /* Attach data */ + NV_OWN_DATA_S(v) = FALSE; + NV_DATA_S(v) = v_data; + } + + return(v); +} + +/* ---------------------------------------------------------------------------- + * Function to create an array of new serial vectors. + */ + +N_Vector *N_VCloneVectorArray_Serial(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VClone_Serial(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Serial(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------------------- + * Function to create an array of new serial vectors with NULL data array. + */ + +N_Vector *N_VCloneVectorArrayEmpty_Serial(int count, N_Vector w) +{ + N_Vector *vs; + int j; + + if (count <= 0) return(NULL); + + vs = NULL; + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = NULL; + vs[j] = N_VCloneEmpty_Serial(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray_Serial(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +/* ---------------------------------------------------------------------------- + * Function to free an array created with N_VCloneVectorArray_Serial + */ + +void N_VDestroyVectorArray_Serial(N_Vector *vs, int count) +{ + int j; + + for (j = 0; j < count; j++) N_VDestroy_Serial(vs[j]); + + free(vs); vs = NULL; + + return; +} + +/* ---------------------------------------------------------------------------- + * Function to print the a serial vector + */ + +void N_VPrint_Serial(N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%11.8Lg\n", xd[i]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%11.8lg\n", xd[i]); +#else + printf("%11.8g\n", xd[i]); +#endif + } + printf("\n"); + + return; +} + +/* + * ----------------------------------------------------------------- + * implementation of vector operations + * ----------------------------------------------------------------- + */ + +N_Vector N_VCloneEmpty_Serial(N_Vector w) +{ + N_Vector v; + N_Vector_Ops ops; + N_VectorContent_Serial content; + + if (w == NULL) return(NULL); + + /* Create vector */ + v = NULL; + v = (N_Vector) malloc(sizeof *v); + if (v == NULL) return(NULL); + + /* Create vector operation structure */ + ops = NULL; + ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops)); + if (ops == NULL) { free(v); return(NULL); } + + ops->nvclone = w->ops->nvclone; + ops->nvcloneempty = w->ops->nvcloneempty; + ops->nvdestroy = w->ops->nvdestroy; + ops->nvspace = w->ops->nvspace; + ops->nvgetarraypointer = w->ops->nvgetarraypointer; + ops->nvsetarraypointer = w->ops->nvsetarraypointer; + ops->nvlinearsum = w->ops->nvlinearsum; + ops->nvconst = w->ops->nvconst; + ops->nvprod = w->ops->nvprod; + ops->nvdiv = w->ops->nvdiv; + ops->nvscale = w->ops->nvscale; + ops->nvabs = w->ops->nvabs; + ops->nvinv = w->ops->nvinv; + ops->nvaddconst = w->ops->nvaddconst; + ops->nvdotprod = w->ops->nvdotprod; + ops->nvmaxnorm = w->ops->nvmaxnorm; + ops->nvwrmsnormmask = w->ops->nvwrmsnormmask; + ops->nvwrmsnorm = w->ops->nvwrmsnorm; + ops->nvmin = w->ops->nvmin; + ops->nvwl2norm = w->ops->nvwl2norm; + ops->nvl1norm = w->ops->nvl1norm; + ops->nvcompare = w->ops->nvcompare; + ops->nvinvtest = w->ops->nvinvtest; + ops->nvconstrmask = w->ops->nvconstrmask; + ops->nvminquotient = w->ops->nvminquotient; + + /* Create content */ + content = NULL; + content = (N_VectorContent_Serial) malloc(sizeof(struct _N_VectorContent_Serial)); + if (content == NULL) { free(ops); free(v); return(NULL); } + + content->length = NV_LENGTH_S(w); + content->own_data = FALSE; + content->data = NULL; + + /* Attach content and ops */ + v->content = content; + v->ops = ops; + + return(v); +} + +N_Vector N_VClone_Serial(N_Vector w) +{ + N_Vector v; + realtype *data; + long int length; + + v = NULL; + v = N_VCloneEmpty_Serial(w); + if (v == NULL) return(NULL); + + length = NV_LENGTH_S(w); + + /* Create data */ + if (length > 0) { + + /* Allocate memory */ + data = NULL; + data = (realtype *) malloc(length * sizeof(realtype)); + if(data == NULL) { N_VDestroy_Serial(v); return(NULL); } + + /* Attach data */ + NV_OWN_DATA_S(v) = TRUE; + NV_DATA_S(v) = data; + + } + + return(v); +} + +void N_VDestroy_Serial(N_Vector v) +{ + if (NV_OWN_DATA_S(v) == TRUE) { + free(NV_DATA_S(v)); + NV_DATA_S(v) = NULL; + } + free(v->content); v->content = NULL; + free(v->ops); v->ops = NULL; + free(v); v = NULL; + + return; +} + +void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw) +{ + *lrw = NV_LENGTH_S(v); + *liw = 1; + + return; +} + +realtype *N_VGetArrayPointer_Serial(N_Vector v) +{ + return((realtype *) NV_DATA_S(v)); +} + +void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v) +{ + if (NV_LENGTH_S(v) > 0) NV_DATA_S(v) = v_data; + + return; +} + +void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + long int i, N; + realtype c, *xd, *yd, *zd; + N_Vector v1, v2; + booleantype test; + + xd = yd = zd = NULL; + + if ((b == ONE) && (z == y)) { /* BLAS usage: axpy y <- ax+y */ + Vaxpy_Serial(a,x,y); + return; + } + + if ((a == ONE) && (z == x)) { /* BLAS usage: axpy x <- by+x */ + Vaxpy_Serial(b,y,x); + return; + } + + /* Case: a == b == 1.0 */ + + if ((a == ONE) && (b == ONE)) { + VSum_Serial(x, y, z); + return; + } + + /* Cases: (1) a == 1.0, b = -1.0, (2) a == -1.0, b == 1.0 */ + + if ((test = ((a == ONE) && (b == -ONE))) || ((a == -ONE) && (b == ONE))) { + v1 = test ? y : x; + v2 = test ? x : y; + VDiff_Serial(v2, v1, z); + return; + } + + /* Cases: (1) a == 1.0, b == other or 0.0, (2) a == other or 0.0, b == 1.0 */ + /* if a or b is 0.0, then user should have called N_VScale */ + + if ((test = (a == ONE)) || (b == ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin1_Serial(c, v1, v2, z); + return; + } + + /* Cases: (1) a == -1.0, b != 1.0, (2) a != 1.0, b == -1.0 */ + + if ((test = (a == -ONE)) || (b == -ONE)) { + c = test ? b : a; + v1 = test ? y : x; + v2 = test ? x : y; + VLin2_Serial(c, v1, v2, z); + return; + } + + /* Case: a == b */ + /* catches case both a and b are 0.0 - user should have called N_VConst */ + + if (a == b) { + VScaleSum_Serial(a, x, y, z); + return; + } + + /* Case: a == -b */ + + if (a == -b) { + VScaleDiff_Serial(a, x, y, z); + return; + } + + /* Do all cases not handled above: + (1) a == other, b == 0.0 - user should have called N_VScale + (2) a == 0.0, b == other - user should have called N_VScale + (3) a,b == other, a !=b, a != -b */ + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+(b*yd[i]); + + return; +} + +void N_VConst_Serial(realtype c, N_Vector z) +{ + long int i, N; + realtype *zd; + + zd = NULL; + + N = NV_LENGTH_S(z); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) zd[i] = c; + + return; +} + +void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]*yd[i]; + + return; +} + +void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]/yd[i]; + + return; +} + +void N_VScale_Serial(realtype c, N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + if (z == x) { /* BLAS usage: scale x <- cx */ + VScaleBy_Serial(c, x); + return; + } + + if (c == ONE) { + VCopy_Serial(x, z); + } else if (c == -ONE) { + VNeg_Serial(x, z); + } else { + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + for (i = 0; i < N; i++) + zd[i] = c*xd[i]; + } + + return; +} + +void N_VAbs_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = ABS(xd[i]); + + return; +} + +void N_VInv_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = ONE/xd[i]; + + return; +} + +void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+b; + + return; +} + +realtype N_VDotProd_Serial(N_Vector x, N_Vector y) +{ + long int i, N; + realtype sum, *xd, *yd; + + sum = ZERO; + xd = yd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + + for (i = 0; i < N; i++) + sum += xd[i]*yd[i]; + + return(sum); +} + +realtype N_VMaxNorm_Serial(N_Vector x) +{ + long int i, N; + realtype max, *xd; + + max = ZERO; + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) { + if (ABS(xd[i]) > max) max = ABS(xd[i]); + } + + return(max); +} + +realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + return(RSqrt(sum/N)); +} + +realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id) +{ + long int i, N; + realtype sum, prodi, *xd, *wd, *idd; + + sum = ZERO; + xd = wd = idd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + idd = NV_DATA_S(id); + + for (i = 0; i < N; i++) { + if (idd[i] > ZERO) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + } + + return(RSqrt(sum / N)); +} + +realtype N_VMin_Serial(N_Vector x) +{ + long int i, N; + realtype min, *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + min = xd[0]; + + for (i = 1; i < N; i++) { + if (xd[i] < min) min = xd[i]; + } + + return(min); +} + +realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w) +{ + long int i, N; + realtype sum, prodi, *xd, *wd; + + sum = ZERO; + xd = wd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + wd = NV_DATA_S(w); + + for (i = 0; i < N; i++) { + prodi = xd[i]*wd[i]; + sum += SQR(prodi); + } + + return(RSqrt(sum)); +} + +realtype N_VL1Norm_Serial(N_Vector x) +{ + long int i, N; + realtype sum, *xd; + + sum = ZERO; + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i= c) ? ONE : ZERO; + } + + return; +} + +booleantype N_VInvTest_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) { + if (xd[i] == ZERO) return(FALSE); + zd[i] = ONE/xd[i]; + } + + return(TRUE); +} + +booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m) +{ + long int i, N; + booleantype test; + realtype *cd, *xd, *md; + + cd = xd = md = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + cd = NV_DATA_S(c); + md = NV_DATA_S(m); + + test = TRUE; + + for (i = 0; i < N; i++) { + md[i] = ZERO; + if (cd[i] == ZERO) continue; + if (cd[i] > ONEPT5 || cd[i] < -ONEPT5) { + if ( xd[i]*cd[i] <= ZERO) { test = FALSE; md[i] = ONE; } + continue; + } + if ( cd[i] > HALF || cd[i] < -HALF) { + if (xd[i]*cd[i] < ZERO ) { test = FALSE; md[i] = ONE; } + } + } + + return(test); +} + +realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom) +{ + booleantype notEvenOnce; + long int i, N; + realtype *nd, *dd, min; + + nd = dd = NULL; + + N = NV_LENGTH_S(num); + nd = NV_DATA_S(num); + dd = NV_DATA_S(denom); + + notEvenOnce = TRUE; + min = BIG_REAL; + + for (i = 0; i < N; i++) { + if (dd[i] == ZERO) continue; + else { + if (!notEvenOnce) min = MIN(min, nd[i]/dd[i]); + else { + min = nd[i]/dd[i]; + notEvenOnce = FALSE; + } + } + } + + return(min); +} + +/* + * ----------------------------------------------------------------- + * private functions + * ----------------------------------------------------------------- + */ + +static void VCopy_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]; + + return; +} + +static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]+yd[i]; + + return; +} + +static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = xd[i]-yd[i]; + + return; +} + +static void VNeg_Serial(N_Vector x, N_Vector z) +{ + long int i, N; + realtype *xd, *zd; + + xd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = -xd[i]; + + return; +} + +static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]+yd[i]); + + return; +} + +static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = c*(xd[i]-yd[i]); + + return; +} + +static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])+yd[i]; + + return; +} + +static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z) +{ + long int i, N; + realtype *xd, *yd, *zd; + + xd = yd = zd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + zd = NV_DATA_S(z); + + for (i = 0; i < N; i++) + zd[i] = (a*xd[i])-yd[i]; + + return; +} + +static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y) +{ + long int i, N; + realtype *xd, *yd; + + xd = yd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + yd = NV_DATA_S(y); + + if (a == ONE) { + for (i = 0; i < N; i++) + yd[i] += xd[i]; + return; + } + + if (a == -ONE) { + for (i = 0; i < N; i++) + yd[i] -= xd[i]; + return; + } + + for (i = 0; i < N; i++) + yd[i] += a*xd[i]; + + return; +} + +static void VScaleBy_Serial(realtype a, N_Vector x) +{ + long int i, N; + realtype *xd; + + xd = NULL; + + N = NV_LENGTH_S(x); + xd = NV_DATA_S(x); + + for (i = 0; i < N; i++) + xd[i] *= a; + + return; +} diff --git a/dep/cvode-2.7.0/sundials/CMakeLists.txt b/dep/cvode-2.7.0/sundials/CMakeLists.txt new file mode 100644 index 00000000..64364d24 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/CMakeLists.txt @@ -0,0 +1,45 @@ +# --------------------------------------------------------------- +# $Revision: 1.4 $ +# $Date: 2009/02/17 02:52:53 $ +# --------------------------------------------------------------- +# Programmer: Radu Serban @ LLNL +# --------------------------------------------------------------- +# Copyright (c) 2007, The Regents of the University of California. +# Produced at the Lawrence Livermore National Laboratory. +# All rights reserved. +# For details, see the LICENSE file. +# --------------------------------------------------------------- +# CMakeLists.txt file for the generic SUNDIALS modules + +# From here we only install the generic SUNDIALS headers. +# The implementations themselves are incorporated in the individual SUNDIALS solver libraries. + +INSTALL(CODE "MESSAGE(\"\nInstall shared components\n\")") + +# Add variable sundials_HEADERS with the exported SUNDIALS header files +SET(sundials_HEADERS + sundials_band.h + sundials_dense.h + sundials_direct.h + sundials_iterative.h + sundials_math.h + sundials_nvector.h + sundials_fnvector.h + sundials_spbcgs.h + sundials_spgmr.h + sundials_sptfqmr.h + sundials_types.h + ) + +# Add prefix with complete path to the SUNDIALS header files +ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_HEADERS) + +# Install the SUNDIALS header files +INSTALL(FILES ${sundials_HEADERS} DESTINATION include/dep/sundials) + +# If Blas/Lapack support was enabled, install the Lapack interface headers +IF(LAPACK_FOUND) + SET(sundials_BL_HEADERS sundials_lapack.h) + ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_BL_HEADERS) + INSTALL(FILES ${sundials_BL_HEADERS} DESTINATION include/dep/sundials) +ENDIF(LAPACK_FOUND) diff --git a/dep/cvode-2.7.0/sundials/README b/dep/cvode-2.7.0/sundials/README new file mode 100644 index 00000000..0b6bd8c8 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/README @@ -0,0 +1,215 @@ + SUNDIALS + Shared Module + Release 2.5.0, March 2012 + + +The family of solvers referred to as SUNDIALS consists of solvers +CVODE (ODE), CVODES (ODE with sensitivity analysis capabilities), +IDA (DAE), IDAS (DAE with sensitivity analysis capabilities), and +KINSOL (for nonlinear algebraic systems). + +The various solvers of this family share many subordinate modules contained +in this module: +- generic NVECTOR module +- generic linear solver modules (band, dense, lapack, spgmr, bcg, tfqmr) +- definitions of SUNDIALS types (realtype, booleantype) +- common math functions (RpowerI, RPowerR, RSqrt, RAbs,...) + + +A. Documentation +---------------- +All shared submodules are fully described in the user documentation for any of +the SUNDIALS solvers [1-5]. A PDF file for the user guide for a particular solver +is available in the solver's subdirectory under doc/. + + +B. Installation +--------------- + +For basic installation instructions see the file /sundials/INSTALL_NOTES. +For complete installation instructions see any of the user guides. + + +C. References +------------- + +[1] A. C. Hindmarsh and R. Serban, "User Documentation for CVODE v2.7.0," + LLNL technical report UCRL-MA-208108, December 2011. + +[2] A. C. Hindmarsh and R. Serban, "User Documentation for CVODES v2.7.0," + LLNL technical report UCRL-MA-208111, December 2011. + +[3] A. C. Hindmarsh and R. Serban, "User Documentation for IDA v2.7.0," + LLNL technical report UCRL-MA-208112, December 2011. + +[4] R. Serban and C. Petra, "User Documentation for IDAS v1.1.0," + LLNL technical report UCRL-SM-234051, December 2011. + +[5] A. M. Collier, A. C. Hindmarsh, R. Serban,and C. S. Woodward, "User + Documentation for KINSOL v2.7.0," LLNL technical report UCRL-MA-208116, + December 2011. + + +D. Releases +----------- + +v. 2.5.0 - Mar. 2012 +v. 2.4.0 - May 2009 +v. 2.3.0 - Nov. 2006 +v. 2.2.0 - Mar. 2006 +v. 2.1.1 - May. 2005 +v. 2.1.0 - Apr. 2005 +v. 2.0.2 - Mar. 2005 +v. 2.0.1 - Jan. 2005 +v. 2.0 - Dec. 2004 +v. 1.0 - Jul. 2002 (first SUNDIALS release) +v. 0.0 - Mar. 2002 + + +E. Revision History +------------------- + +v. 2.4.0 (May 2009) ---> v. 2.5.0 (Mar. 2012) +--------------------------------------------- + +- Changes to user interface + - One significant design change was made with this release: The problem + size and its relatives, bandwidth parameters, related internal indices, + pivot arrays, and the optional output lsflag, have all been + changed from type int to type long int, except for the + problem size and bandwidths in user calls to routines specifying + BLAS/LAPACK routines for the dense/band linear solvers. The function + NewIntArray is replaced by a pair NewIntArray/NewLintArray, + for int and long int arrays, respectively. + +v. 2.3.0 (Nov. 2006) ---> v. 2.4.0 (May 2009) +--------------------------------------------- + +- New features + - added a new generic linear solver module based on Blas + Lapack + for both dense and banded matrices. + +- Changes to user interface + - common functionality for all direct linear solvers (dense, band, and + the new Lapack solver) has been collected into the DLS (Direct Linear + Solver) module, implemented in the files sundials_direct.h and + sundials_direct.c (similar to the SPILS module for the iterative linear + solvers). + - in order to include the new Lapack-based linear solver, all dimensions + for the above linear solvers (problem sizes, bandwidths,... including + the underlying matrix data types) are now of type 'int' (and not 'long int'). + + +v. 2.2.0 (Mar. 2006) ---> v. 2.3.0 (Nov. 2006) +---------------------------------------------- + +- Changes to the user interface + - modified sundials_dense and sundials_smalldense to work with + rectangular m by n matrices (m <= n). + +- Changes related to the build system + - reorganized source tree + - exported header files are installed in solver-specific subdirectories + of ${includedir} + - sundialsTB is distributed only as part of the SUNDIALS tarball + +v. 2.1.1 (May 2005) ---> v. 2.2.0 (Mar. 2006) +--------------------------------------------- + +- New features + - added SPBCG (scaled preconditioned Bi-CGStab) linear solver module + - added SPTFQMR (scaled preconditioned TFQMR) linear solver module + +- Changes related to the build system + - updated configure script and Makefiles for Fortran examples to avoid C++ + compiler errors (now use CC and MPICC to link only if necessary) + - SUNDIALS shared header files are installed under a 'sundials' subdirectory + of the install include directory + - the shared object files are now linked into each SUNDIALS library rather + than into a separate libsundials_shared library + +- Changes to the user interface + - added prefix 'sundials_' to all shared header files + +v. 2.1.0 (Apr. 2005) ---> v. 2.1.1 (May.2005) +--------------------------------------------- + +- Changes to data structures + - added N_VCloneEmpty to global vector operations table + +v. 2.0.2 (Mar. 2005) ---> v. 2.1.0 (Apr. 2005) +---------------------------------------------- + +- none + +v. 2.0.1 (Jan. 2005) ---> v. 2.0.2 (Mar. 2005) +---------------------------------------------- + +- Changes related to the build system + - fixed autoconf-related bug to allow configuration with the PGI Fortran compiler + - modified to use customized detection of the Fortran name mangling scheme + (autoconf's AC_F77_WRAPPERS routine is problematic on some platforms) + - added --with-mpi-flags as a configure option to allow user to specify + MPI-specific flags + - updated Makefiles for Fortran examples to avoid C++ compiler errors (now use + CC and MPICC to link) + +v. 2.0 (Dec. 2004) ---> v. 2.0.1 (Jan. 2005) +-------------------------------------------- + +- Changes related to the build system + - changed order of compiler directives in header files to avoid compilation + errors when using a C++ compiler. + +v. 1.0 (Jul. 2002) ---> v. 2.0 (Dec. 2004) +------------------------------------------ + +- Changes to the generic NVECTOR module + - removed machEnv, redefined table of vector operations (now contained + in the N_Vector structure itself). + - all SUNDIALS functions create new N_Vector variables through cloning, using + an N_Vector passed by the user as a template. + - a particular NVECTOR implementation is supposed to provide user-callable + constructor and destructor functions. + - removed from structure of vector operations the following functions: + N_VNew, N_VNew_S, N_VFree, N_VFree_S, N_VMake, N_VDispose, N_VGetData, + N_VSetData, N_VConstrProdPos, and N_VOneMask. + - added in structure of vector operations the following functions: + N_VClone, N_VDestroy, N_VSpace, N_VGetArrayPointer, N_VSetArrayPointer, + and N_VWrmsNormMask. + - Note that nvec_ser and nvec_par are now separate modules outside the + shared SUNDIALS module. + +- Changes to the generic linear solvers + - in SPGMR, added a dummy N_Vector argument to be used as a template + for cloning. + - in SPGMR, removed N (problem dimension) from argument list of SpgmrMalloc. + - iterative.{c,h} replace iterativ.{c,h} + - modified constant names in iterative.h (preconditioner types are prefixed + with 'PREC_'). + - changed numerical values for MODIFIED_GS (from 0 to 1) and CLASSICAL_GS + (from 1 to 2). + +- Changes to sundialsmath submodule + - replaced internal routine for estimation of unit roundoff with definition + of unit roundoff from float.h + - modified functions to call appropriate math routines given the precision + level specified by the user. + +- Changes to sundialstypes submodule + - removed type 'integertype'. + - added definitions for 'BIG_REAL', 'SMALL_REAL', and 'UNIT_ROUNDOFF' using + values from float.h based on the precision. + - changed definition of macro RCONST to depend on precision. + +v 0.0 (Mar. 2002) ---> v. 1.0 (Jul. 2002) +----------------------------------------- + +20020321 Defined and implemented generic NVECTOR module, and separate serial/ + parallel NVECTOR modules, including serial/parallel F/C interfaces. + Modified dense and band backsolve routines to take real* type for + RHS and solution vector. +20020329 Named the DenseMat, BandMat, and SpgmrMemRec structures. +20020626 Changed type names to realtype, integertype, booleantype. + Renamed llnltypes and llnlmath files. + diff --git a/dep/cvode-2.7.0/sundials/sundials_band.c b/dep/cvode-2.7.0/sundials/sundials_band.c new file mode 100644 index 00000000..b9286ab1 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_band.c @@ -0,0 +1,235 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2010/12/01 22:46:56 $ + * ----------------------------------------------------------------- + * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic BAND linear + * solver package. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +#define ROW(i,j,smu) (i-j+smu) + +/* + * ----------------------------------------------------- + * Functions working on DlsMat + * ----------------------------------------------------- + */ + +long int BandGBTRF(DlsMat A, long int *p) +{ + return(bandGBTRF(A->cols, A->M, A->mu, A->ml, A->s_mu, p)); +} + +void BandGBTRS(DlsMat A, long int *p, realtype *b) +{ + bandGBTRS(A->cols, A->M, A->s_mu, A->ml, p, b); +} + +void BandCopy(DlsMat A, DlsMat B, long int copymu, long int copyml) +{ + bandCopy(A->cols, B->cols, A->M, A->s_mu, B->s_mu, copymu, copyml); +} + +void BandScale(realtype c, DlsMat A) +{ + bandScale(c, A->cols, A->M, A->mu, A->ml, A->s_mu); +} + +/* + * ----------------------------------------------------- + * Functions working on realtype** + * ----------------------------------------------------- + */ + +long int bandGBTRF(realtype **a, long int n, long int mu, long int ml, long int smu, long int *p) +{ + long int c, r, num_rows; + long int i, j, k, l, storage_l, storage_k, last_col_k, last_row_k; + realtype *a_c, *col_k, *diag_k, *sub_diag_k, *col_j, *kptr, *jptr; + realtype max, temp, mult, a_kj; + booleantype swap; + + /* zero out the first smu - mu rows of the rectangular array a */ + + num_rows = smu - mu; + if (num_rows > 0) { + for (c=0; c < n; c++) { + a_c = a[c]; + for (r=0; r < num_rows; r++) { + a_c[r] = ZERO; + } + } + } + + /* k = elimination step number */ + + for (k=0; k < n-1; k++, p++) { + + col_k = a[k]; + diag_k = col_k + smu; + sub_diag_k = diag_k + 1; + last_row_k = MIN(n-1,k+ml); + + /* find l = pivot row number */ + + l=k; + max = ABS(*diag_k); + for (i=k+1, kptr=sub_diag_k; i <= last_row_k; i++, kptr++) { + if (ABS(*kptr) > max) { + l=i; + max = ABS(*kptr); + } + } + storage_l = ROW(l, k, smu); + *p = l; + + /* check for zero pivot element */ + + if (col_k[storage_l] == ZERO) return(k+1); + + /* swap a(l,k) and a(k,k) if necessary */ + + if ( (swap = (l != k) )) { + temp = col_k[storage_l]; + col_k[storage_l] = *diag_k; + *diag_k = temp; + } + + /* Scale the elements below the diagonal in */ + /* column k by -1.0 / a(k,k). After the above swap, */ + /* a(k,k) holds the pivot element. This scaling */ + /* stores the pivot row multipliers -a(i,k)/a(k,k) */ + /* in a(i,k), i=k+1, ..., MIN(n-1,k+ml). */ + + mult = -ONE / (*diag_k); + for (i=k+1, kptr = sub_diag_k; i <= last_row_k; i++, kptr++) + (*kptr) *= mult; + + /* row_i = row_i - [a(i,k)/a(k,k)] row_k, i=k+1, ..., MIN(n-1,k+ml) */ + /* row k is the pivot row after swapping with row l. */ + /* The computation is done one column at a time, */ + /* column j=k+1, ..., MIN(k+smu,n-1). */ + + last_col_k = MIN(k+smu,n-1); + for (j=k+1; j <= last_col_k; j++) { + + col_j = a[j]; + storage_l = ROW(l,j,smu); + storage_k = ROW(k,j,smu); + a_kj = col_j[storage_l]; + + /* Swap the elements a(k,j) and a(k,l) if l!=k. */ + + if (swap) { + col_j[storage_l] = col_j[storage_k]; + col_j[storage_k] = a_kj; + } + + /* a(i,j) = a(i,j) - [a(i,k)/a(k,k)]*a(k,j) */ + /* a_kj = a(k,j), *kptr = - a(i,k)/a(k,k), *jptr = a(i,j) */ + + if (a_kj != ZERO) { + for (i=k+1, kptr=sub_diag_k, jptr=col_j+ROW(k+1,j,smu); + i <= last_row_k; + i++, kptr++, jptr++) + (*jptr) += a_kj * (*kptr); + } + } + } + + /* set the last pivot row to be n-1 and check for a zero pivot */ + + *p = n-1; + if (a[n-1][smu] == ZERO) return(n); + + /* return 0 to indicate success */ + + return(0); +} + +void bandGBTRS(realtype **a, long int n, long int smu, long int ml, long int *p, realtype *b) +{ + long int k, l, i, first_row_k, last_row_k; + realtype mult, *diag_k; + + /* Solve Ly = Pb, store solution y in b */ + + for (k=0; k < n-1; k++) { + l = p[k]; + mult = b[l]; + if (l != k) { + b[l] = b[k]; + b[k] = mult; + } + diag_k = a[k]+smu; + last_row_k = MIN(n-1,k+ml); + for (i=k+1; i <= last_row_k; i++) + b[i] += mult * diag_k[i-k]; + } + + /* Solve Ux = y, store solution x in b */ + + for (k=n-1; k >= 0; k--) { + diag_k = a[k]+smu; + first_row_k = MAX(0,k-smu); + b[k] /= (*diag_k); + mult = -b[k]; + for (i=first_row_k; i <= k-1; i++) + b[i] += mult*diag_k[i-k]; + } +} + +void bandCopy(realtype **a, realtype **b, long int n, long int a_smu, long int b_smu, + long int copymu, long int copyml) +{ + long int i, j, copySize; + realtype *a_col_j, *b_col_j; + + copySize = copymu + copyml + 1; + + for (j=0; j < n; j++) { + a_col_j = a[j]+a_smu-copymu; + b_col_j = b[j]+b_smu-copymu; + for (i=0; i < copySize; i++) + b_col_j[i] = a_col_j[i]; + } +} + +void bandScale(realtype c, realtype **a, long int n, long int mu, long int ml, long int smu) +{ + long int i, j, colSize; + realtype *col_j; + + colSize = mu + ml + 1; + + for(j=0; j < n; j++) { + col_j = a[j]+smu-mu; + for (i=0; i < colSize; i++) + col_j[i] *= c; + } +} + +void bandAddIdentity(realtype **a, long int n, long int smu) +{ + long int j; + + for(j=0; j < n; j++) + a[j][smu] += ONE; +} diff --git a/dep/cvode-2.7.0/sundials/sundials_dense.c b/dep/cvode-2.7.0/sundials/sundials_dense.c new file mode 100644 index 00000000..4fa3bb07 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_dense.c @@ -0,0 +1,373 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.7 $ + * $Date: 2010/12/01 22:46:56 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic package of dense + * matrix operations. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) +#define TWO RCONST(2.0) + +/* + * ----------------------------------------------------- + * Functions working on DlsMat + * ----------------------------------------------------- + */ + +long int DenseGETRF(DlsMat A, long int *p) +{ + return(denseGETRF(A->cols, A->M, A->N, p)); +} + +void DenseGETRS(DlsMat A, long int *p, realtype *b) +{ + denseGETRS(A->cols, A->N, p, b); +} + +long int DensePOTRF(DlsMat A) +{ + return(densePOTRF(A->cols, A->M)); +} + +void DensePOTRS(DlsMat A, realtype *b) +{ + densePOTRS(A->cols, A->M, b); +} + +int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk) +{ + return(denseGEQRF(A->cols, A->M, A->N, beta, wrk)); +} + +int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, realtype *wrk) +{ + return(denseORMQR(A->cols, A->M, A->N, beta, vn, vm, wrk)); +} + +void DenseCopy(DlsMat A, DlsMat B) +{ + denseCopy(A->cols, B->cols, A->M, A->N); +} + +void DenseScale(realtype c, DlsMat A) +{ + denseScale(c, A->cols, A->M, A->N); +} + +long int denseGETRF(realtype **a, long int m, long int n, long int *p) +{ + long int i, j, k, l; + realtype *col_j, *col_k; + realtype temp, mult, a_kj; + + /* k-th elimination step number */ + for (k=0; k < n; k++) { + + col_k = a[k]; + + /* find l = pivot row number */ + l=k; + for (i=k+1; i < m; i++) + if (ABS(col_k[i]) > ABS(col_k[l])) l=i; + p[k] = l; + + /* check for zero pivot element */ + if (col_k[l] == ZERO) return(k+1); + + /* swap a(k,1:n) and a(l,1:n) if necessary */ + if ( l!= k ) { + for (i=0; i 0; k--) { + col_k = a[k]; + b[k] /= col_k[k]; + for (i=0; i0) { + for(i=j; i=0; i--) { + col_i = a[i]; + for (j=i+1; j= n) + * using Householder reflections. + * + * On exit, the elements on and above the diagonal of A contain the n by n + * upper triangular matrix R; the elements below the diagonal, with the array beta, + * represent the orthogonal matrix Q as a product of elementary reflectors . + * + * v (of length m) must be provided as workspace. + * + */ + +int denseGEQRF(realtype **a, long int m, long int n, realtype *beta, realtype *v) +{ + realtype ajj, s, mu, v1, v1_2; + realtype *col_j, *col_k; + long int i, j, k; + + /* For each column...*/ + for(j=0; j= n. + * + * v (of length m) must be provided as workspace. + */ +int denseORMQR(realtype **a, long int m, long int n, realtype *beta, + realtype *vn, realtype *vm, realtype *v) +{ + realtype *col_j, s; + long int i, j; + + /* Initialize vm */ + for(i=0; i=0; j--) { + + col_j = a[j]; + + v[0] = ONE; + s = vm[j]; + for(i=1; i +#include + +#include +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +DlsMat NewDenseMat(long int M, long int N) +{ + DlsMat A; + long int j; + + if ( (M <= 0) || (N <= 0) ) return(NULL); + + A = NULL; + A = (DlsMat) malloc(sizeof *A); + if (A==NULL) return (NULL); + + A->data = (realtype *) malloc(M * N * sizeof(realtype)); + if (A->data == NULL) { + free(A); A = NULL; + return(NULL); + } + A->cols = (realtype **) malloc(N * sizeof(realtype *)); + if (A->cols == NULL) { + free(A->data); A->data = NULL; + free(A); A = NULL; + return(NULL); + } + + for (j=0; j < N; j++) A->cols[j] = A->data + j * M; + + A->M = M; + A->N = N; + A->ldim = M; + A->ldata = M*N; + + A->type = SUNDIALS_DENSE; + + return(A); +} + +realtype **newDenseMat(long int m, long int n) +{ + long int j; + realtype **a; + + if ( (n <= 0) || (m <= 0) ) return(NULL); + + a = NULL; + a = (realtype **) malloc(n * sizeof(realtype *)); + if (a == NULL) return(NULL); + + a[0] = NULL; + a[0] = (realtype *) malloc(m * n * sizeof(realtype)); + if (a[0] == NULL) { + free(a); a = NULL; + return(NULL); + } + + for (j=1; j < n; j++) a[j] = a[0] + j * m; + + return(a); +} + + +DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu) +{ + DlsMat A; + long int j, colSize; + + if (N <= 0) return(NULL); + + A = NULL; + A = (DlsMat) malloc(sizeof *A); + if (A == NULL) return (NULL); + + colSize = smu + ml + 1; + A->data = NULL; + A->data = (realtype *) malloc(N * colSize * sizeof(realtype)); + if (A->data == NULL) { + free(A); A = NULL; + return(NULL); + } + + A->cols = NULL; + A->cols = (realtype **) malloc(N * sizeof(realtype *)); + if (A->cols == NULL) { + free(A->data); + free(A); A = NULL; + return(NULL); + } + + for (j=0; j < N; j++) A->cols[j] = A->data + j * colSize; + + A->M = N; + A->N = N; + A->mu = mu; + A->ml = ml; + A->s_mu = smu; + A->ldim = colSize; + A->ldata = N * colSize; + + A->type = SUNDIALS_BAND; + + return(A); +} + +realtype **newBandMat(long int n, long int smu, long int ml) +{ + realtype **a; + long int j, colSize; + + if (n <= 0) return(NULL); + + a = NULL; + a = (realtype **) malloc(n * sizeof(realtype *)); + if (a == NULL) return(NULL); + + colSize = smu + ml + 1; + a[0] = NULL; + a[0] = (realtype *) malloc(n * colSize * sizeof(realtype)); + if (a[0] == NULL) { + free(a); a = NULL; + return(NULL); + } + + for (j=1; j < n; j++) a[j] = a[0] + j * colSize; + + return(a); +} + +void DestroyMat(DlsMat A) +{ + free(A->data); A->data = NULL; + free(A->cols); + free(A); A = NULL; +} + +void destroyMat(realtype **a) +{ + free(a[0]); a[0] = NULL; + free(a); a = NULL; +} + +int *NewIntArray(int N) +{ + int *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (int *) malloc(N * sizeof(int)); + + return(vec); +} + +int *newIntArray(int n) +{ + int *v; + + if (n <= 0) return(NULL); + + v = NULL; + v = (int *) malloc(n * sizeof(int)); + + return(v); +} + +long int *NewLintArray(long int N) +{ + long int *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (long int *) malloc(N * sizeof(long int)); + + return(vec); +} + +long int *newLintArray(long int n) +{ + long int *v; + + if (n <= 0) return(NULL); + + v = NULL; + v = (long int *) malloc(n * sizeof(long int)); + + return(v); +} + +realtype *NewRealArray(long int N) +{ + realtype *vec; + + if (N <= 0) return(NULL); + + vec = NULL; + vec = (realtype *) malloc(N * sizeof(realtype)); + + return(vec); +} + +realtype *newRealArray(long int m) +{ + realtype *v; + + if (m <= 0) return(NULL); + + v = NULL; + v = (realtype *) malloc(m * sizeof(realtype)); + + return(v); +} + +void DestroyArray(void *V) +{ + free(V); + V = NULL; +} + +void destroyArray(void *v) +{ + free(v); + v = NULL; +} + + +void AddIdentity(DlsMat A) +{ + long int i; + + switch (A->type) { + + case SUNDIALS_DENSE: + for (i=0; iN; i++) A->cols[i][i] += ONE; + break; + + case SUNDIALS_BAND: + for (i=0; iM; i++) A->cols[i][A->s_mu] += ONE; + break; + + } + +} + + +void SetToZero(DlsMat A) +{ + long int i, j, colSize; + realtype *col_j; + + switch (A->type) { + + case SUNDIALS_DENSE: + + for (j=0; jN; j++) { + col_j = A->cols[j]; + for (i=0; iM; i++) + col_j[i] = ZERO; + } + + break; + + case SUNDIALS_BAND: + + colSize = A->mu + A->ml + 1; + for (j=0; jM; j++) { + col_j = A->cols[j] + A->s_mu - A->mu; + for (i=0; itype) { + + case SUNDIALS_DENSE: + + printf("\n"); + for (i=0; i < A->M; i++) { + for (j=0; j < A->N; j++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%12Lg ", DENSE_ELEM(A,i,j)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%12lg ", DENSE_ELEM(A,i,j)); +#else + printf("%12g ", DENSE_ELEM(A,i,j)); +#endif + } + printf("\n"); + } + printf("\n"); + + break; + + case SUNDIALS_BAND: + + a = A->cols; + printf("\n"); + for (i=0; i < A->N; i++) { + start = MAX(0,i-A->ml); + finish = MIN(A->N-1,i+A->mu); + for (j=0; j < start; j++) printf("%12s ",""); + for (j=start; j <= finish; j++) { +#if defined(SUNDIALS_EXTENDED_PRECISION) + printf("%12Lg ", a[j][i-j+A->s_mu]); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + printf("%12lg ", a[j][i-j+A->s_mu]); +#else + printf("%12g ", a[j][i-j+A->s_mu]); +#endif + } + printf("\n"); + } + printf("\n"); + + break; + + } + +} + + diff --git a/dep/cvode-2.7.0/sundials/sundials_iterative.c b/dep/cvode-2.7.0/sundials/sundials_iterative.c new file mode 100644 index 00000000..41ccc172 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_iterative.c @@ -0,0 +1,288 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the iterative.h header + * file. It contains the implementation of functions that may be + * useful for many different iterative solvers of A x = b. + * ----------------------------------------------------------------- + */ + +#include + +#include +#include + +#define FACTOR RCONST(1000.0) +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : ModifiedGS + * ----------------------------------------------------------------- + * This implementation of ModifiedGS is a slight modification of a + * previous modified Gram-Schmidt routine (called mgs) written by + * Milo Dorr. + * ----------------------------------------------------------------- + */ + +int ModifiedGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm) +{ + int i, k_minus_1, i0; + realtype new_norm_2, new_product, vk_norm, temp; + + vk_norm = RSqrt(N_VDotProd(v[k],v[k])); + k_minus_1 = k - 1; + i0 = MAX(k-p, 0); + + /* Perform modified Gram-Schmidt */ + + for (i=i0; i < k; i++) { + h[i][k_minus_1] = N_VDotProd(v[i], v[k]); + N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]); + } + + /* Compute the norm of the new vector at v[k] */ + + *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + /* If the norm of the new vector at v[k] is less than + FACTOR (== 1000) times unit roundoff times the norm of the + input vector v[k], then the vector will be reorthogonalized + in order to ensure that nonorthogonality is not being masked + by a very small vector length. */ + + temp = FACTOR * vk_norm; + if ((temp + (*new_vk_norm)) != temp) return(0); + + new_norm_2 = ZERO; + + for (i=i0; i < k; i++) { + new_product = N_VDotProd(v[i], v[k]); + temp = FACTOR * h[i][k_minus_1]; + if ((temp + new_product) == temp) continue; + h[i][k_minus_1] += new_product; + N_VLinearSum(ONE, v[k],-new_product, v[i], v[k]); + new_norm_2 += SQR(new_product); + } + + if (new_norm_2 != ZERO) { + new_product = SQR(*new_vk_norm) - new_norm_2; + *new_vk_norm = (new_product > ZERO) ? RSqrt(new_product) : ZERO; + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : ClassicalGS + * ----------------------------------------------------------------- + * This implementation of ClassicalGS was contributed by Homer Walker + * and Peter Brown. + * ----------------------------------------------------------------- + */ + +int ClassicalGS(N_Vector *v, realtype **h, int k, int p, + realtype *new_vk_norm, N_Vector temp, realtype *s) +{ + int i, k_minus_1, i0; + realtype vk_norm; + + k_minus_1 = k - 1; + + /* Perform Classical Gram-Schmidt */ + + vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + i0 = MAX(k-p, 0); + for (i=i0; i < k; i++) { + h[i][k_minus_1] = N_VDotProd(v[i], v[k]); + } + + for (i=i0; i < k; i++) { + N_VLinearSum(ONE, v[k], -h[i][k_minus_1], v[i], v[k]); + } + + /* Compute the norm of the new vector at v[k] */ + + *new_vk_norm = RSqrt(N_VDotProd(v[k], v[k])); + + /* Reorthogonalize if necessary */ + + if ((FACTOR * (*new_vk_norm)) < vk_norm) { + + for (i=i0; i < k; i++) { + s[i] = N_VDotProd(v[i], v[k]); + } + + if (i0 < k) { + N_VScale(s[i0], v[i0], temp); + h[i0][k_minus_1] += s[i0]; + } + for (i=i0+1; i < k; i++) { + N_VLinearSum(s[i], v[i], ONE, temp, temp); + h[i][k_minus_1] += s[i]; + } + N_VLinearSum(ONE, v[k], -ONE, temp, v[k]); + + *new_vk_norm = RSqrt(N_VDotProd(v[k],v[k])); + } + + return(0); +} + +/* + * ----------------------------------------------------------------- + * Function : QRfact + * ----------------------------------------------------------------- + * This implementation of QRfact is a slight modification of a + * previous routine (called qrfact) written by Milo Dorr. + * ----------------------------------------------------------------- + */ + +int QRfact(int n, realtype **h, realtype *q, int job) +{ + realtype c, s, temp1, temp2, temp3; + int i, j, k, q_ptr, n_minus_1, code=0; + + switch (job) { + case 0: + + /* Compute a new factorization of H */ + + code = 0; + for (k=0; k < n; k++) { + + /* Multiply column k by the previous k-1 Givens rotations */ + + for (j=0; j < k-1; j++) { + i = 2*j; + temp1 = h[j][k]; + temp2 = h[j+1][k]; + c = q[i]; + s = q[i+1]; + h[j][k] = c*temp1 - s*temp2; + h[j+1][k] = s*temp1 + c*temp2; + } + + /* Compute the Givens rotation components c and s */ + + q_ptr = 2*k; + temp1 = h[k][k]; + temp2 = h[k+1][k]; + if( temp2 == ZERO) { + c = ONE; + s = ZERO; + } else if (ABS(temp2) >= ABS(temp1)) { + temp3 = temp1/temp2; + s = -ONE/RSqrt(ONE+SQR(temp3)); + c = -s*temp3; + } else { + temp3 = temp2/temp1; + c = ONE/RSqrt(ONE+SQR(temp3)); + s = -c*temp3; + } + q[q_ptr] = c; + q[q_ptr+1] = s; + if( (h[k][k] = c*temp1 - s*temp2) == ZERO) code = k+1; + } + break; + + default: + + /* Update the factored H to which a new column has been added */ + + n_minus_1 = n - 1; + code = 0; + + /* Multiply the new column by the previous n-1 Givens rotations */ + + for (k=0; k < n_minus_1; k++) { + i = 2*k; + temp1 = h[k][n_minus_1]; + temp2 = h[k+1][n_minus_1]; + c = q[i]; + s = q[i+1]; + h[k][n_minus_1] = c*temp1 - s*temp2; + h[k+1][n_minus_1] = s*temp1 + c*temp2; + } + + /* Compute new Givens rotation and multiply it times the last two + entries in the new column of H. Note that the second entry of + this product will be 0, so it is not necessary to compute it. */ + + temp1 = h[n_minus_1][n_minus_1]; + temp2 = h[n][n_minus_1]; + if (temp2 == ZERO) { + c = ONE; + s = ZERO; + } else if (ABS(temp2) >= ABS(temp1)) { + temp3 = temp1/temp2; + s = -ONE/RSqrt(ONE+SQR(temp3)); + c = -s*temp3; + } else { + temp3 = temp2/temp1; + c = ONE/RSqrt(ONE+SQR(temp3)); + s = -c*temp3; + } + q_ptr = 2*n_minus_1; + q[q_ptr] = c; + q[q_ptr+1] = s; + if ((h[n_minus_1][n_minus_1] = c*temp1 - s*temp2) == ZERO) + code = n; + } + + return (code); +} + +/* + * ----------------------------------------------------------------- + * Function : QRsol + * ----------------------------------------------------------------- + * This implementation of QRsol is a slight modification of a + * previous routine (called qrsol) written by Milo Dorr. + * ----------------------------------------------------------------- + */ + +int QRsol(int n, realtype **h, realtype *q, realtype *b) +{ + realtype c, s, temp1, temp2; + int i, k, q_ptr, code=0; + + /* Compute Q*b */ + + for (k=0; k < n; k++) { + q_ptr = 2*k; + c = q[q_ptr]; + s = q[q_ptr+1]; + temp1 = b[k]; + temp2 = b[k+1]; + b[k] = c*temp1 - s*temp2; + b[k+1] = s*temp1 + c*temp2; + } + + /* Solve R*x = Q*b */ + + for (k=n-1; k >= 0; k--) { + if (h[k][k] == ZERO) { + code = k + 1; + break; + } + b[k] /= h[k][k]; + for (i=0; i < k; i++) b[i] -= b[k]*h[i][k]; + } + + return (code); +} diff --git a/dep/cvode-2.7.0/sundials/sundials_math.c b/dep/cvode-2.7.0/sundials/sundials_math.c new file mode 100644 index 00000000..8bc9d593 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_math.c @@ -0,0 +1,94 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.1 $ + * $Date: 2006/07/05 15:32:38 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a simple C-language math + * library. + * ----------------------------------------------------------------- + */ + +#include +#include +#include + +#include + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +realtype RPowerI(realtype base, int exponent) +{ + int i, expt; + realtype prod; + + prod = ONE; + expt = abs(exponent); + for(i = 1; i <= expt; i++) prod *= base; + if (exponent < 0) prod = ONE/prod; + return(prod); +} + +realtype RPowerR(realtype base, realtype exponent) +{ + if (base <= ZERO) return(ZERO); + +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) pow((double) base, (double) exponent)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(pow(base, exponent)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(powf(base, exponent)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(powl(base, exponent)); +#endif +} + +realtype RSqrt(realtype x) +{ + if (x <= ZERO) return(ZERO); + +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) sqrt((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(sqrt(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(sqrtf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(sqrtl(x)); +#endif +} + +realtype RAbs(realtype x) +{ +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) fabs((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(fabs(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(fabsf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(fabsl(x)); +#endif +} + +realtype RExp(realtype x) +{ +#if defined(SUNDIALS_USE_GENERIC_MATH) + return((realtype) exp((double) x)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + return(exp(x)); +#elif defined(SUNDIALS_SINGLE_PRECISION) + return(expf(x)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + return(expl(x)); +#endif +} diff --git a/dep/cvode-2.7.0/sundials/sundials_nvector.c b/dep/cvode-2.7.0/sundials/sundials_nvector.c new file mode 100644 index 00000000..e8e1b833 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_nvector.c @@ -0,0 +1,233 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.3 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Radu Serban and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for a generic NVECTOR package. + * It contains the implementation of the N_Vector operations listed + * in nvector.h. + * ----------------------------------------------------------------- + */ + +#include + +#include + +/* + * ----------------------------------------------------------------- + * Functions in the 'ops' structure + * ----------------------------------------------------------------- + */ + +N_Vector N_VClone(N_Vector w) +{ + N_Vector v = NULL; + v = w->ops->nvclone(w); + return(v); +} + +N_Vector N_VCloneEmpty(N_Vector w) +{ + N_Vector v = NULL; + v = w->ops->nvcloneempty(w); + return(v); +} + +void N_VDestroy(N_Vector v) +{ + if (v==NULL) return; + v->ops->nvdestroy(v); + return; +} + +void N_VSpace(N_Vector v, long int *lrw, long int *liw) +{ + v->ops->nvspace(v, lrw, liw); + return; +} + +realtype *N_VGetArrayPointer(N_Vector v) +{ + return((realtype *) v->ops->nvgetarraypointer(v)); +} + +void N_VSetArrayPointer(realtype *v_data, N_Vector v) +{ + v->ops->nvsetarraypointer(v_data, v); + return; +} + +void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z) +{ + z->ops->nvlinearsum(a, x, b, y, z); + return; +} + +void N_VConst(realtype c, N_Vector z) +{ + z->ops->nvconst(c, z); + return; +} + +void N_VProd(N_Vector x, N_Vector y, N_Vector z) +{ + z->ops->nvprod(x, y, z); + return; +} + +void N_VDiv(N_Vector x, N_Vector y, N_Vector z) +{ + z->ops->nvdiv(x, y, z); + return; +} + +void N_VScale(realtype c, N_Vector x, N_Vector z) +{ + z->ops->nvscale(c, x, z); + return; +} + +void N_VAbs(N_Vector x, N_Vector z) +{ + z->ops->nvabs(x, z); + return; +} + +void N_VInv(N_Vector x, N_Vector z) +{ + z->ops->nvinv(x, z); + return; +} + +void N_VAddConst(N_Vector x, realtype b, N_Vector z) +{ + z->ops->nvaddconst(x, b, z); + return; +} + +realtype N_VDotProd(N_Vector x, N_Vector y) +{ + return((realtype) y->ops->nvdotprod(x, y)); +} + +realtype N_VMaxNorm(N_Vector x) +{ + return((realtype) x->ops->nvmaxnorm(x)); +} + +realtype N_VWrmsNorm(N_Vector x, N_Vector w) +{ + return((realtype) x->ops->nvwrmsnorm(x, w)); +} + +realtype N_VWrmsNormMask(N_Vector x, N_Vector w, N_Vector id) +{ + return((realtype) x->ops->nvwrmsnormmask(x, w, id)); +} + +realtype N_VMin(N_Vector x) +{ + return((realtype) x->ops->nvmin(x)); +} + +realtype N_VWL2Norm(N_Vector x, N_Vector w) +{ + return((realtype) x->ops->nvwl2norm(x, w)); +} + +realtype N_VL1Norm(N_Vector x) +{ + return((realtype) x->ops->nvl1norm(x)); +} + +void N_VCompare(realtype c, N_Vector x, N_Vector z) +{ + z->ops->nvcompare(c, x, z); + return; +} + +booleantype N_VInvTest(N_Vector x, N_Vector z) +{ + return((booleantype) z->ops->nvinvtest(x, z)); +} + +booleantype N_VConstrMask(N_Vector c, N_Vector x, N_Vector m) +{ + return((booleantype) x->ops->nvconstrmask(c, x, m)); +} + +realtype N_VMinQuotient(N_Vector num, N_Vector denom) +{ + return((realtype) num->ops->nvminquotient(num, denom)); +} + +/* + * ----------------------------------------------------------------- + * Additional functions exported by the generic NVECTOR: + * N_VCloneEmptyVectorArray + * N_VCloneVectorArray + * N_VDestroyVectorArray + * ----------------------------------------------------------------- + */ + +N_Vector *N_VCloneEmptyVectorArray(int count, N_Vector w) +{ + N_Vector *vs = NULL; + int j; + + if (count <= 0) return(NULL); + + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = N_VCloneEmpty(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +N_Vector *N_VCloneVectorArray(int count, N_Vector w) +{ + N_Vector *vs = NULL; + int j; + + if (count <= 0) return(NULL); + + vs = (N_Vector *) malloc(count * sizeof(N_Vector)); + if(vs == NULL) return(NULL); + + for (j = 0; j < count; j++) { + vs[j] = N_VClone(w); + if (vs[j] == NULL) { + N_VDestroyVectorArray(vs, j-1); + return(NULL); + } + } + + return(vs); +} + +void N_VDestroyVectorArray(N_Vector *vs, int count) +{ + int j; + + if (vs==NULL) return; + + for (j = 0; j < count; j++) N_VDestroy(vs[j]); + + free(vs); vs = NULL; + + return; +} diff --git a/dep/cvode-2.7.0/sundials/sundials_spbcgs.c b/dep/cvode-2.7.0/sundials/sundials_spbcgs.c new file mode 100644 index 00000000..b73bf26b --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_spbcgs.c @@ -0,0 +1,379 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Peter Brown and Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2004, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled, preconditioned + * Bi-CGSTAB (SPBCG) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SpbcgMalloc + * ----------------------------------------------------------------- + */ + +SpbcgMem SpbcgMalloc(int l_max, N_Vector vec_tmpl) +{ + SpbcgMem mem; + N_Vector r_star, r, p, q, u, Ap, vtemp; + + /* Check the input parameters */ + + if (l_max <= 0) return(NULL); + + /* Get arrays to hold temporary vectors */ + + r_star = N_VClone(vec_tmpl); + if (r_star == NULL) { + return(NULL); + } + + r = N_VClone(vec_tmpl); + if (r == NULL) { + N_VDestroy(r_star); + return(NULL); + } + + p = N_VClone(vec_tmpl); + if (p == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + return(NULL); + } + + q = N_VClone(vec_tmpl); + if (q == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + return(NULL); + } + + u = N_VClone(vec_tmpl); + if (u == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + return(NULL); + } + + Ap = N_VClone(vec_tmpl); + if (Ap == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + return(NULL); + } + + vtemp = N_VClone(vec_tmpl); + if (vtemp == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + N_VDestroy(Ap); + return(NULL); + } + + /* Get memory for an SpbcgMemRec containing SPBCG matrices and vectors */ + + mem = NULL; + mem = (SpbcgMem) malloc(sizeof(SpbcgMemRec)); + if (mem == NULL) { + N_VDestroy(r_star); + N_VDestroy(r); + N_VDestroy(p); + N_VDestroy(q); + N_VDestroy(u); + N_VDestroy(Ap); + N_VDestroy(vtemp); + return(NULL); + } + + /* Set the fields of mem */ + + mem->l_max = l_max; + mem->r_star = r_star; + mem->r = r; + mem->p = p; + mem->q = q; + mem->u = u; + mem->Ap = Ap; + mem->vtemp = vtemp; + + /* Return the pointer to SPBCG memory */ + + return(mem); +} + +/* + * ----------------------------------------------------------------- + * Function : SpbcgSolve + * ----------------------------------------------------------------- + */ + +int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps) +{ + realtype alpha, beta, omega, omega_denom, beta_num, beta_denom, r_norm, rho; + N_Vector r_star, r, p, q, u, Ap, vtemp; + booleantype preOnLeft, preOnRight, scale_x, scale_b, converged; + int l, l_max, ier; + + if (mem == NULL) return(SPBCG_MEM_NULL); + + /* Make local copies of mem variables */ + + l_max = mem->l_max; + r_star = mem->r_star; + r = mem->r; + p = mem->p; + q = mem->q; + u = mem->u; + Ap = mem->Ap; + vtemp = mem->vtemp; + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize converged flag */ + + if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT)); + preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT)); + + scale_x = (sx != NULL); + scale_b = (sb != NULL); + + /* Set r_star to initial (unscaled) residual r_0 = b - A*x_0 */ + + if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star); + else { + ier = atimes(A_data, x, r_star); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, r_star, r_star); + } + + /* Apply left preconditioner and b-scaling to r_star = r_0 */ + + if (preOnLeft) { + ier = psolve(P_data, r_star, r, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, r_star, r); + + if (scale_b) N_VProd(sb, r, r_star); + else N_VScale(ONE, r, r_star); + + /* Initialize beta_denom to the dot product of r0 with r0 */ + + beta_denom = N_VDotProd(r_star, r_star); + + /* Set r_norm to L2 norm of r_star = sb P1_inv r_0, and + return if small */ + + *res_norm = r_norm = rho = RSqrt(beta_denom); + if (r_norm <= delta) return(SPBCG_SUCCESS); + + /* Copy r_star to r and p */ + + N_VScale(ONE, r_star, r); + N_VScale(ONE, r_star, p); + + /* Begin main iteration loop */ + + for(l = 0; l < l_max; l++) { + + (*nli)++; + + /* Generate Ap = A-tilde p, where A-tilde = sb P1_inv A P2_inv sx_inv */ + + /* Apply x-scaling: vtemp = sx_inv p */ + + if (scale_x) N_VDiv(p, sx, vtemp); + else N_VScale(ONE, p, vtemp); + + /* Apply right preconditioner: vtemp = P2_inv sx_inv p */ + + if (preOnRight) { + N_VScale(ONE, vtemp, Ap); + ier = psolve(P_data, Ap, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + + /* Apply A: Ap = A P2_inv sx_inv p */ + + ier = atimes(A_data, vtemp, Ap ); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + + /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */ + + if (preOnLeft) { + ier = psolve(P_data, Ap, vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, Ap, vtemp); + + /* Apply b-scaling: Ap = sb P1_inv A P2_inv sx_inv p */ + + if (scale_b) N_VProd(sb, vtemp, Ap); + else N_VScale(ONE, vtemp, Ap); + + + /* Calculate alpha = / */ + + alpha = ((N_VDotProd(r, r_star) / N_VDotProd(Ap, r_star))); + + /* Update q = r - alpha*Ap = r - alpha*(sb P1_inv A P2_inv sx_inv p) */ + + N_VLinearSum(ONE, r, -alpha, Ap, q); + + /* Generate u = A-tilde q */ + + /* Apply x-scaling: vtemp = sx_inv q */ + + if (scale_x) N_VDiv(q, sx, vtemp); + else N_VScale(ONE, q, vtemp); + + /* Apply right preconditioner: vtemp = P2_inv sx_inv q */ + + if (preOnRight) { + N_VScale(ONE, vtemp, u); + ier = psolve(P_data, u, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + + /* Apply A: u = A P2_inv sx_inv u */ + + ier = atimes(A_data, vtemp, u ); + if (ier != 0) + return((ier < 0) ? SPBCG_ATIMES_FAIL_UNREC : SPBCG_ATIMES_FAIL_REC); + + /* Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */ + + if (preOnLeft) { + ier = psolve(P_data, u, vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, u, vtemp); + + /* Apply b-scaling: u = sb P1_inv A P2_inv sx_inv u */ + + if (scale_b) N_VProd(sb, vtemp, u); + else N_VScale(ONE, vtemp, u); + + + /* Calculate omega = / */ + + omega_denom = N_VDotProd(u, u); + if (omega_denom == ZERO) omega_denom = ONE; + omega = (N_VDotProd(u, q) / omega_denom); + + /* Update x = x + alpha*p + omega*q */ + + N_VLinearSum(alpha, p, omega, q, vtemp); + N_VLinearSum(ONE, x, ONE, vtemp, x); + + /* Update the residual r = q - omega*u */ + + N_VLinearSum(ONE, q, -omega, u, r); + + /* Set rho = norm(r) and check convergence */ + + *res_norm = rho = RSqrt(N_VDotProd(r, r)); + if (rho <= delta) { + converged = TRUE; + break; + } + + /* Not yet converged, continue iteration */ + /* Update beta = / * alpha / omega */ + + beta_num = N_VDotProd(r, r_star); + beta = ((beta_num / beta_denom) * (alpha / omega)); + beta_denom = beta_num; + + /* Update p = r + beta*(p - omega*Ap) */ + + N_VLinearSum(ONE, p, -omega, Ap, vtemp); + N_VLinearSum(ONE, r, beta, vtemp, p); + + } + + /* Main loop finished */ + + if ((converged == TRUE) || (rho < r_norm)) { + + /* Apply the x-scaling and right preconditioner: x = P2_inv sx_inv x */ + + if (scale_x) N_VDiv(x, sx, x); + if (preOnRight) { + ier = psolve(P_data, x, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC); + N_VScale(ONE, vtemp, x); + } + + if (converged == TRUE) return(SPBCG_SUCCESS); + else return(SPBCG_RES_REDUCED); + } + else return(SPBCG_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SpbcgFree + * ----------------------------------------------------------------- + */ + +void SpbcgFree(SpbcgMem mem) +{ + + if (mem == NULL) return; + + N_VDestroy(mem->r_star); + N_VDestroy(mem->r); + N_VDestroy(mem->p); + N_VDestroy(mem->q); + N_VDestroy(mem->u); + N_VDestroy(mem->Ap); + N_VDestroy(mem->vtemp); + + free(mem); mem = NULL; +} diff --git a/dep/cvode-2.7.0/sundials/sundials_spgmr.c b/dep/cvode-2.7.0/sundials/sundials_spgmr.c new file mode 100644 index 00000000..7efd1876 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_spgmr.c @@ -0,0 +1,458 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and + * Radu Serban @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2002, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled preconditioned + * GMRES (SPGMR) iterative linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SpgmrMalloc + * ----------------------------------------------------------------- + */ + +SpgmrMem SpgmrMalloc(int l_max, N_Vector vec_tmpl) +{ + SpgmrMem mem; + N_Vector *V, xcor, vtemp; + realtype **Hes, *givens, *yg; + int k, i; + + /* Check the input parameters. */ + + if (l_max <= 0) return(NULL); + + /* Get memory for the Krylov basis vectors V[0], ..., V[l_max]. */ + + V = N_VCloneVectorArray(l_max+1, vec_tmpl); + if (V == NULL) return(NULL); + + /* Get memory for the Hessenberg matrix Hes. */ + + Hes = NULL; + Hes = (realtype **) malloc((l_max+1)*sizeof(realtype *)); + if (Hes == NULL) { + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + for (k = 0; k <= l_max; k++) { + Hes[k] = NULL; + Hes[k] = (realtype *) malloc(l_max*sizeof(realtype)); + if (Hes[k] == NULL) { + for (i = 0; i < k; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + } + + /* Get memory for Givens rotation components. */ + + givens = NULL; + givens = (realtype *) malloc(2*l_max*sizeof(realtype)); + if (givens == NULL) { + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory to hold the correction to z_tilde. */ + + xcor = N_VClone(vec_tmpl); + if (xcor == NULL) { + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory to hold SPGMR y and g vectors. */ + + yg = NULL; + yg = (realtype *) malloc((l_max+1)*sizeof(realtype)); + if (yg == NULL) { + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get an array to hold a temporary vector. */ + + vtemp = N_VClone(vec_tmpl); + if (vtemp == NULL) { + free(yg); yg = NULL; + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Get memory for an SpgmrMemRec containing SPGMR matrices and vectors. */ + + mem = NULL; + mem = (SpgmrMem) malloc(sizeof(SpgmrMemRec)); + if (mem == NULL) { + N_VDestroy(vtemp); + free(yg); yg = NULL; + N_VDestroy(xcor); + free(givens); givens = NULL; + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + N_VDestroyVectorArray(V, l_max+1); + return(NULL); + } + + /* Set the fields of mem. */ + + mem->l_max = l_max; + mem->V = V; + mem->Hes = Hes; + mem->givens = givens; + mem->xcor = xcor; + mem->yg = yg; + mem->vtemp = vtemp; + + /* Return the pointer to SPGMR memory. */ + + return(mem); +} + +/* + * ----------------------------------------------------------------- + * Function : SpgmrSolve + * ----------------------------------------------------------------- + */ + +int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, int gstype, realtype delta, int max_restarts, + void *P_data, N_Vector s1, N_Vector s2, ATimesFn atimes, + PSolveFn psolve, realtype *res_norm, int *nli, int *nps) +{ + N_Vector *V, xcor, vtemp; + realtype **Hes, *givens, *yg; + realtype beta, rotation_product, r_norm, s_product, rho; + booleantype preOnLeft, preOnRight, scale2, scale1, converged; + int i, j, k, l, l_plus_1, l_max, krydim, ier, ntries; + + if (mem == NULL) return(SPGMR_MEM_NULL); + + /* Initialize some variables */ + + l_plus_1 = 0; + krydim = 0; + + /* Make local copies of mem variables. */ + + l_max = mem->l_max; + V = mem->V; + Hes = mem->Hes; + givens = mem->givens; + xcor = mem->xcor; + yg = mem->yg; + vtemp = mem->vtemp; + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize converged flag */ + + if (max_restarts < 0) max_restarts = 0; + + if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) + pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_LEFT) || (pretype == PREC_BOTH)); + preOnRight = ((pretype == PREC_RIGHT) || (pretype == PREC_BOTH)); + scale1 = (s1 != NULL); + scale2 = (s2 != NULL); + + /* Set vtemp and V[0] to initial (unscaled) residual r_0 = b - A*x_0. */ + + if (N_VDotProd(x, x) == ZERO) { + N_VScale(ONE, b, vtemp); + } else { + ier = atimes(A_data, x, vtemp); + if (ier != 0) + return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, vtemp, vtemp); + } + N_VScale(ONE, vtemp, V[0]); + + /* Apply left preconditioner and left scaling to V[0] = r_0. */ + + if (preOnLeft) { + ier = psolve(P_data, V[0], vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, V[0], vtemp); + } + + if (scale1) { + N_VProd(s1, vtemp, V[0]); + } else { + N_VScale(ONE, vtemp, V[0]); + } + + /* Set r_norm = beta to L2 norm of V[0] = s1 P1_inv r_0, and + return if small. */ + + *res_norm = r_norm = beta = RSqrt(N_VDotProd(V[0], V[0])); + if (r_norm <= delta) + return(SPGMR_SUCCESS); + + /* Initialize rho to avoid compiler warning message */ + + rho = beta; + + /* Set xcor = 0. */ + + N_VConst(ZERO, xcor); + + + /* Begin outer iterations: up to (max_restarts + 1) attempts. */ + + for (ntries = 0; ntries <= max_restarts; ntries++) { + + /* Initialize the Hessenberg matrix Hes and Givens rotation + product. Normalize the initial vector V[0]. */ + + for (i = 0; i <= l_max; i++) + for (j = 0; j < l_max; j++) + Hes[i][j] = ZERO; + + rotation_product = ONE; + + N_VScale(ONE/r_norm, V[0], V[0]); + + /* Inner loop: generate Krylov sequence and Arnoldi basis. */ + + for (l = 0; l < l_max; l++) { + + (*nli)++; + + krydim = l_plus_1 = l + 1; + + /* Generate A-tilde V[l], where A-tilde = s1 P1_inv A P2_inv s2_inv. */ + + /* Apply right scaling: vtemp = s2_inv V[l]. */ + + if (scale2) N_VDiv(V[l], s2, vtemp); + else N_VScale(ONE, V[l], vtemp); + + /* Apply right preconditioner: vtemp = P2_inv s2_inv V[l]. */ + + if (preOnRight) { + N_VScale(ONE, vtemp, V[l_plus_1]); + ier = psolve(P_data, V[l_plus_1], vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } + + /* Apply A: V[l+1] = A P2_inv s2_inv V[l]. */ + + ier = atimes(A_data, vtemp, V[l_plus_1] ); + if (ier != 0) + return((ier < 0) ? SPGMR_ATIMES_FAIL_UNREC : SPGMR_ATIMES_FAIL_REC); + + /* Apply left preconditioning: vtemp = P1_inv A P2_inv s2_inv V[l]. */ + + if (preOnLeft) { + ier = psolve(P_data, V[l_plus_1], vtemp, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, V[l_plus_1], vtemp); + } + + /* Apply left scaling: V[l+1] = s1 P1_inv A P2_inv s2_inv V[l]. */ + + if (scale1) { + N_VProd(s1, vtemp, V[l_plus_1]); + } else { + N_VScale(ONE, vtemp, V[l_plus_1]); + } + + /* Orthogonalize V[l+1] against previous V[i]: V[l+1] = w_tilde. */ + + if (gstype == CLASSICAL_GS) { + if (ClassicalGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l]), + vtemp, yg) != 0) + return(SPGMR_GS_FAIL); + } else { + if (ModifiedGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l])) != 0) + return(SPGMR_GS_FAIL); + } + + /* Update the QR factorization of Hes. */ + + if(QRfact(krydim, Hes, givens, l) != 0 ) + return(SPGMR_QRFACT_FAIL); + + /* Update residual norm estimate; break if convergence test passes. */ + + rotation_product *= givens[2*l+1]; + *res_norm = rho = ABS(rotation_product*r_norm); + + if (rho <= delta) { converged = TRUE; break; } + + /* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */ + + N_VScale(ONE/Hes[l_plus_1][l], V[l_plus_1], V[l_plus_1]); + } + + /* Inner loop is done. Compute the new correction vector xcor. */ + + /* Construct g, then solve for y. */ + + yg[0] = r_norm; + for (i = 1; i <= krydim; i++) yg[i]=ZERO; + if (QRsol(krydim, Hes, givens, yg) != 0) + return(SPGMR_QRSOL_FAIL); + + /* Add correction vector V_l y to xcor. */ + + for (k = 0; k < krydim; k++) + N_VLinearSum(yg[k], V[k], ONE, xcor, xcor); + + /* If converged, construct the final solution vector x and return. */ + + if (converged) { + + /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */ + + if (scale2) N_VDiv(xcor, s2, xcor); + if (preOnRight) { + ier = psolve(P_data, xcor, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, xcor, vtemp); + } + + /* Add vtemp to initial x to get final solution x, and return */ + + N_VLinearSum(ONE, x, ONE, vtemp, x); + + return(SPGMR_SUCCESS); + } + + /* Not yet converged; if allowed, prepare for restart. */ + + if (ntries == max_restarts) break; + + /* Construct last column of Q in yg. */ + + s_product = ONE; + for (i = krydim; i > 0; i--) { + yg[i] = s_product*givens[2*i-2]; + s_product *= givens[2*i-1]; + } + yg[0] = s_product; + + /* Scale r_norm and yg. */ + r_norm *= s_product; + for (i = 0; i <= krydim; i++) + yg[i] *= r_norm; + r_norm = ABS(r_norm); + + /* Multiply yg by V_(krydim+1) to get last residual vector; restart. */ + N_VScale(yg[0], V[0], V[0]); + for (k = 1; k <= krydim; k++) + N_VLinearSum(yg[k], V[k], ONE, V[0], V[0]); + + } + + /* Failed to converge, even after allowed restarts. + If the residual norm was reduced below its initial value, compute + and return x anyway. Otherwise return failure flag. */ + + if (rho < beta) { + + /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor. */ + + if (scale2) N_VDiv(xcor, s2, xcor); + if (preOnRight) { + ier = psolve(P_data, xcor, vtemp, PREC_RIGHT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC); + } else { + N_VScale(ONE, xcor, vtemp); + } + + /* Add vtemp to initial x to get final solution x, and return. */ + + N_VLinearSum(ONE, x, ONE, vtemp, x); + + return(SPGMR_RES_REDUCED); + } + + return(SPGMR_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SpgmrFree + * ----------------------------------------------------------------- + */ + +void SpgmrFree(SpgmrMem mem) +{ + int i, l_max; + realtype **Hes, *givens, *yg; + + if (mem == NULL) return; + + l_max = mem->l_max; + Hes = mem->Hes; + givens = mem->givens; + yg = mem->yg; + + for (i = 0; i <= l_max; i++) {free(Hes[i]); Hes[i] = NULL;} + free(Hes); Hes = NULL; + free(mem->givens); givens = NULL; + free(mem->yg); yg = NULL; + + N_VDestroyVectorArray(mem->V, l_max+1); + N_VDestroy(mem->xcor); + N_VDestroy(mem->vtemp); + + free(mem); mem = NULL; +} diff --git a/dep/cvode-2.7.0/sundials/sundials_sptfqmr.c b/dep/cvode-2.7.0/sundials/sundials_sptfqmr.c new file mode 100644 index 00000000..626ca006 --- /dev/null +++ b/dep/cvode-2.7.0/sundials/sundials_sptfqmr.c @@ -0,0 +1,516 @@ +/* + * ----------------------------------------------------------------- + * $Revision: 1.2 $ + * $Date: 2007/04/06 20:33:30 $ + * ----------------------------------------------------------------- + * Programmer(s): Aaron Collier @ LLNL + * ----------------------------------------------------------------- + * Copyright (c) 2005, The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * All rights reserved. + * For details, see the LICENSE file. + * ----------------------------------------------------------------- + * This is the implementation file for the scaled preconditioned + * Transpose-Free Quasi-Minimal Residual (SPTFQMR) linear solver. + * ----------------------------------------------------------------- + */ + +#include +#include + +#include +#include + +/* + * ----------------------------------------------------------------- + * private constants + * ----------------------------------------------------------------- + */ + +#define ZERO RCONST(0.0) +#define ONE RCONST(1.0) + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrMalloc + * ----------------------------------------------------------------- + */ + +SptfqmrMem SptfqmrMalloc(int l_max, N_Vector vec_tmpl) +{ + SptfqmrMem mem; + N_Vector *r; + N_Vector q, d, v, p, u; + N_Vector r_star, vtemp1, vtemp2, vtemp3; + + /* Check the input parameters */ + if ((l_max <= 0) || (vec_tmpl == NULL)) return(NULL); + + /* Allocate space for vectors */ + + r_star = N_VClone(vec_tmpl); + if (r_star == NULL) return(NULL); + + q = N_VClone(vec_tmpl); + if (q == NULL) { + N_VDestroy(r_star); + return(NULL); + } + + d = N_VClone(vec_tmpl); + if (d == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + return(NULL); + } + + v = N_VClone(vec_tmpl); + if (v == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + return(NULL); + } + + p = N_VClone(vec_tmpl); + if (p == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + return(NULL); + } + + r = N_VCloneVectorArray(2, vec_tmpl); + if (r == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + return(NULL); + } + + u = N_VClone(vec_tmpl); + if (u == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + return(NULL); + } + + vtemp1 = N_VClone(vec_tmpl); + if (vtemp1 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + return(NULL); + } + + vtemp2 = N_VClone(vec_tmpl); + if (vtemp2 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + return(NULL); + } + + vtemp3 = N_VClone(vec_tmpl); + if (vtemp3 == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + return(NULL); + } + + /* Allocate memory for SptfqmrMemRec */ + mem = NULL; + mem = (SptfqmrMem) malloc(sizeof(SptfqmrMemRec)); + if (mem == NULL) { + N_VDestroy(r_star); + N_VDestroy(q); + N_VDestroy(d); + N_VDestroy(v); + N_VDestroy(p); + N_VDestroyVectorArray(r, 2); + N_VDestroy(u); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + N_VDestroy(vtemp3); + return(NULL); + } + + /* Intialize SptfqmrMemRec data structure */ + mem->l_max = l_max; + mem->r_star = r_star; + mem->q = q; + mem->d = d; + mem->v = v; + mem->p = p; + mem->r = r; + mem->u = u; + mem->vtemp1 = vtemp1; + mem->vtemp2 = vtemp2; + mem->vtemp3 = vtemp3; + + /* Return pointer to SPTFQMR memory block */ + return(mem); +} + +#define l_max (mem->l_max) +#define r_star (mem->r_star) +#define q_ (mem->q) +#define d_ (mem->d) +#define v_ (mem->v) +#define p_ (mem->p) +#define r_ (mem->r) +#define u_ (mem->u) +#define vtemp1 (mem->vtemp1) +#define vtemp2 (mem->vtemp2) +#define vtemp3 (mem->vtemp3) + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrSolve + * ----------------------------------------------------------------- + */ + +int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b, + int pretype, realtype delta, void *P_data, N_Vector sx, + N_Vector sb, ATimesFn atimes, PSolveFn psolve, + realtype *res_norm, int *nli, int *nps) +{ + realtype alpha, tau, eta, beta, c, sigma, v_bar, omega; + realtype rho[2]; + realtype r_init_norm, r_curr_norm; + realtype temp_val; + booleantype preOnLeft, preOnRight, scale_x, scale_b, converged; + booleantype b_ok; + int n, m, ier; + + /* Exit immediately if memory pointer is NULL */ + if (mem == NULL) return(SPTFQMR_MEM_NULL); + + temp_val = r_curr_norm = -ONE; /* Initialize to avoid compiler warnings */ + + *nli = *nps = 0; /* Initialize counters */ + converged = FALSE; /* Initialize convergence flag */ + b_ok = FALSE; + + if ((pretype != PREC_LEFT) && + (pretype != PREC_RIGHT) && + (pretype != PREC_BOTH)) pretype = PREC_NONE; + + preOnLeft = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT)); + preOnRight = ((pretype == PREC_BOTH) || (pretype == PREC_RIGHT)); + + scale_x = (sx != NULL); + scale_b = (sb != NULL); + + /* Set r_star to initial (unscaled) residual r_star = r_0 = b - A*x_0 */ + /* NOTE: if x == 0 then just set residual to b and continue */ + if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star); + else { + ier = atimes(A_data, x, r_star); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + N_VLinearSum(ONE, b, -ONE, r_star, r_star); + } + + /* Apply left preconditioner and b-scaling to r_star (or really just r_0) */ + if (preOnLeft) { + ier = psolve(P_data, r_star, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) + return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, r_star, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, r_star); + else N_VScale(ONE, vtemp1, r_star); + + /* Initialize rho[0] */ + /* NOTE: initialized here to reduce number of computations - avoid need + to compute r_star^T*r_star twice, and avoid needlessly squaring + values */ + rho[0] = N_VDotProd(r_star, r_star); + + /* Compute norm of initial residual (r_0) to see if we really need + to do anything */ + *res_norm = r_init_norm = RSqrt(rho[0]); + if (r_init_norm <= delta) return(SPTFQMR_SUCCESS); + + /* Set v_ = A*r_0 (preconditioned and scaled) */ + if (scale_x) N_VDiv(r_star, sx, vtemp1); + else N_VScale(ONE, r_star, vtemp1); + if (preOnRight) { + N_VScale(ONE, vtemp1, v_); + ier = psolve(P_data, v_, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, vtemp1, v_); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, v_, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, v_, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, v_); + else N_VScale(ONE, vtemp1, v_); + + /* Initialize remaining variables */ + N_VScale(ONE, r_star, r_[0]); + N_VScale(ONE, r_star, u_); + N_VScale(ONE, r_star, p_); + N_VConst(ZERO, d_); + + tau = r_init_norm; + v_bar = eta = ZERO; + + /* START outer loop */ + for (n = 0; n < l_max; ++n) { + + /* Increment linear iteration counter */ + (*nli)++; + + /* sigma = r_star^T*v_ */ + sigma = N_VDotProd(r_star, v_); + + /* alpha = rho[0]/sigma */ + alpha = rho[0]/sigma; + + /* q_ = u_-alpha*v_ */ + N_VLinearSum(ONE, u_, -alpha, v_, q_); + + /* r_[1] = r_[0]-alpha*A*(u_+q_) */ + N_VLinearSum(ONE, u_, ONE, q_, r_[1]); + if (scale_x) N_VDiv(r_[1], sx, r_[1]); + if (preOnRight) { + N_VScale(ONE, r_[1], vtemp1); + ier = psolve(P_data, vtemp1, r_[1], PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, r_[1], vtemp1); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, vtemp1, r_[1], PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, vtemp1, r_[1]); + if (scale_b) N_VProd(sb, r_[1], vtemp1); + else N_VScale(ONE, r_[1], vtemp1); + N_VLinearSum(ONE, r_[0], -alpha, vtemp1, r_[1]); + + /* START inner loop */ + for (m = 0; m < 2; ++m) { + + /* d_ = [*]+(v_bar^2*eta/alpha)*d_ */ + /* NOTES: + * (1) [*] = u_ if m == 0, and q_ if m == 1 + * (2) using temp_val reduces the number of required computations + * if the inner loop is executed twice + */ + if (m == 0) { + temp_val = RSqrt(N_VDotProd(r_[1], r_[1])); + omega = RSqrt(RSqrt(N_VDotProd(r_[0], r_[0]))*temp_val); + N_VLinearSum(ONE, u_, SQR(v_bar)*eta/alpha, d_, d_); + } + else { + omega = temp_val; + N_VLinearSum(ONE, q_, SQR(v_bar)*eta/alpha, d_, d_); + } + + /* v_bar = omega/tau */ + v_bar = omega/tau; + + /* c = (1+v_bar^2)^(-1/2) */ + c = ONE / RSqrt(ONE+SQR(v_bar)); + + /* tau = tau*v_bar*c */ + tau = tau*v_bar*c; + + /* eta = c^2*alpha */ + eta = SQR(c)*alpha; + + /* x = x+eta*d_ */ + N_VLinearSum(ONE, x, eta, d_, x); + + /* Check for convergence... */ + /* NOTE: just use approximation to norm of residual, if possible */ + *res_norm = r_curr_norm = tau*RSqrt(m+1); + + /* Exit inner loop if iteration has converged based upon approximation + to norm of current residual */ + if (r_curr_norm <= delta) { + converged = TRUE; + break; + } + + /* Decide if actual norm of residual vector should be computed */ + /* NOTES: + * (1) if r_curr_norm > delta, then check if actual residual norm + * is OK (recall we first compute an approximation) + * (2) if r_curr_norm >= r_init_norm and m == 1 and n == l_max, then + * compute actual residual norm to see if the iteration can be + * saved + * (3) the scaled and preconditioned right-hand side of the given + * linear system (denoted by b) is only computed once, and the + * result is stored in vtemp3 so it can be reused - reduces the + * number of psovles if using left preconditioning + */ + if ((r_curr_norm > delta) || + (r_curr_norm >= r_init_norm && m == 1 && n == l_max)) { + + /* Compute norm of residual ||b-A*x||_2 (preconditioned and scaled) */ + if (scale_x) N_VDiv(x, sx, vtemp1); + else N_VScale(ONE, x, vtemp1); + if (preOnRight) { + ier = psolve(P_data, vtemp1, vtemp2, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC); + N_VScale(ONE, vtemp2, vtemp1); + } + ier = atimes(A_data, vtemp1, vtemp2); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, vtemp2, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, vtemp2, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, vtemp2); + else N_VScale(ONE, vtemp1, vtemp2); + /* Only precondition and scale b once (result saved for reuse) */ + if (!b_ok) { + b_ok = TRUE; + if (preOnLeft) { + ier = psolve(P_data, b, vtemp3, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, b, vtemp3); + if (scale_b) N_VProd(sb, vtemp3, vtemp3); + } + N_VLinearSum(ONE, vtemp3, -ONE, vtemp2, vtemp1); + *res_norm = r_curr_norm = RSqrt(N_VDotProd(vtemp1, vtemp1)); + + /* Exit inner loop if inequality condition is satisfied + (meaning exit if we have converged) */ + if (r_curr_norm <= delta) { + converged = TRUE; + break; + } + + } + + } /* END inner loop */ + + /* If converged, then exit outer loop as well */ + if (converged == TRUE) break; + + /* rho[1] = r_star^T*r_[1] */ + rho[1] = N_VDotProd(r_star, r_[1]); + + /* beta = rho[1]/rho[0] */ + beta = rho[1]/rho[0]; + + /* u_ = r_[1]+beta*q_ */ + N_VLinearSum(ONE, r_[1], beta, q_, u_); + + /* p_ = u_+beta*(q_+beta*p_) */ + N_VLinearSum(beta, q_, SQR(beta), p_, p_); + N_VLinearSum(ONE, u_, ONE, p_, p_); + + /* v_ = A*p_ */ + if (scale_x) N_VDiv(p_, sx, vtemp1); + else N_VScale(ONE, p_, vtemp1); + if (preOnRight) { + N_VScale(ONE, vtemp1, v_); + ier = psolve(P_data, v_, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + ier = atimes(A_data, vtemp1, v_); + if (ier != 0) + return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC); + if (preOnLeft) { + ier = psolve(P_data, v_, vtemp1, PREC_LEFT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC); + } + else N_VScale(ONE, v_, vtemp1); + if (scale_b) N_VProd(sb, vtemp1, v_); + else N_VScale(ONE, vtemp1, v_); + + /* Shift variable values */ + /* NOTE: reduces storage requirements */ + N_VScale(ONE, r_[1], r_[0]); + rho[0] = rho[1]; + + } /* END outer loop */ + + /* Determine return value */ + /* If iteration converged or residual was reduced, then return current iterate (x) */ + if ((converged == TRUE) || (r_curr_norm < r_init_norm)) { + if (scale_x) N_VDiv(x, sx, x); + if (preOnRight) { + ier = psolve(P_data, x, vtemp1, PREC_RIGHT); + (*nps)++; + if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC); + N_VScale(ONE, vtemp1, x); + } + if (converged == TRUE) return(SPTFQMR_SUCCESS); + else return(SPTFQMR_RES_REDUCED); + } + /* Otherwise, return error code */ + else return(SPTFQMR_CONV_FAIL); +} + +/* + * ----------------------------------------------------------------- + * Function : SptfqmrFree + * ----------------------------------------------------------------- + */ + +void SptfqmrFree(SptfqmrMem mem) +{ + + if (mem == NULL) return; + + N_VDestroy(r_star); + N_VDestroy(q_); + N_VDestroy(d_); + N_VDestroy(v_); + N_VDestroy(p_); + N_VDestroyVectorArray(r_, 2); + N_VDestroy(u_); + N_VDestroy(vtemp1); + N_VDestroy(vtemp2); + N_VDestroy(vtemp3); + + free(mem); mem = NULL; +} diff --git a/dep/dsfmt/CMakeLists.txt b/dep/dsfmt/CMakeLists.txt new file mode 100644 index 00000000..189067d7 --- /dev/null +++ b/dep/dsfmt/CMakeLists.txt @@ -0,0 +1,24 @@ + +add_library(depdsfmt dSFMT.c dSFMT_h.c dsfmt_add.c) + +INSTALL(TARGETS depdsfmt DESTINATION lib) + +# Install the header files +SET(dsfmt_HEADERS + dSFMT-params.h + dSFMT-params11213.h + dSFMT-params1279.h + dSFMT-params132049.h + dSFMT-params19937.h + dSFMT-params216091.h + dSFMT-params2203.h + dSFMT-params4253.h + dSFMT-params44497.h + dSFMT-params521.h + dSFMT-params86243.h + dSFMT.h + dsfmt_add.h + ) + +INSTALL(FILES ${dsfmt_HEADERS} DESTINATION include/dep) + diff --git a/dep/dsfmt/LICENSE b/dep/dsfmt/LICENSE new file mode 100644 index 00000000..6f9c4a6d --- /dev/null +++ b/dep/dsfmt/LICENSE @@ -0,0 +1,32 @@ +Copyright (c) 2006,2007 Mutsuo Saito, Makoto Matsumoto and Hiroshima +University. +Copyright (c) 2012 Mutsuo Saito, Makoto Matsumoto, Hiroshima University +and The University of Tokyo. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the names of Hiroshima University, The University of + Tokyo nor the names of its contributors may be used to endorse + or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dep/dsfmt/README b/dep/dsfmt/README new file mode 100644 index 00000000..77c76bc8 --- /dev/null +++ b/dep/dsfmt/README @@ -0,0 +1,12 @@ +SIMD-oriented Fast Mersenne Twister (SFMT) random number library downloaded from: + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/ + +Note: the include file dSFMT.h has been customized for the UQTk toolkit usage. See the comments + at the top of this header file. + +March 6, 2011 (Cosmin) : + - March 2011: using current version 2.1 + - dsfmt_add.c is a wrapper to generate single values for normal (using Box-Muller + transform) and uniform random variables + - compiled with DSFMT_MEXP=216091 which means the period for the random number + generator is 2^216091-1 diff --git a/dep/dsfmt/dSFMT-params.h b/dep/dsfmt/dSFMT-params.h new file mode 100644 index 00000000..825148e6 --- /dev/null +++ b/dep/dsfmt/dSFMT-params.h @@ -0,0 +1,87 @@ +#ifndef DSFMT_PARAMS_H +#define DSFMT_PARAMS_H + +#include "dSFMT.h" + +/*---------------------- + the parameters of DSFMT + following definitions are in dSFMT-paramsXXXX.h file. + ----------------------*/ +/** the pick up position of the array. +#define DSFMT_POS1 122 +*/ + +/** the parameter of shift left as four 32-bit registers. +#define DSFMT_SL1 18 + */ + +/** the parameter of shift right as four 32-bit registers. +#define DSFMT_SR1 12 +*/ + +/** A bitmask, used in the recursion. These parameters are introduced + * to break symmetry of SIMD. +#define DSFMT_MSK1 (uint64_t)0xdfffffefULL +#define DSFMT_MSK2 (uint64_t)0xddfecb7fULL +*/ + +/** These definitions are part of a 128-bit period certification vector. +#define DSFMT_PCV1 UINT64_C(0x00000001) +#define DSFMT_PCV2 UINT64_C(0x00000000) +*/ + +#define DSFMT_LOW_MASK UINT64_C(0x000FFFFFFFFFFFFF) +#define DSFMT_HIGH_CONST UINT64_C(0x3FF0000000000000) +#define DSFMT_SR 12 + +/* for sse2 */ +#if defined(HAVE_SSE2) + #define SSE2_SHUFF 0x1b +#elif defined(HAVE_ALTIVEC) + #if defined(__APPLE__) /* For OSX */ + #define ALTI_SR (vector unsigned char)(4) + #define ALTI_SR_PERM \ + (vector unsigned char)(15,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14) + #define ALTI_SR_MSK \ + (vector unsigned int)(0x000fffffU,0xffffffffU,0x000fffffU,0xffffffffU) + #define ALTI_PERM \ + (vector unsigned char)(12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3) + #else + #define ALTI_SR {4} + #define ALTI_SR_PERM {15,0,1,2,3,4,5,6,15,8,9,10,11,12,13,14} + #define ALTI_SR_MSK {0x000fffffU,0xffffffffU,0x000fffffU,0xffffffffU} + #define ALTI_PERM {12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3} + #endif +#endif + +#if DSFMT_MEXP == 521 + #include "dSFMT-params521.h" +#elif DSFMT_MEXP == 1279 + #include "dSFMT-params1279.h" +#elif DSFMT_MEXP == 2203 + #include "dSFMT-params2203.h" +#elif DSFMT_MEXP == 4253 + #include "dSFMT-params4253.h" +#elif DSFMT_MEXP == 11213 + #include "dSFMT-params11213.h" +#elif DSFMT_MEXP == 19937 + #include "dSFMT-params19937.h" +#elif DSFMT_MEXP == 44497 + #include "dSFMT-params44497.h" +#elif DSFMT_MEXP == 86243 + #include "dSFMT-params86243.h" +#elif DSFMT_MEXP == 132049 + #include "dSFMT-params132049.h" +#elif DSFMT_MEXP == 216091 + #include "dSFMT-params216091.h" +#else +#ifdef __GNUC__ + #error "DSFMT_MEXP is not valid." + #undef DSFMT_MEXP +#else + #undef DSFMT_MEXP +#endif + +#endif + +#endif /* DSFMT_PARAMS_H */ diff --git a/dep/dsfmt/dSFMT-params11213.h b/dep/dsfmt/dSFMT-params11213.h new file mode 100644 index 00000000..d89b5a7b --- /dev/null +++ b/dep/dsfmt/dSFMT-params11213.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS11213_H +#define DSFMT_PARAMS11213_H + +/* #define DSFMT_N 107 */ +/* #define DSFMT_MAXDEGREE 11256 */ +#define DSFMT_POS1 37 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x000ffffffdf7fffd) +#define DSFMT_MSK2 UINT64_C(0x000dfffffff6bfff) +#define DSFMT_MSK32_1 0x000fffffU +#define DSFMT_MSK32_2 0xfdf7fffdU +#define DSFMT_MSK32_3 0x000dffffU +#define DSFMT_MSK32_4 0xfff6bfffU +#define DSFMT_FIX1 UINT64_C(0xd0ef7b7c75b06793) +#define DSFMT_FIX2 UINT64_C(0x9c50ff4caae0a641) +#define DSFMT_PCV1 UINT64_C(0x8234c51207c80000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-11213:37-19:ffffffdf7fffd-dfffffff6bfff" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(3, 3, 3, 3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3, 3, 3, 3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS11213_H */ diff --git a/dep/dsfmt/dSFMT-params1279.h b/dep/dsfmt/dSFMT-params1279.h new file mode 100644 index 00000000..3ed40774 --- /dev/null +++ b/dep/dsfmt/dSFMT-params1279.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS1279_H +#define DSFMT_PARAMS1279_H + +/* #define DSFMT_N 12 */ +/* #define DSFMT_MAXDEGREE 1376 */ +#define DSFMT_POS1 9 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x000efff7ffddffee) +#define DSFMT_MSK2 UINT64_C(0x000fbffffff77fff) +#define DSFMT_MSK32_1 0x000efff7U +#define DSFMT_MSK32_2 0xffddffeeU +#define DSFMT_MSK32_3 0x000fbfffU +#define DSFMT_MSK32_4 0xfff77fffU +#define DSFMT_FIX1 UINT64_C(0xb66627623d1a31be) +#define DSFMT_FIX2 UINT64_C(0x04b6c51147b6109b) +#define DSFMT_PCV1 UINT64_C(0x7049f2da382a6aeb) +#define DSFMT_PCV2 UINT64_C(0xde4ca84a40000001) +#define DSFMT_IDSTR "dSFMT2-1279:9-19:efff7ffddffee-fbffffff77fff" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(3, 3, 3, 3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3, 3, 3, 3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS1279_H */ diff --git a/dep/dsfmt/dSFMT-params132049.h b/dep/dsfmt/dSFMT-params132049.h new file mode 100644 index 00000000..faaced7b --- /dev/null +++ b/dep/dsfmt/dSFMT-params132049.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS132049_H +#define DSFMT_PARAMS132049_H + +/* #define DSFMT_N 1269 */ +/* #define DSFMT_MAXDEGREE 132104 */ +#define DSFMT_POS1 371 +#define DSFMT_SL1 23 +#define DSFMT_MSK1 UINT64_C(0x000fb9f4eff4bf77) +#define DSFMT_MSK2 UINT64_C(0x000fffffbfefff37) +#define DSFMT_MSK32_1 0x000fb9f4U +#define DSFMT_MSK32_2 0xeff4bf77U +#define DSFMT_MSK32_3 0x000fffffU +#define DSFMT_MSK32_4 0xbfefff37U +#define DSFMT_FIX1 UINT64_C(0x4ce24c0e4e234f3b) +#define DSFMT_FIX2 UINT64_C(0x62612409b5665c2d) +#define DSFMT_PCV1 UINT64_C(0x181232889145d000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-132049:371-23:fb9f4eff4bf77-fffffbfefff37" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(7, 7, 7, 7) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xff800000U,0xffffffffU,0xff800000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {7, 7, 7, 7} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xff800000U,0xffffffffU,0xff800000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS132049_H */ diff --git a/dep/dsfmt/dSFMT-params19937.h b/dep/dsfmt/dSFMT-params19937.h new file mode 100644 index 00000000..7f018466 --- /dev/null +++ b/dep/dsfmt/dSFMT-params19937.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS19937_H +#define DSFMT_PARAMS19937_H + +/* #define DSFMT_N 191 */ +/* #define DSFMT_MAXDEGREE 19992 */ +#define DSFMT_POS1 117 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x000ffafffffffb3f) +#define DSFMT_MSK2 UINT64_C(0x000ffdfffc90fffd) +#define DSFMT_MSK32_1 0x000ffaffU +#define DSFMT_MSK32_2 0xfffffb3fU +#define DSFMT_MSK32_3 0x000ffdffU +#define DSFMT_MSK32_4 0xfc90fffdU +#define DSFMT_FIX1 UINT64_C(0x90014964b32f4329) +#define DSFMT_FIX2 UINT64_C(0x3b8d12ac548a7c7a) +#define DSFMT_PCV1 UINT64_C(0x3d84e1ac0dc82880) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-19937:117-19:ffafffffffb3f-ffdfffc90fffd" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(3, 3, 3, 3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3, 3, 3, 3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS19937_H */ diff --git a/dep/dsfmt/dSFMT-params216091.h b/dep/dsfmt/dSFMT-params216091.h new file mode 100644 index 00000000..8693c7c2 --- /dev/null +++ b/dep/dsfmt/dSFMT-params216091.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS216091_H +#define DSFMT_PARAMS216091_H + +/* #define DSFMT_N 2077 */ +/* #define DSFMT_MAXDEGREE 216136 */ +#define DSFMT_POS1 1890 +#define DSFMT_SL1 23 +#define DSFMT_MSK1 UINT64_C(0x000bf7df7fefcfff) +#define DSFMT_MSK2 UINT64_C(0x000e7ffffef737ff) +#define DSFMT_MSK32_1 0x000bf7dfU +#define DSFMT_MSK32_2 0x7fefcfffU +#define DSFMT_MSK32_3 0x000e7fffU +#define DSFMT_MSK32_4 0xfef737ffU +#define DSFMT_FIX1 UINT64_C(0xd7f95a04764c27d7) +#define DSFMT_FIX2 UINT64_C(0x6a483861810bebc2) +#define DSFMT_PCV1 UINT64_C(0x3af0a8f3d5600000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-216091:1890-23:bf7df7fefcfff-e7ffffef737ff" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(7, 7, 7, 7) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xff800000U,0xffffffffU,0xff800000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {7, 7, 7, 7} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xff800000U,0xffffffffU,0xff800000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS216091_H */ diff --git a/dep/dsfmt/dSFMT-params2203.h b/dep/dsfmt/dSFMT-params2203.h new file mode 100644 index 00000000..e63c4ffd --- /dev/null +++ b/dep/dsfmt/dSFMT-params2203.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS2203_H +#define DSFMT_PARAMS2203_H + +/* #define DSFMT_N 20 */ +/* #define DSFMT_MAXDEGREE 2208 */ +#define DSFMT_POS1 7 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x000fdffff5edbfff) +#define DSFMT_MSK2 UINT64_C(0x000f77fffffffbfe) +#define DSFMT_MSK32_1 0x000fdfffU +#define DSFMT_MSK32_2 0xf5edbfffU +#define DSFMT_MSK32_3 0x000f77ffU +#define DSFMT_MSK32_4 0xfffffbfeU +#define DSFMT_FIX1 UINT64_C(0xb14e907a39338485) +#define DSFMT_FIX2 UINT64_C(0xf98f0735c637ef90) +#define DSFMT_PCV1 UINT64_C(0x8000000000000000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-2203:7-19:fdffff5edbfff-f77fffffffbfe" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(3, 3, 3, 3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3, 3, 3, 3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS2203_H */ diff --git a/dep/dsfmt/dSFMT-params4253.h b/dep/dsfmt/dSFMT-params4253.h new file mode 100644 index 00000000..d7960af4 --- /dev/null +++ b/dep/dsfmt/dSFMT-params4253.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS4253_H +#define DSFMT_PARAMS4253_H + +/* #define DSFMT_N 40 */ +/* #define DSFMT_MAXDEGREE 4288 */ +#define DSFMT_POS1 19 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x0007b7fffef5feff) +#define DSFMT_MSK2 UINT64_C(0x000ffdffeffefbfc) +#define DSFMT_MSK32_1 0x0007b7ffU +#define DSFMT_MSK32_2 0xfef5feffU +#define DSFMT_MSK32_3 0x000ffdffU +#define DSFMT_MSK32_4 0xeffefbfcU +#define DSFMT_FIX1 UINT64_C(0x80901b5fd7a11c65) +#define DSFMT_FIX2 UINT64_C(0x5a63ff0e7cb0ba74) +#define DSFMT_PCV1 UINT64_C(0x1ad277be12000000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-4253:19-19:7b7fffef5feff-ffdffeffefbfc" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(3, 3, 3, 3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3, 3, 3, 3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS4253_H */ diff --git a/dep/dsfmt/dSFMT-params44497.h b/dep/dsfmt/dSFMT-params44497.h new file mode 100644 index 00000000..39f358c2 --- /dev/null +++ b/dep/dsfmt/dSFMT-params44497.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS44497_H +#define DSFMT_PARAMS44497_H + +/* #define DSFMT_N 427 */ +/* #define DSFMT_MAXDEGREE 44536 */ +#define DSFMT_POS1 304 +#define DSFMT_SL1 19 +#define DSFMT_MSK1 UINT64_C(0x000ff6dfffffffef) +#define DSFMT_MSK2 UINT64_C(0x0007ffdddeefff6f) +#define DSFMT_MSK32_1 0x000ff6dfU +#define DSFMT_MSK32_2 0xffffffefU +#define DSFMT_MSK32_3 0x0007ffddU +#define DSFMT_MSK32_4 0xdeefff6fU +#define DSFMT_FIX1 UINT64_C(0x75d910f235f6e10e) +#define DSFMT_FIX2 UINT64_C(0x7b32158aedc8e969) +#define DSFMT_PCV1 UINT64_C(0x4c3356b2a0000000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-44497:304-19:ff6dfffffffef-7ffdddeefff6f" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(3, 3, 3, 3) + #define ALTI_SL1_PERM \ + (vector unsigned char)(2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {3, 3, 3, 3} + #define ALTI_SL1_PERM \ + {2,3,4,5,6,7,30,30,10,11,12,13,14,15,0,1} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfff80000U,0xffffffffU,0xfff80000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS44497_H */ diff --git a/dep/dsfmt/dSFMT-params521.h b/dep/dsfmt/dSFMT-params521.h new file mode 100644 index 00000000..f771dc19 --- /dev/null +++ b/dep/dsfmt/dSFMT-params521.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS521_H +#define DSFMT_PARAMS521_H + +/* #define DSFMT_N 4 */ +/* #define DSFMT_MAXDEGREE 544 */ +#define DSFMT_POS1 3 +#define DSFMT_SL1 25 +#define DSFMT_MSK1 UINT64_C(0x000fbfefff77efff) +#define DSFMT_MSK2 UINT64_C(0x000ffeebfbdfbfdf) +#define DSFMT_MSK32_1 0x000fbfefU +#define DSFMT_MSK32_2 0xff77efffU +#define DSFMT_MSK32_3 0x000ffeebU +#define DSFMT_MSK32_4 0xfbdfbfdfU +#define DSFMT_FIX1 UINT64_C(0xcfb393d661638469) +#define DSFMT_FIX2 UINT64_C(0xc166867883ae2adb) +#define DSFMT_PCV1 UINT64_C(0xccaa588000000000) +#define DSFMT_PCV2 UINT64_C(0x0000000000000001) +#define DSFMT_IDSTR "dSFMT2-521:3-25:fbfefff77efff-ffeebfbdfbfdf" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(1, 1, 1, 1) + #define ALTI_SL1_PERM \ + (vector unsigned char)(3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xfe000000U,0xffffffffU,0xfe000000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {1, 1, 1, 1} + #define ALTI_SL1_PERM \ + {3,4,5,6,7,29,29,29,11,12,13,14,15,0,1,2} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xfe000000U,0xffffffffU,0xfe000000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS521_H */ diff --git a/dep/dsfmt/dSFMT-params86243.h b/dep/dsfmt/dSFMT-params86243.h new file mode 100644 index 00000000..bf3dcd0d --- /dev/null +++ b/dep/dsfmt/dSFMT-params86243.h @@ -0,0 +1,40 @@ +#ifndef DSFMT_PARAMS86243_H +#define DSFMT_PARAMS86243_H + +/* #define DSFMT_N 829 */ +/* #define DSFMT_MAXDEGREE 86344 */ +#define DSFMT_POS1 231 +#define DSFMT_SL1 13 +#define DSFMT_MSK1 UINT64_C(0x000ffedff6ffffdf) +#define DSFMT_MSK2 UINT64_C(0x000ffff7fdffff7e) +#define DSFMT_MSK32_1 0x000ffedfU +#define DSFMT_MSK32_2 0xf6ffffdfU +#define DSFMT_MSK32_3 0x000ffff7U +#define DSFMT_MSK32_4 0xfdffff7eU +#define DSFMT_FIX1 UINT64_C(0x1d553e776b975e68) +#define DSFMT_FIX2 UINT64_C(0x648faadf1416bf91) +#define DSFMT_PCV1 UINT64_C(0x5f2cd03e2758a373) +#define DSFMT_PCV2 UINT64_C(0xc0b7eb8410000001) +#define DSFMT_IDSTR "dSFMT2-86243:231-13:ffedff6ffffdf-ffff7fdffff7e" + + +/* PARAMETERS FOR ALTIVEC */ +#if defined(__APPLE__) /* For OSX */ + #define ALTI_SL1 (vector unsigned int)(5, 5, 5, 5) + #define ALTI_SL1_PERM \ + (vector unsigned char)(1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0) + #define ALTI_SL1_MSK \ + (vector unsigned int)(0xffffffffU,0xffffe000U,0xffffffffU,0xffffe000U) + #define ALTI_MSK (vector unsigned int)(DSFMT_MSK32_1, \ + DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4) +#else /* For OTHER OSs(Linux?) */ + #define ALTI_SL1 {5, 5, 5, 5} + #define ALTI_SL1_PERM \ + {1,2,3,4,5,6,7,31,9,10,11,12,13,14,15,0} + #define ALTI_SL1_MSK \ + {0xffffffffU,0xffffe000U,0xffffffffU,0xffffe000U} + #define ALTI_MSK \ + {DSFMT_MSK32_1, DSFMT_MSK32_2, DSFMT_MSK32_3, DSFMT_MSK32_4} +#endif + +#endif /* DSFMT_PARAMS86243_H */ diff --git a/dep/dsfmt/dSFMT.c b/dep/dsfmt/dSFMT.c new file mode 100644 index 00000000..a764dd22 --- /dev/null +++ b/dep/dsfmt/dSFMT.c @@ -0,0 +1,735 @@ +/** + * @file dSFMT.c + * @brief double precision SIMD-oriented Fast Mersenne Twister (dSFMT) + * based on IEEE 754 format. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (Hiroshima University) + * + * Copyright (C) 2007,2008 Mutsuo Saito, Makoto Matsumoto and Hiroshima + * University. All rights reserved. + * + * The new BSD License is applied to this software, see LICENSE.txt + */ +#include +#include +#include +#include "dSFMT-params.h" +#include "dSFMT.h" + +/** dsfmt internal state vector */ +dsfmt_t dsfmt_global_data; +/** dsfmt mexp for check */ +static const int dsfmt_mexp = DSFMT_MEXP; + +/*---------------- + STATIC FUNCTIONS + ----------------*/ +inline static uint32_t ini_func1(uint32_t x); +inline static uint32_t ini_func2(uint32_t x); +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, + int size); +inline static int idxof(int i); +static void initial_mask(dsfmt_t *dsfmt); +static void period_certification(dsfmt_t *dsfmt); + +#if defined(HAVE_SSE2) +# include +/** mask data for sse2 */ +static __m128i sse2_param_mask; +/** 1 in 64bit for sse2 */ +static __m128i sse2_int_one; +/** 2.0 double for sse2 */ +static __m128d sse2_double_two; +/** -1.0 double for sse2 */ +static __m128d sse2_double_m_one; + +static void setup_const(void); +#endif + +/** + * This function simulate a 32-bit array index overlapped to 64-bit + * array of LITTLE ENDIAN in BIG ENDIAN machine. + */ +#if defined(DSFMT_BIG_ENDIAN) +inline static int idxof(int i) { + return i ^ 1; +} +#else +inline static int idxof(int i) { + return i; +} +#endif + +/** + * This function represents the recursion formula. + * @param r output + * @param a a 128-bit part of the internal state array + * @param b a 128-bit part of the internal state array + * @param lung a 128-bit part of the internal state array + */ +#if defined(HAVE_ALTIVEC) +inline static void do_recursion(w128_t *r, w128_t *a, w128_t * b, + w128_t *lung) { + const vector unsigned char sl1 = ALTI_SL1; + const vector unsigned char sl1_perm = ALTI_SL1_PERM; + const vector unsigned int sl1_msk = ALTI_SL1_MSK; + const vector unsigned char sr1 = ALTI_SR; + const vector unsigned char sr1_perm = ALTI_SR_PERM; + const vector unsigned int sr1_msk = ALTI_SR_MSK; + const vector unsigned char perm = ALTI_PERM; + const vector unsigned int msk1 = ALTI_MSK; + vector unsigned int w, x, y, z; + + z = a->s; + w = lung->s; + x = vec_perm(w, (vector unsigned int)perm, perm); + y = vec_perm(z, sl1_perm, sl1_perm); + y = vec_sll(y, sl1); + y = vec_and(y, sl1_msk); + w = vec_xor(x, b->s); + w = vec_xor(w, y); + x = vec_perm(w, (vector unsigned int)sr1_perm, sr1_perm); + x = vec_srl(x, sr1); + x = vec_and(x, sr1_msk); + y = vec_and(w, msk1); + z = vec_xor(z, y); + r->s = vec_xor(z, x); + lung->s = w; +} +#elif defined(HAVE_SSE2) +/** + * This function setup some constant variables for SSE2. + */ +static void setup_const(void) { + static int first = 1; + if (!first) { + return; + } + sse2_param_mask = _mm_set_epi32(DSFMT_MSK32_3, DSFMT_MSK32_4, + DSFMT_MSK32_1, DSFMT_MSK32_2); + sse2_int_one = _mm_set_epi32(0, 1, 0, 1); + sse2_double_two = _mm_set_pd(2.0, 2.0); + sse2_double_m_one = _mm_set_pd(-1.0, -1.0); + first = 0; +} + +/** + * This function represents the recursion formula. + * @param r output 128-bit + * @param a a 128-bit part of the internal state array + * @param b a 128-bit part of the internal state array + * @param d a 128-bit part of the internal state array (I/O) + */ +inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *u) { + __m128i v, w, x, y, z; + + x = a->si; + z = _mm_slli_epi64(x, DSFMT_SL1); + y = _mm_shuffle_epi32(u->si, SSE2_SHUFF); + z = _mm_xor_si128(z, b->si); + y = _mm_xor_si128(y, z); + + v = _mm_srli_epi64(y, DSFMT_SR); + w = _mm_and_si128(y, sse2_param_mask); + v = _mm_xor_si128(v, x); + v = _mm_xor_si128(v, w); + r->si = v; + u->si = y; +} +#else /* standard C */ +/** + * This function represents the recursion formula. + * @param r output 128-bit + * @param a a 128-bit part of the internal state array + * @param b a 128-bit part of the internal state array + * @param lung a 128-bit part of the internal state array (I/O) + */ +inline static void do_recursion(w128_t *r, w128_t *a, w128_t * b, + w128_t *lung) { + uint64_t t0, t1, L0, L1; + + t0 = a->u[0]; + t1 = a->u[1]; + L0 = lung->u[0]; + L1 = lung->u[1]; + lung->u[0] = (t0 << DSFMT_SL1) ^ (L1 >> 32) ^ (L1 << 32) ^ b->u[0]; + lung->u[1] = (t1 << DSFMT_SL1) ^ (L0 >> 32) ^ (L0 << 32) ^ b->u[1]; + r->u[0] = (lung->u[0] >> DSFMT_SR) ^ (lung->u[0] & DSFMT_MSK1) ^ t0; + r->u[1] = (lung->u[1] >> DSFMT_SR) ^ (lung->u[1] & DSFMT_MSK2) ^ t1; +} +#endif + +#if defined(HAVE_SSE2) +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range [0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_c0o1(w128_t *w) { + w->sd = _mm_add_pd(w->sd, sse2_double_m_one); +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1]. + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0c1(w128_t *w) { + w->sd = _mm_sub_pd(sse2_double_two, w->sd); +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0o1(w128_t *w) { + w->si = _mm_or_si128(w->si, sse2_int_one); + w->sd = _mm_add_pd(w->sd, sse2_double_m_one); +} +#else /* standard C and altivec */ +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range [0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_c0o1(w128_t *w) { + w->d[0] -= 1.0; + w->d[1] -= 1.0; +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1]. + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0c1(w128_t *w) { + w->d[0] = 2.0 - w->d[0]; + w->d[1] = 2.0 - w->d[1]; +} + +/** + * This function converts the double precision floating point numbers which + * distribute uniformly in the range [1, 2) to those which distribute uniformly + * in the range (0, 1). + * @param w 128bit stracture of double precision floating point numbers (I/O) + */ +inline static void convert_o0o1(w128_t *w) { + w->u[0] |= 1; + w->u[1] |= 1; + w->d[0] -= 1.0; + w->d[1] -= 1.0; +} +#endif + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_c0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_c0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_c0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0o1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0o1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0o1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function fills the user-specified array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param size number of 128-bit pseudorandom numbers to be generated. + */ +inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array, + int size) { + int i, j; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&array[0], &dsfmt->status[0], &dsfmt->status[DSFMT_POS1], + &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&array[i], &dsfmt->status[i], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + } + for (; i < size - DSFMT_N; i++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + convert_o0c1(&array[i - DSFMT_N]); + } + for (j = 0; j < 2 * DSFMT_N - size; j++) { + dsfmt->status[j] = array[j + size - DSFMT_N]; + } + for (; i < size; i++, j++) { + do_recursion(&array[i], &array[i - DSFMT_N], + &array[i + DSFMT_POS1 - DSFMT_N], &lung); + dsfmt->status[j] = array[i]; + convert_o0c1(&array[i - DSFMT_N]); + } + for (i = size - DSFMT_N; i < size; i++) { + convert_o0c1(&array[i]); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function represents a function used in the initialization + * by init_by_array + * @param x 32-bit integer + * @return 32-bit integer + */ +static uint32_t ini_func1(uint32_t x) { + return (x ^ (x >> 27)) * (uint32_t)1664525UL; +} + +/** + * This function represents a function used in the initialization + * by init_by_array + * @param x 32-bit integer + * @return 32-bit integer + */ +static uint32_t ini_func2(uint32_t x) { + return (x ^ (x >> 27)) * (uint32_t)1566083941UL; +} + +/** + * This function initializes the internal state array to fit the IEEE + * 754 format. + * @param dsfmt dsfmt state vector. + */ +static void initial_mask(dsfmt_t *dsfmt) { + int i; + uint64_t *psfmt; + + psfmt = &dsfmt->status[0].u[0]; + for (i = 0; i < DSFMT_N * 2; i++) { + psfmt[i] = (psfmt[i] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST; + } +} + +/** + * This function certificate the period of 2^{SFMT_MEXP}-1. + * @param dsfmt dsfmt state vector. + */ +static void period_certification(dsfmt_t *dsfmt) { + uint64_t pcv[2] = {DSFMT_PCV1, DSFMT_PCV2}; + uint64_t tmp[2]; + uint64_t inner; + int i; +#if (DSFMT_PCV2 & 1) != 1 + int j; + uint64_t work; +#endif + + tmp[0] = (dsfmt->status[DSFMT_N].u[0] ^ DSFMT_FIX1); + tmp[1] = (dsfmt->status[DSFMT_N].u[1] ^ DSFMT_FIX2); + + inner = tmp[0] & pcv[0]; + inner ^= tmp[1] & pcv[1]; + for (i = 32; i > 0; i >>= 1) { + inner ^= inner >> i; + } + inner &= 1; + /* check OK */ + if (inner == 1) { + return; + } + /* check NG, and modification */ +#if (DSFMT_PCV2 & 1) == 1 + dsfmt->status[DSFMT_N].u[1] ^= 1; +#else + for (i = 1; i >= 0; i--) { + work = 1; + for (j = 0; j < 64; j++) { + if ((work & pcv[i]) != 0) { + dsfmt->status[DSFMT_N].u[i] ^= work; + return; + } + work = work << 1; + } + } +#endif + return; +} + +/*---------------- + PUBLIC FUNCTIONS + ----------------*/ +/** + * This function returns the identification string. The string shows + * the Mersenne exponent, and all parameters of this generator. + * @return id string. + */ +const char *dsfmt_get_idstring(void) { + return DSFMT_IDSTR; +} + +/** + * This function returns the minimum size of array used for \b + * fill_array functions. + * @return minimum size of array used for fill_array functions. + */ +int dsfmt_get_min_array_size(void) { + return DSFMT_N64; +} + +/** + * This function fills the internal state array with double precision + * floating point pseudorandom numbers of the IEEE 754 format. + * @param dsfmt dsfmt state vector. + */ +void dsfmt_gen_rand_all(dsfmt_t *dsfmt) { + int i; + w128_t lung; + + lung = dsfmt->status[DSFMT_N]; + do_recursion(&dsfmt->status[0], &dsfmt->status[0], + &dsfmt->status[DSFMT_POS1], &lung); + for (i = 1; i < DSFMT_N - DSFMT_POS1; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1], &lung); + } + for (; i < DSFMT_N; i++) { + do_recursion(&dsfmt->status[i], &dsfmt->status[i], + &dsfmt->status[i + DSFMT_POS1 - DSFMT_N], &lung); + } + dsfmt->status[DSFMT_N] = lung; +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [1, 2) to the + * specified array[] by one call. The number of pseudorandom numbers + * is specified by the argument \b size, which must be at least (SFMT_MEXP + * / 128) * 2 and a multiple of two. The function + * get_min_array_size() returns this minimum size. The generation by + * this function is much faster than the following fill_array_xxx functions. + * + * For initialization, init_gen_rand() or init_by_array() must be called + * before the first call of this function. This function can not be + * used after calling genrand_xxx functions, without initialization. + * + * @param dsfmt dsfmt state vector. + * @param array an array where pseudorandom numbers are filled + * by this function. The pointer to the array must be "aligned" + * (namely, must be a multiple of 16) in the SIMD version, since it + * refers to the address of a 128-bit integer. In the standard C + * version, the pointer is arbitrary. + * + * @param size the number of 64-bit pseudorandom integers to be + * generated. size must be a multiple of 2, and greater than or equal + * to (SFMT_MEXP / 128) * 2. + * + * @note \b memalign or \b posix_memalign is available to get aligned + * memory. Mac OSX doesn't have these functions, but \b malloc of OSX + * returns the pointer to the aligned memory block. + */ +void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c1o2(dsfmt, (w128_t *)array, size / 2); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1] to the + * specified array[] by one call. This function is the same as + * fill_array_close1_open2() except the distribution range. + * + * @param dsfmt dsfmt state vector. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa fill_array_close1_open2() + */ +void dsfmt_fill_array_open_close(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0c1(dsfmt, (w128_t *)array, size / 2); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [0, 1) to the + * specified array[] by one call. This function is the same as + * fill_array_close1_open2() except the distribution range. + * + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param dsfmt dsfmt state vector. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa fill_array_close1_open2() + */ +void dsfmt_fill_array_close_open(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_c0o1(dsfmt, (w128_t *)array, size / 2); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1) to the + * specified array[] by one call. This function is the same as + * fill_array_close1_open2() except the distribution range. + * + * @param dsfmt dsfmt state vector. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa fill_array_close1_open2() + */ +void dsfmt_fill_array_open_open(dsfmt_t *dsfmt, double array[], int size) { + assert(size % 2 == 0); + assert(size >= DSFMT_N64); + gen_rand_array_o0o1(dsfmt, (w128_t *)array, size / 2); +} + +#if defined(__INTEL_COMPILER) +# pragma warning(disable:981) +#endif +/** + * This function initializes the internal state array with a 32-bit + * integer seed. + * @param dsfmt dsfmt state vector. + * @param seed a 32-bit integer used as the seed. + * @param mexp caller's mersenne expornent + */ +void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) { + int i; + uint32_t *psfmt; + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + psfmt = &dsfmt->status[0].u32[0]; + psfmt[idxof(0)] = seed; + for (i = 1; i < (DSFMT_N + 1) * 4; i++) { + psfmt[idxof(i)] = 1812433253UL + * (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; +#if defined(HAVE_SSE2) + setup_const(); +#endif +} + +/** + * This function initializes the internal state array, + * with an array of 32-bit integers used as the seeds + * @param dsfmt dsfmt state vector. + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + * @param mexp caller's mersenne expornent + */ +void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length, int mexp) { + int i, j, count; + uint32_t r; + uint32_t *psfmt32; + int lag; + int mid; + int size = (DSFMT_N + 1) * 4; /* pulmonary */ + + /* make sure caller program is compiled with the same MEXP */ + if (mexp != dsfmt_mexp) { + fprintf(stderr, "DSFMT_MEXP doesn't match with dSFMT.c\n"); + exit(1); + } + if (size >= 623) { + lag = 11; + } else if (size >= 68) { + lag = 7; + } else if (size >= 39) { + lag = 5; + } else { + lag = 3; + } + mid = (size - lag) / 2; + + psfmt32 = &dsfmt->status[0].u32[0]; + memset(dsfmt->status, 0x8b, sizeof(dsfmt->status)); + if (key_length + 1 > size) { + count = key_length + 1; + } else { + count = size; + } + r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)] + ^ psfmt32[idxof((size - 1) % size)]); + psfmt32[idxof(mid % size)] += r; + r += key_length; + psfmt32[idxof((mid + lag) % size)] += r; + psfmt32[idxof(0)] = r; + count--; + for (i = 1, j = 0; (j < count) && (j < key_length); j++) { + r = ini_func1(psfmt32[idxof(i)] + ^ psfmt32[idxof((i + mid) % size)] + ^ psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += init_key[j] + i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (; j < count; j++) { + r = ini_func1(psfmt32[idxof(i)] + ^ psfmt32[idxof((i + mid) % size)] + ^ psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] += r; + r += i; + psfmt32[idxof((i + mid + lag) % size)] += r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + for (j = 0; j < size; j++) { + r = ini_func2(psfmt32[idxof(i)] + + psfmt32[idxof((i + mid) % size)] + + psfmt32[idxof((i + size - 1) % size)]); + psfmt32[idxof((i + mid) % size)] ^= r; + r -= i; + psfmt32[idxof((i + mid + lag) % size)] ^= r; + psfmt32[idxof(i)] = r; + i = (i + 1) % size; + } + initial_mask(dsfmt); + period_certification(dsfmt); + dsfmt->idx = DSFMT_N64; +#if defined(HAVE_SSE2) + setup_const(); +#endif +} +#if defined(__INTEL_COMPILER) +# pragma warning(default:981) +#endif diff --git a/dep/dsfmt/dSFMT.h b/dep/dsfmt/dSFMT.h new file mode 100644 index 00000000..11ff5531 --- /dev/null +++ b/dep/dsfmt/dSFMT.h @@ -0,0 +1,246 @@ +/** + * @file dSFMT.h + * + * @brief double precision SIMD oriented Fast Mersenne Twister(dSFMT) + * pseudorandom number generator based on IEEE 754 format. + * + * @author Mutsuo Saito (Hiroshima University) + * @author Makoto Matsumoto (Hiroshima University) + * + * Copyright (C) 2007, 2008 Mutsuo Saito, Makoto Matsumoto and + * Hiroshima University. All rights reserved. + * + * The new BSD License is applied to this software. + * see LICENSE.txt + * + * @note We assume that your system has inttypes.h. If your system + * doesn't have inttypes.h, you have to typedef uint32_t and uint64_t, + * and you have to define PRIu64 and PRIx64 in this file as follows: + * @verbatim + typedef unsigned int uint32_t + typedef unsigned long long uint64_t + #define PRIu64 "llu" + #define PRIx64 "llx" +@endverbatim + * uint32_t must be exactly 32-bit unsigned integer type (no more, no + * less), and uint64_t must be exactly 64-bit unsigned integer type. + * PRIu64 and PRIx64 are used for printf function to print 64-bit + * unsigned int and 64-bit unsigned int in hexadecimal format. + * + * This file has been modified by the Sandia UQTk group in the following way: + * DSFMT_MEXP has been set to 216091 + * defined DSFMT_DO_NOT_USE_OLD_NAMES + * removed some compiler specific directives + * defined DSFMT_PRE_INLINE and DSFMT_PST_INLINE to empty + * added extern "C" to the functions that need to be called from C++ + */ + +#ifndef DSFMT_H +#define DSFMT_H + +/** UQTk specific setting */ +#define DSFMT_DO_NOT_USE_OLD_NAMES + +#include +#include + +/*----------------- + BASIC DEFINITIONS + -----------------*/ +/* Mersenne Exponent. The period of the sequence + * is a multiple of 2^DSFMT_MEXP-1. + * #define DSFMT_MEXP 19937 */ + +/** UQTk setting */ +#define DSFMT_MEXP 216091 + +/** DSFMT generator has an internal state array of 128-bit integers, + * and N is its size. */ +#define DSFMT_N ((DSFMT_MEXP - 128) / 104 + 1) +/** N32 is the size of internal state array when regarded as an array + * of 32-bit integers.*/ +#define DSFMT_N32 (DSFMT_N * 4) +/** N64 is the size of internal state array when regarded as an array + * of 64-bit integers.*/ +#define DSFMT_N64 (DSFMT_N * 2) + +#if !defined(DSFMT_BIG_ENDIAN) +# if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) +# if __BYTE_ORDER == __BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) +# if _BYTE_ORDER == _BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(__BYTE_ORDER__) && defined(__BIG_ENDIAN__) +# if __BYTE_ORDER__ == __BIG_ENDIAN__ +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(BYTE_ORDER) && defined(BIG_ENDIAN) +# if BYTE_ORDER == BIG_ENDIAN +# define DSFMT_BIG_ENDIAN 1 +# endif +# elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) \ + || defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) +# define DSFMT_BIG_ENDIAN 1 +# endif +#endif + +#if defined(DSFMT_BIG_ENDIAN) && defined(__amd64) +# undef DSFMT_BIG_ENDIAN +#endif + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# include +#elif defined(_MSC_VER) || defined(__BORLANDC__) +# if !defined(DSFMT_UINT32_DEFINED) && !defined(SFMT_UINT32_DEFINED) +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; +# define UINT64_C(v) (v ## ui64) +# define DSFMT_UINT32_DEFINED +# if !defined(inline) +# define inline __inline +# endif +# endif +#else +# include +# if !defined(inline) +# if defined(__GNUC__) +# define inline __inline__ +# else +# define inline +# endif +# endif +#endif + +#ifndef PRIu64 +# if defined(_MSC_VER) || defined(__BORLANDC__) +# define PRIu64 "I64u" +# define PRIx64 "I64x" +# else +# define PRIu64 "llu" +# define PRIx64 "llx" +# endif +#endif + +#ifndef UINT64_C +# define UINT64_C(v) (v ## ULL) +#endif + +/*------------------------------------------ + 128-bit SIMD like data type for standard C + ------------------------------------------*/ +#if defined(HAVE_ALTIVEC) +# if !defined(__APPLE__) +# include +# endif +/** 128-bit data structure */ +union W128_T { + vector unsigned int s; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; +}; + +#elif defined(HAVE_SSE2) +# include + +/** 128-bit data structure */ +union W128_T { + __m128i si; + __m128d sd; + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; +}; +#else /* standard C */ +/** 128-bit data structure */ +union W128_T { + uint64_t u[2]; + uint32_t u32[4]; + double d[2]; +}; +#endif + +/** 128-bit data type */ +typedef union W128_T w128_t; + +/** the 128-bit internal state array */ +struct DSFMT_T { + w128_t status[DSFMT_N + 1]; + int idx; +}; +typedef struct DSFMT_T dsfmt_t; + +/** dsfmt internal state vector */ +extern dsfmt_t dsfmt_global_data; +/** dsfmt mexp for check */ +extern const int dsfmt_global_mexp; + +void dsfmt_gen_rand_all(dsfmt_t *dsfmt); +void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp); +void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length, int mexp); +const char *dsfmt_get_idstring(void); +int dsfmt_get_min_array_size(void); + +/** UQTk setting: no inlining */ +#define DSFMT_PRE_INLINE +#define DSFMT_PST_INLINE + +/** UQTk setting: allow functions to be called by C++ */ + +#ifdef __cplusplus +extern "C" +{ +#endif +DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32 (dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_close_open (dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_open_close (dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_genrand_open_open (dsfmt_t *dsfmt) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32 (void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open (void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close (void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open (void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_fill_array_open_close (dsfmt_t *dsfmt, double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_fill_array_close_open (dsfmt_t *dsfmt, double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_fill_array_open_open (dsfmt_t *dsfmt, double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_fill_array_close1_open2(dsfmt_t *dsfmt, double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close (double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open (double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open (double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand (uint32_t seed) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_gv_init_by_array (uint32_t init_key[],int key_length) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[],int key_length) DSFMT_PST_INLINE; +#ifdef __cplusplus +} +#endif + + +#if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) +DSFMT_PRE_INLINE const char *get_idstring(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE int get_min_array_size(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_close1_open2(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_close_open(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_open_close(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE double genrand_open_open(void) DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) + DSFMT_PST_INLINE; +DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) + DSFMT_PST_INLINE; + +#endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ + +#endif /* DSFMT_H */ diff --git a/dep/dsfmt/dSFMT_h.c b/dep/dsfmt/dSFMT_h.c new file mode 100644 index 00000000..f925f57d --- /dev/null +++ b/dep/dsfmt/dSFMT_h.c @@ -0,0 +1,397 @@ +/** +This file is created by the Sandia UQTk group. +Since the inlining is turned off in dSFMT.h, the function definitions are moved from dSFMT.h to this file, leaving dSFMT.h only with declarations. +This way including dSFMT.h does not produce 'duplicate symbol' errors. +*/ + +#include "dSFMT.h" +#include "dsfmt_add.h" + + + +/** + * This function generates and returns unsigned 32-bit integer. + * This is slower than SFMT, only for convenience usage. + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE uint32_t dsfmt_genrand_uint32(dsfmt_t *dsfmt) { + uint32_t r; + uint64_t *psfmt64 = &dsfmt->status[0].u[0]; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++] & 0xffffffffU; + return r; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [1, 2). This is + * the primitive and faster than generating numbers in other ranges. + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_genrand_close1_open2(dsfmt_t *dsfmt) { + double r; + double *psfmt64 = &dsfmt->status[0].d[0]; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r = psfmt64[dsfmt->idx++]; + return r; +} + +/** + * This function generates and returns unsigned 32-bit integer. + * This is slower than SFMT, only for convenience usage. + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE uint32_t dsfmt_gv_genrand_uint32(void) { + return dsfmt_genrand_uint32(&dsfmt_global_data); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [1, 2). + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_gv_genrand_close1_open2(void) { + return dsfmt_genrand_close1_open2(&dsfmt_global_data); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [0, 1). + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_genrand_close_open(dsfmt_t *dsfmt) { + return dsfmt_genrand_close1_open2(dsfmt) - 1.0; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range [0, 1). + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_gv_genrand_close_open(void) { + return dsfmt_gv_genrand_close1_open2() - 1.0; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1]. + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_genrand_open_close(dsfmt_t *dsfmt) { + return 2.0 - dsfmt_genrand_close1_open2(dsfmt); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1]. + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_close(void) { + return 2.0 - dsfmt_gv_genrand_close1_open2(); +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1). + * dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called + * before this function. + * @param dsfmt dsfmt internal state date + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_genrand_open_open(dsfmt_t *dsfmt) { + double *dsfmt64 = &dsfmt->status[0].d[0]; + union { + double d; + uint64_t u; + } r; + + if (dsfmt->idx >= DSFMT_N64) { + dsfmt_gen_rand_all(dsfmt); + dsfmt->idx = 0; + } + r.d = dsfmt64[dsfmt->idx++]; + r.u |= 1; + return r.d - 1.0; +} + +/** + * This function generates and returns double precision pseudorandom + * number which distributes uniformly in the range (0, 1). + * dsfmt_gv_init_gen_rand() or dsfmt_gv_init_by_array() must be called + * before this function. This function uses \b global variables. + * @return double precision floating point pseudorandom number + */ +DSFMT_PRE_INLINE double dsfmt_gv_genrand_open_open(void) { + return dsfmt_genrand_open_open(&dsfmt_global_data); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [1, 2) to the + * specified array[] by one call. This function is the same as + * dsfmt_fill_array_close1_open2() except that this function uses + * \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close1_open2(double array[], int size) { + dsfmt_fill_array_close1_open2(&dsfmt_global_data, array, size); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1] to the + * specified array[] by one call. This function is the same as + * dsfmt_gv_fill_array_close1_open2() except the distribution range. + * This function uses \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() and \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_close(double array[], int size) { + dsfmt_fill_array_open_close(&dsfmt_global_data, array, size); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range [0, 1) to the + * specified array[] by one call. This function is the same as + * dsfmt_gv_fill_array_close1_open2() except the distribution range. + * This function uses \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_close_open(double array[], int size) { + dsfmt_fill_array_close_open(&dsfmt_global_data, array, size); +} + +/** + * This function generates double precision floating point + * pseudorandom numbers which distribute in the range (0, 1) to the + * specified array[] by one call. This function is the same as + * dsfmt_gv_fill_array_close1_open2() except the distribution range. + * This function uses \b global variables. + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2() \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void dsfmt_gv_fill_array_open_open(double array[], int size) { + dsfmt_fill_array_open_open(&dsfmt_global_data, array, size); +} + +/** + * This function initializes the internal state array with a 32-bit + * integer seed. + * @param dsfmt dsfmt state vector. + * @param seed a 32-bit integer used as the seed. + */ +DSFMT_PRE_INLINE void dsfmt_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed) { + dsfmt_chk_init_gen_rand(dsfmt, seed, DSFMT_MEXP); + dsfmt_reset_add(); +} + +/** + * This function initializes the internal state array with a 32-bit + * integer seed. This function uses \b global variables. + * @param seed a 32-bit integer used as the seed. + * see also \sa dsfmt_init_gen_rand() + */ +DSFMT_PRE_INLINE void dsfmt_gv_init_gen_rand(uint32_t seed) { + dsfmt_init_gen_rand(&dsfmt_global_data, seed); + dsfmt_reset_add(); +} + +/** + * This function initializes the internal state array, + * with an array of 32-bit integers used as the seeds. + * @param dsfmt dsfmt state vector + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + */ +DSFMT_PRE_INLINE void dsfmt_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[], + int key_length) { + dsfmt_chk_init_by_array(dsfmt, init_key, key_length, DSFMT_MEXP); +} + +/** + * This function initializes the internal state array, + * with an array of 32-bit integers used as the seeds. + * This function uses \b global variables. + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + * see also \sa dsfmt_init_by_array() + */ +DSFMT_PRE_INLINE void dsfmt_gv_init_by_array(uint32_t init_key[], int key_length) { + dsfmt_init_by_array(&dsfmt_global_data, init_key, key_length); +} + + + + +#if !defined(DSFMT_DO_NOT_USE_OLD_NAMES) +/** + * This function is just the same as dsfmt_get_idstring(). + * @return id string. + * see also \sa dsfmt_get_idstring() + */ +DSFMT_PRE_INLINE const char *get_idstring(void) { + return dsfmt_get_idstring(); +} + +/** + * This function is just the same as dsfmt_get_min_array_size(). + * @return minimum size of array used for fill_array functions. + * see also \sa dsfmt_get_min_array_size() + */ +DSFMT_PRE_INLINE int get_min_array_size(void) { + return dsfmt_get_min_array_size(); +} + +/** + * This function is just the same as dsfmt_gv_init_gen_rand(). + * @param seed a 32-bit integer used as the seed. + * see also \sa dsfmt_gv_init_gen_rand(), \sa dsfmt_init_gen_rand(). + */ +DSFMT_PRE_INLINE void init_gen_rand(uint32_t seed) { + dsfmt_gv_init_gen_rand(seed); + dsfmt_reset_add(); +} + +/** + * This function is just the same as dsfmt_gv_init_by_array(). + * @param init_key the array of 32-bit integers, used as a seed. + * @param key_length the length of init_key. + * see also \sa dsfmt_gv_init_by_array(), \sa dsfmt_init_by_array(). + */ +DSFMT_PRE_INLINE void init_by_array(uint32_t init_key[], int key_length) { + dsfmt_gv_init_by_array(init_key, key_length); +} + +/** + * This function is just the same as dsfmt_gv_genrand_close1_open2(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_close1_open2() \sa + * dsfmt_gv_genrand_close1_open2() + */ +DSFMT_PRE_INLINE double genrand_close1_open2(void) { + return dsfmt_gv_genrand_close1_open2(); +} + +/** + * This function is just the same as dsfmt_gv_genrand_close_open(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_close_open() \sa + * dsfmt_gv_genrand_close_open() + */ +DSFMT_PRE_INLINE double genrand_close_open(void) { + return dsfmt_gv_genrand_close_open(); +} + +/** + * This function is just the same as dsfmt_gv_genrand_open_close(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_open_close() \sa + * dsfmt_gv_genrand_open_close() + */ +DSFMT_PRE_INLINE double genrand_open_close(void) { + return dsfmt_gv_genrand_open_close(); +} + +/** + * This function is just the same as dsfmt_gv_genrand_open_open(). + * @return double precision floating point number. + * see also \sa dsfmt_genrand_open_open() \sa + * dsfmt_gv_genrand_open_open() + */ +DSFMT_PRE_INLINE double genrand_open_open(void) { + return dsfmt_gv_genrand_open_open(); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_open_close(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_gv_fill_array_open_close(), \sa + * dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void fill_array_open_close(double array[], int size) { + dsfmt_gv_fill_array_open_close(array, size); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_close_open(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_gv_fill_array_close_open(), \sa + * dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void fill_array_close_open(double array[], int size) { + dsfmt_gv_fill_array_close_open(array, size); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_open_open(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_gv_fill_array_open_open(), \sa + * dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void fill_array_open_open(double array[], int size) { + dsfmt_gv_fill_array_open_open(array, size); +} + +/** + * This function is juset the same as dsfmt_gv_fill_array_close1_open2(). + * @param array an array where pseudorandom numbers are filled + * by this function. + * @param size the number of pseudorandom numbers to be generated. + * see also \sa dsfmt_fill_array_close1_open2(), \sa + * dsfmt_gv_fill_array_close1_open2() + */ +DSFMT_PRE_INLINE void fill_array_close1_open2(double array[], int size) { + dsfmt_gv_fill_array_close1_open2(array, size); +} +#endif /* DSFMT_DO_NOT_USE_OLD_NAMES */ diff --git a/dep/dsfmt/dsfmt_add.c b/dep/dsfmt/dsfmt_add.c new file mode 100644 index 00000000..601d901c --- /dev/null +++ b/dep/dsfmt/dsfmt_add.c @@ -0,0 +1,133 @@ +#include "dsfmt_add.h" +#include "stdlib.h" +#include "stdio.h" +#include "math.h" + + +#define DPI2 8.0*atan(1.0) + +static int dsfmt_nrv_calls = 0 ; + +void dsfmt_reset_add() +{ + dsfmt_nrv_calls = 0 ; +} + +double dsfmt_gv_genrand_urv() +{ + return dsfmt_gv_genrand_open_open(); +} + +double dsfmt_genrand_urv(dsfmt_t *dsfmt) +{ + return dsfmt_genrand_open_open(dsfmt); +} + + +double dsfmt_gv_genrand_urv_sm(double a, double b) +{ + if (a>b){ + printf("dsfmt_gv_genrand_unif_sm(): Lower bound of the interval is larger than the upper bound : %lg > %lg\n",a, b); + printf(" -> Abort !\n"); + fflush(stdout); + exit(0) ; + } + + return ( dsfmt_gv_genrand_urv()*(b-a)+a ); +} + +double dsfmt_genrand_urv_sm(dsfmt_t *dsfmt, double a, double b) +{ + if (a>b){ + printf("dsfmt_genrand_unif_sm(): Lower bound of the interval is larger than the upper bound : %lg > %lg\n",a, b); + printf(" -> Abort !\n"); + fflush(stdout); + exit(0) ; + } + + return ( dsfmt_genrand_urv(dsfmt)*(b-a)+a ); +} + +double dsfmt_gv_genrand_nrv() +{ + double unif[2], sm2logu1, pi2u2 ; + static double zn1, zn2; + if ( dsfmt_nrv_calls == 0 ) + { + unif[0]=dsfmt_gv_genrand_open_close(); + unif[1]=dsfmt_gv_genrand_open_close(); + sm2logu1 = sqrt(-2.0*log(unif[0])) ; + pi2u2 = DPI2*unif[1] ; + zn1 = sm2logu1*cos(pi2u2) ; + zn2 = sm2logu1*sin(pi2u2) ; + dsfmt_nrv_calls = 1; + return ( zn1 ) ; + } + else if ( dsfmt_nrv_calls == 1 ) + { + dsfmt_nrv_calls = 0 ; + return ( zn2 ); + } + else + { + printf("dsfmt_genrand_nrv(): Unknown value for internal variable dsfmt_nrv_calls : %d\n",dsfmt_nrv_calls); + printf(" -> Abort !\n"); + fflush(stdout); + exit(0) ; + } + +} + +double dsfmt_genrand_nrv(dsfmt_t *dsfmt) +{ + double unif[2], sm2logu1, pi2u2 ; + static double zn1, zn2; + + // if ( dsfmt_nrv_calls == 0 ) + // { + unif[0] = dsfmt_genrand_open_close(dsfmt); + unif[1] = dsfmt_genrand_open_close(dsfmt); + sm2logu1 = sqrt(-2.0*log(unif[0])) ; + pi2u2 = DPI2*unif[1] ; + zn1 = sm2logu1*cos(pi2u2) ; + // zn2 = sm2logu1*sin(pi2u2) ; + // dsfmt_nrv_calls = 1; + return ( zn1 ) ; + // } + // else if ( dsfmt_nrv_calls == 1 ) + // { + // dsfmt_nrv_calls = 0 ; + // return ( zn2 ); + // } + // else + // { + // printf("dsfmt_genrand_nrv(): Unknown value for internal variable dsfmt_nrv_calls : %d\n",dsfmt_nrv_calls); + // printf(" -> Abort !\n"); + // fflush(stdout); + // exit(0) ; + // } + +} + +double dsfmt_gv_genrand_nrv_sm(double mu, double sigma) +{ + if (sigma <= 0) { + printf("dsfmt_gv_genrand_nrv_sm(): Sigma is less than or equal to 0"); + printf(" -> Abort !\n"); + fflush(stdout); + exit(0) ; + } + return ( dsfmt_gv_genrand_nrv()*sigma+mu ); +} + +double dsfmt_genrand_nrv_sm(dsfmt_t *dsfmt, double mu, double sigma) +{ + if (sigma <= 0) { + printf("dsfmt_genrand_nrv(): Sigma is less than or equal to 0"); + printf(" -> Abort !\n"); + fflush(stdout); + exit(0); + } + return ( dsfmt_genrand_nrv(dsfmt)*sigma+mu ); +} + diff --git a/dep/dsfmt/dsfmt_add.h b/dep/dsfmt/dsfmt_add.h new file mode 100644 index 00000000..5184d0b6 --- /dev/null +++ b/dep/dsfmt/dsfmt_add.h @@ -0,0 +1,26 @@ +#ifndef DSFMTADD_H_Seen +#define DSFMTADD_H_Seen + +#include "dSFMT.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + void dsfmt_reset_add() ; + + double dsfmt_gv_genrand_urv(); + double dsfmt_genrand_urv(dsfmt_t *dsfmt); + double dsfmt_gv_genrand_urv_sm(double a, double b); + double dsfmt_genrand_urv_sm(dsfmt_t *dsfmt, double a, double b); + + double dsfmt_gv_genrand_nrv(); + double dsfmt_genrand_nrv(dsfmt_t *dsfmt) ; + double dsfmt_gv_genrand_nrv_sm(double mu, double sigma) ; + double dsfmt_genrand_nrv_sm(dsfmt_t *dsfmt, double mu, double sigma) ; +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dep/figtree/CMakeLists.txt b/dep/figtree/CMakeLists.txt new file mode 100644 index 00000000..196bf885 --- /dev/null +++ b/dep/figtree/CMakeLists.txt @@ -0,0 +1,18 @@ + + +FILE(GLOB fgsrcs "*.cpp") +add_library(depfigtree ${fgsrcs}) + +include_directories (../ann) + +INSTALL(TARGETS depfigtree DESTINATION lib) + +# Install the header files +SET(figtree_HEADERS + figtree_internal.h + figtree.h + KCenterClustering.h + ) + +INSTALL(FILES ${figtree_HEADERS} DESTINATION include/dep) + diff --git a/dep/figtree/KCenterClustering.cpp b/dep/figtree/KCenterClustering.cpp new file mode 100755 index 00000000..938a353b --- /dev/null +++ b/dep/figtree/KCenterClustering.cpp @@ -0,0 +1,475 @@ +//------------------------------------------------------------------- +// This code was modified by Vlad Morariu: +// 11/03/06: +// Removed references to Matlab to compile code into a library +// 01/24/07: +// KCenterClustering now has the ability to increase the number of +// clusters incrementally, calculating the max cluster radius at each +// iteration. +// 02/07/07: +// Clustering now stops when the max cluster radius +// is zero (when number of clusters has reached the number of +// unique points), and the number of ACTUAL clusters used is returned. +// 06/19/07: +// Set the cluster index array to zero initially inside of the constructor +// since we start with all samples belonging to one center. +//------------------------------------------------------------------- + +//------------------------------------------------------------------- +// The code was written by Changjiang Yang and Vikas Raykar +// and is copyrighted under the Lesser GPL: +// +// Copyright (C) 2006 Changjiang Yang and Vikas Raykar +// +// This program 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; version 2.1 or later. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. +// +// The author may be contacted via email at:cyang(at)sarnoff(.)com +// vikas(at)umiacs(.)umd(.)edu +//------------------------------------------------------------------- + +//------------------------------------------------------------------- +// File : KCenterClustering.cpp +// Purpose : Implementation for the k-center clustering algorithm. +// Author : Vikas C. Raykar (vikas@cs.umd.edu) +// Date : April 25 2005, June 10 2005, August 23, 2005 +//------------------------------------------------------------------- + +#include "KCenterClustering.h" +#include +#include +#include +#include //for memset +#define min(a,b) (((a)<(b))?(a):(b)) + + + +//------------------------------------------------------------------- +// Constructor +// +// PURPOSE +// ------- +// Initialize the class. +// Read the parameters. +// +// INPUT +// ---------- +// Dim --> dimension of the points. +// NSources --> number of sources. +// pSources --> pointer to sources, (d*N). +// pClusterIndex --> pointer to a vector of length N where the +// i th element is the cluster number to +// which the i th point belongs. +// +//------------------------------------------------------------------- + +KCenterClustering::KCenterClustering(int Dim, + int NSources, + double *pSources, + int *pClusterIndex, + int NumClusters + ) +{ + + //Read the parameters + + d=Dim; + N=NSources; + px=pSources; + pci=pClusterIndex; + K=NumClusters; + dist_C = new double[N]; //distances to the center. + r=new double[K]; + + // moved from Cluster() by Vlad 1/24/07 + pCenters = new int[K]; //indices of the centers. + cprev = new int[N]; // index to the previous node + cnext = new int[N]; // index to the next node + far2c = new int[K]; // farthest node to the center + + numClusters = 0; + + // KCenterClustering has errors if these are not all zeros to begin with. + memset( pci, 0, sizeof(int)*N ); +} + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- + +KCenterClustering::~KCenterClustering() +{ + delete [] dist_C; + delete [] r; + + // moved from Cluster() by Vlad 1/24/07 + delete []cprev; + delete []cnext; + delete []far2c; + delete []pCenters; +} + + + +//------------------------------------------------------------------- +// ddist is the square of the distance of two vectors(double) +//------------------------------------------------------------------- + + +double +KCenterClustering::ddist(const int d, const double *x, const double *y) +{ + double t, s = 0.0; + for (int i = d; i != 0; i--) + { + t = *x++ - *y++; + s += t * t; + } + return s; +} + + + +//------------------------------------------------------------------- +// Find the largest element from a vector +//------------------------------------------------------------------- + +int +KCenterClustering::idmax(int n, double *x) +{ + int k = 0; + double t = -1.0; + for (int i = 0; i < n; i++, x++) + if( t < *x ) + { + t = *x; + k = i; + } + return k; + +} + + +//------------------------------------------------------------------- +// k-center Clustering. +//------------------------------------------------------------------- +// +// Gonzalez's farthest-point clustering algorithm. +// +// OUTPUT +// ---------------- +// +// MaxClusterRadius --> maximum radius of the clusters, (rx). +// pci --> vector of length N where the i th element is the +// cluster number to which the i th point belongs. +// pci[i] varies between 0 to K-1. +//------------------------------------------------------------------- + + +int +KCenterClustering::Cluster() +{ + // randomly pick one node as the first center. + srand( (unsigned)time( NULL ) ); + int nc = rand() % N; // new center + + // add the ind-th node to the first center. + pCenters[0] = nc; + + // compute the distances from each node to the first center. + // initialize the circular linked list, the center is the + // sentinel node. + const double *x_nc, *x_j; + x_nc = px + nc*d; + x_j = px; + for (int j = 0; j < N; x_j += d, j++) + { + dist_C[j] = (j==nc)? 0.0:ddist(d, x_j, x_nc); + cnext[j] = j+1; + cprev[j] = j-1; + } + cnext[N-1] = 0; // link the tail to the head. + cprev[0] = N-1; // link the head to the tail. + + // compute the radius of the first cluster and the farthest + // node to the center. + nc = idmax(N,dist_C); + far2c[0] = nc; + r[0] = dist_C[nc]; + MaxClusterRadius=sqrt(r[0]); + numClusters = 1; + + for(int i = 1; i < K && MaxClusterRadius > 0; i++) + { + //find the maximum of vector dist_C, i.e., find the node + //that is farthest away from C. It is a new center. + nc = idmax(i,r); + nc = far2c[nc]; + pCenters[i] = nc; //add the ind-th node to the current center. + r[i] = dist_C[nc] = 0.0;pci[nc]=i; + far2c[i] = nc; + cnext[cprev[nc]] = cnext[nc]; // delete nc + cprev[cnext[nc]] = cprev[nc]; + cnext[nc] = cprev[nc] = nc; //self-loop + + //update the distances from each point to the current center. + x_nc = px + nc*d; + for (int j = 0; j < i; j++) + { + int ct_j = pCenters[j]; + x_j = px + ct_j*d; + double dc2cq = ddist(d, x_j, x_nc) / 4; + if (dc2cq < r[j]) // neighbor cluster + { + r[j] = 0.0; + far2c[j] = ct_j; + int k = cnext[ct_j]; + while (k != ct_j) // visit the circular linked list + { + int nextk = cnext[k]; + //compare the distances from new center + //and from current center. + double dist2c_k = dist_C[k]; + if ( dc2cq < dist2c_k ) + { + + x_j = px + k*d; + double dd = ddist(d, x_j, x_nc); + if ( dd < dist2c_k ) + { + dist_C[k] = dd; // update distances to center + pci[k]=i; + if (r[i] < dd) // find max r + { + r[i] = dd; + far2c[i] = k; + + } + cnext[cprev[k]] = nextk; // delete nextk from ct_j + cprev[nextk] = cprev[k]; + cnext[k] = cnext[nc]; // insert nextk to nc + cprev[cnext[nc]] = k; + cnext[nc] = k; + cprev[k] = nc; + + + } + else if ( r[j] < dist2c_k ) + { + r[j] = dist2c_k; + far2c[j] = k; + + } + } + else if ( r[j] < dist2c_k ) + { + r[j] = dist2c_k; + far2c[j] = k; + } // if d < 2 r_k + k = nextk; + } // while k + } // if d < 2 r + } // for j + + // added by vlad 2/6/07 to make sure that we don't keep clustering once each cluster has radius 0 + // otherwise some clusters will have no pts assigned to them + nc = idmax(i+1,r); + MaxClusterRadius=sqrt(r[nc]); + numClusters = i+1; + } // for i + + // commented by vlad 2/6/07 to move it above inside of the loop + //nc = idmax(K,r); + //MaxClusterRadius=sqrt(r[nc]); + //numClusters = K; // added by Vlad 1/24/07 + + return numClusters; +} + +void +KCenterClustering::ClusterIncrement( int * nClusters, double * maxRadius ) +{ + if( numClusters == 0 ) + { + // randomly pick one node as the first center. + srand( (unsigned)time( NULL ) ); + int nc = rand() % N; // new center + + // add the ind-th node to the first center. + pCenters[0] = nc; + + // compute the distances from each node to the first center. + // initialize the circular linked list, the center is the + // sentinel node. + const double *x_nc, *x_j; + x_nc = px + nc*d; + x_j = px; + for (int j = 0; j < N; x_j += d, j++) + { + dist_C[j] = (j==nc)? 0.0:ddist(d, x_j, x_nc); + cnext[j] = j+1; + cprev[j] = j-1; + } + cnext[N-1] = 0; // link the tail to the head. + cprev[0] = N-1; // link the head to the tail. + + // compute the radius of the first cluster and the farthest + // node to the center. + nc = idmax(N,dist_C); + far2c[0] = nc; + r[0] = dist_C[nc]; + + MaxClusterRadius=sqrt(r[0]); + numClusters++; + } + else + { + if( numClusters < K && MaxClusterRadius > 0 ) + { + int i = numClusters; + int nc; + const double *x_nc, *x_j; + + //find the maximum of vector dist_C, i.e., find the node + //that is farthest away from C. It is a new center. + nc = idmax(i,r); + nc = far2c[nc]; + pCenters[i] = nc; //add the ind-th node to the current center. + r[i] = dist_C[nc] = 0.0;pci[nc]=i; + far2c[i] = nc; + cnext[cprev[nc]] = cnext[nc]; // delete nc + cprev[cnext[nc]] = cprev[nc]; + cnext[nc] = cprev[nc] = nc; //self-loop + + //update the distances from each point to the current center. + x_nc = px + nc*d; + for (int j = 0; j < i; j++) + { + int ct_j = pCenters[j]; + x_j = px + ct_j*d; + double dc2cq = ddist(d, x_j, x_nc) / 4; + if (dc2cq < r[j]) // neighbor cluster + { + r[j] = 0.0; + far2c[j] = ct_j; + int k = cnext[ct_j]; + while (k != ct_j) // visit the circular linked list + { + int nextk = cnext[k]; + //compare the distances from new center + //and from current center. + double dist2c_k = dist_C[k]; + if ( dc2cq < dist2c_k ) + { + x_j = px + k*d; + double dd = ddist(d, x_j, x_nc); + if ( dd < dist2c_k ) + { + dist_C[k] = dd; // update distances to center + pci[k]=i; + if (r[i] < dd) // find max r + { + r[i] = dd; + far2c[i] = k; + } + cnext[cprev[k]] = nextk; // delete nextk from ct_j + cprev[nextk] = cprev[k]; + cnext[k] = cnext[nc]; // insert nextk to nc + cprev[cnext[nc]] = k; + cnext[nc] = k; + cprev[k] = nc; + } + else if ( r[j] < dist2c_k ) + { + r[j] = dist2c_k; + far2c[j] = k; + } + } + else if ( r[j] < dist2c_k ) + { + r[j] = dist2c_k; + far2c[j] = k; + } // if d < 2 r_k + k = nextk; + } // while k + } // if d < 2 r + } // for j + + numClusters++; + nc = idmax(numClusters,r); + MaxClusterRadius=sqrt(r[nc]); + } // if( numClusters < K && MaxClusterRadius > 0 ) + } // else ( numClusters > 0 ) + + if( nClusters != NULL ) + *nClusters = numClusters; + if( maxRadius != NULL ) + *maxRadius = MaxClusterRadius; +} + + +//------------------------------------------------------------------------ +// Computes +// [1] the cluster centers by taking the mean of all the points +// belonging to a cluster. +// [2] the number of points in each cluster. +// [3] the radius of each cluster. +//------------------------------------------------------------------------ +// NumClusters --> number of clusters +// pClusterCenters --> pointer to the cluster centers, (d*K), +// pNumPoints --> pointer to the num of points in each cluster, (K). +// pClusterRadii --> pointer to the radius of each cluster, (K). +//------------------------------------------------------------------------ + +void +KCenterClustering::ComputeClusterCenters( + int NumClusters, + double *pClusterCenters, + int *pNumPoints, + double *pClusterRadii + ) +{ + int K=NumClusters; + + for(int k=0; k dimension of the points. +// NSources --> number of sources. +// pSources --> pointer to sources, (d*N). +// NumClusters --> number of clusters. +// +// OUTPUT +// ---------------- +// +// MaxClusterRadius --> maximum radius of the clusters, (rx). +// pClusterIndex --> vector of length N where the i th element is the +// cluster number to which the i th point belongs. +// pClusterIndex[i] varies between 0 to K-1. +// pClusterCenters --> pointer to the cluster centers, (d*K). +// pNumPoints --> pointer to the number of points in each cluster, (K). +// pClusterRadii --> pointer to the radius of each cluster, (K). +//---------------------------------------------------------------------------- + +#ifndef K_CENTER_CLUSTERING_H +#define K_CENTER_CLUSTERING_H + +class KCenterClustering{ + public: + + //Output parameters + + double MaxClusterRadius; //maximum cluster radius + + //Functions + + //constructor + KCenterClustering(int Dim, + int NSources, + double *pSources, + int *pClusterIndex, + int NumClusters + ); + + //destructor + ~KCenterClustering(); + + //K-center clustering + //Returns the number of actual clusters (it might have stopped early if all clusters have + // radius of 0 -- which means that the number of clusters has reached the number + // of unique pts) + int Cluster(); + + //Incremental k-center clustering + // nClusters - if non-NULL, value is set to the # of clusters at end of call + // maxRadius - if non-NULL, value is set to the max radius of all clusters + void ClusterIncrement( int * nClusters, double * maxRadius ); + + //Compute cluster centers and the number of points in each cluster + //and the radius of each cluster. + void ComputeClusterCenters( int NumClusters, + double *pClusterCenters, + int *pNumPoints, + double *pClusterRadii + ); + + private: + //Input Parameters + + int d; // dimension of the points. + int N; // number of sources. + double *px; // pointer to sources, (d*N). + int K; // max number of clusters + int *pci; // pointer to a vector of length N where the i th element is the + // cluster number to which the i th point belongs. + double *dist_C; // distances to the center. + double *r; + + int *pCenters; // indices of the centers. + int *cprev; // index to the previous node + int *cnext; // index to the next node + int *far2c; // farthest node to the center + + int numClusters; // added by Vlad to keep track of # of clusters + + //Functions + double ddist(const int d, const double *x, const double *y); + int idmax(int n, double *x); + +}; + + +#endif diff --git a/dep/figtree/LICENSE b/dep/figtree/LICENSE new file mode 100644 index 00000000..20b5fa47 --- /dev/null +++ b/dep/figtree/LICENSE @@ -0,0 +1,26 @@ +FIGTree: Fast Improved Gauss Transform with Tree Data Structure LICENSE + +This code extends Vikas Raykar's version of the IFGT code, which +was provided under the GNU Lesser General Public License (LGPL). +As a result, the FIGTree library is also released under the LGPL. + +IMPROVED FAST GAUSS TRANSFORM (IFGT) LICENSE + +Copyright Information The code was written by Vikas C. Raykar and Changjiang Yang +is copyrighted under the Lesser GPL: + +Copyright (C) 2006 Vikas C. Raykar and Changjiang Yang + +This program 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; version 2.1 or later. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. You should +have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. The author may +be contacted via email at: vikas (at) umiacs (.) umd (.) edu and +cyang (at) sarnoff (.) com. + diff --git a/dep/figtree/figtree.cpp b/dep/figtree/figtree.cpp new file mode 100755 index 00000000..497c1f99 --- /dev/null +++ b/dep/figtree/figtree.cpp @@ -0,0 +1,3044 @@ +// File: figtree.cpp +// Created: 11-03-06 by Vlad Morariu +// +// Modified: 6-22-07 by Vlad Morariu +// Initial changes from previous version of the IFGT code (written by Vikas C. +// Raykar and Changjiang Yang) and FIGTree code (written by Vikas C. Raykar). +// +// Modifications include: +// 1) Code can compile into a dynamic library that provides C-style interface +// without requiring Matlab. +// +// 2) Added an improved parameter selection method that removes assumption that +// sources are uniformly distributed (observed large speedup in cases where +// sources were not uniformly distributed, and often little slowdown from +// overhead when the sources were actually uniformly distributed). +// +// 3) Changed the IFGT code to take multiple sets of weights for same set of +// sources and targets instead of having to call IFGT code multiple times. +// By computing a set of coefficients for each weight set, much overhead is +// saved (eg. computing monomials, and so on), resulting in significant +// speedup. +// +// 4) Added function (figtree()) that performs all parameter selection/clustering +// using any choice of parameter selection and evaluation algorithms. +// +// 5) Some bugs/problem cases were fixed (some bugs caused seg faults, others +// were certain problem cases that could result in bad parameter selection +// and, as a result, memory allocation errors or seg faults). +// +// 6) In the original implementation, most code resided in the constructor and +// Evaluate() functions of a class, and was actually called in sequential +// order as if it were a C function (thus not using any real advantages of +// C++ classes). Thus, all code except for that of KCenterClustering, which +// seems to fit better in a class, has been put in C-style functions inside +// of figtree.cpp. The original location of the original source is indicated +// in figtree.cpp before each function. +// +// 7) Stylistic changes (eg. variable naming conventions, function names, ...) +// +// Modified: 9-23-07 by Vlad Morariu +// Change code to compile on linux and solaris. +// +// Modified: 10-03-07 by Vlad Morariu +// Remove requirement that data is in unit hypercube by adding +// maxRange parameter to figtreeChoose* functions. +// +// Modified: 01-22-08 by Vlad Morariu +// Rename library to FIGTree (and some +// other function remanimg) +// +// Modified: 02-20-08 by Vlad Morariu +// Added nchoosek_double function to use 'double' instead of 'int' to prevent +// overflow issues. The overflow would cause incorrect parameter estimation +// which then resulted in out of memory errors. +// +// Modified: 02-21-08 by Vlad Morariu +// Allow rx to be zero (each pt has a cluster center on it), and allow +// figtreeChooseParametersNonUniform to choose a value of K that gives rx=0. +// In some cases in higher dimensions, it is significantly cheaper to have +// a center at each pt (i.e. rx=0) than having even one cluster with nonzero +// radius (since the radius might require excessively high pMax). +// Also added FIGTREE_CHECK_POS_DOUBLE macro to allow rx to be zero when +// checking input parameters. +// +// Modified: 05-03-08 by Vlad Morariu +// Add method selection code. This set of functions uses a tree data structure +// and k-center clustering to estimate number of source neighbors, target neighbors, +// and ifgt parameters, which then allows us to estimate how much it would cost +// to evaluate using any of direct, direct+tree, ifgt, or ifgt+tree. +// +// Modified: 05-27-08 by Vlad Morariu +// Change figtreeChooseParameters* and figtreeChooseTruncationNumber functions +// to return the predicted errorBound. This can then be used to check if +// the parameters chosen will satisfy the desired error bound (they may not +// since we enforce a limit on pMax (the truncation number). +// +// Modified: 05-29-08 by Vlad Morariu +// Fixed a small computational error in the error bound (when choosing truncation +// number). Because the bounds are loose, the desired error was still met even +// with the computation error. +// +// Modified: 05-29-08 to 06-10-08 by Vlad Morariu +// A few changes were made: +// 1) Added code to choose individual truncation numbers for both targets and sources +// using pointwise error bounds. +// 2) Added code to choose individual truncation numbers for targets and sources +// using clusterwise error bounds. +// 3) Reuse K-center clustering computed during method selection if +// FIGTREE_EVAL_AUTO is chosen. +// 4) Changed ANN code to compute unordered nearest neighbors, saving time +// by not using a priority queue and also because now the fixed radius +// nearest neighbor computation and retrieval is done in one step, +// instead of first finding # of nn's and then doing the search again to +// retrieve the nn's. This really speeds up direct+tree since the ANN +// priority queue was implemented using insertion sort. +// +// Modified: 11-02-08, 12-01-08 to 12-05-08 by Vlad Morariu +// Made some revisions before posting new version online. +// 1) Changed interface of figtree so users can choose truncation method +// (also changed figtree() to automatically revert to the simplest +// truncation method in cases where the two more complex methods +// cannot give a speedup). +// 2) Revised some comments +// 3) Found all parameters used throughout code and defined constants for them +// so that users can change them and recompile. In future releases, +// these should only be defaults, and users should be able to modify them +// at runtime. +// 4) Removed most helper functions from figtree.h (all but figtree(), +// figtreeChooseEvaluationMethod(), and figtreeKCenterClustering() ) and +// placed them in figtree_internal.h. +// 5) Changed floating op estimation functions to reflect revised versions +// of code +// +// Modified: 2010/05/12 by Vlad Morariu +// Added stdlib.h and string.h includes to for exit(), strcmp(), memset(), etc. +// (they used to be implicitly included by gcc headers, but they are not anymore). +// +// +//------------------------------------------------------------------------------ +// The code was written by Vlad Morariu, Vikas Raykar, and Changjiang Yang +// and is copyrighted under the Lesser GPL: +// +// Copyright (C) 2008 Vlad Morariu and Vikas Raykar and Changjiang Yang +// +// This program 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; version 2.1 or later. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. +// +// The author may be contacted via email at: +// morariu(at)umd(.)edu, vikas(at)umiacs(.)umd(.)edu, cyang(at)sarnoff(.)com +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Parameters used by the algorithm +// +// Currently, the code must be recompiled when these parameters are changed. +// In future releases, users should be able to dynamically set these at runtime. +// +// FLOPS_EXP is especially important since each processor might have different +// values for this, which will affect prediction performance +//------------------------------------------------------------------------------ + +#define P_UPPER_LIMIT 100 // upper limit on truncation numbers +//#define C_UPPER_LIMIT 536870912 // upper limit for total amt of memory + // coefficients can use... NOT USED FOR NOW + +// these parameters are all for the method selection portion of the code +#define M_SAMPLE 50 // number of queries when querying tree +#define N_SS_MIN 100 // min number of source samples +#define N_SS_POW .75 // the exponent for determining size of + // subsampled set Nss = N^N_SS_POW +#define K_LIMIT_TO_AVG_NBR_RATIO 2 // the max K we allow as ratio of avg source neighbors +#define FLOPS_EXP 28 // how many floating point ops does exp() + // take (machine dependent) + +//------------------------------------------------------------------------------ +// headers +//------------------------------------------------------------------------------ +#define _SECURE_SCL 0 + +#include "figtree.h" +#include "figtree_internal.h" + +#include // for definition of NULL +#include // for rounding (floor) +#include // for printf +#include // for memset() + +#include // for lower_bound and random_sample +#include // for greater + +#include "KCenterClustering.h" // provides class for KCenterClustering + +#ifndef FIGTREE_NO_ANN +#include "ANN.h" // ANN library used for kd-tree in FIGTree code +#endif + +#ifndef INT_MAX +#include +#endif + +#ifndef DBL_MAX +#include +#endif + +// define MAX and MIN if not yet defined +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b) ) +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b) ) +#endif + +//------------------------------------------------------------------------------ +// change some functions (printf, new, delete) to use Matlab functions +// instead if we are compiling library for use in matlab mex file. +//------------------------------------------------------------------------------ +#ifdef FIGTREE_USE_MATLAB_MEX +#include "mex.h" + +// use mexPrintf instead of printf for messages +#undef printf +#define printf mexPrintf + +/* +//Commented this out because when ANN is compiled as part of the same DLL +//it uses the 'new()' definition below, which significantly slows it down. +//I am not sure why the code in the ANN source files uses the 'new()' +//definition in figtree.cpp. +inline +void * operator new (size_t size) +{ + void *p=mxMalloc(size); + return p; +} + +inline +void operator delete (void *p) +{ + mxFree(p); +} +*/ +#endif + +//------------------------------------------------------------------------------ +// define some macros to use for checking values of input args +// without the macros, all the if statements take up a lot of space +//------------------------------------------------------------------------------ +#define FIGTREE_CHECK_POS_NONZERO_DOUBLE( VAR, FCN ) \ + if( (VAR) <= 0.0 ) \ + { \ + printf( #FCN ": Input '" #VAR "' must be a positive number.\n"); \ + return -1; \ + } + +#define FIGTREE_CHECK_POS_DOUBLE( VAR, FCN ) \ + if( (VAR) < 0.0 ) \ + { \ + printf( #FCN ": Input '" #VAR "' must be a positive number.\n"); \ + return -1; \ + } + +#define FIGTREE_CHECK_POS_NONZERO_INT( VAR, FCN ) \ + if( (VAR) <= 0.0 ) \ + { \ + printf( #FCN ": Input '" #VAR "' must be a positive number.\n"); \ + return -1; \ + } + +#define FIGTREE_CHECK_NONNULL_PTR( VAR, FCN ) \ + if( (VAR) == NULL ) \ + { \ + printf( #FCN ": Input pointer '" #VAR "' is NULL.\n"); \ + return -1; \ + } + +#ifndef ANN_H +#define ANNpointArray void* +#define ANNkd_tree void* +#endif + +typedef struct _FigtreeData +{ +// // general params - not used yet, but will be used when saving data-structured for multiple calls +// int d; +// int N; +// int M; +// int W; +// double epsilon; +// double * x; +// double h; +// double * q; +// double * y; + + // params for IFGT + int pMax; + int pMaxTotal; + int K; + int * clusterIndex; + double * clusterCenters; + double * clusterRadii; + int * numPoints; + double r; + double rx; + + // params for IFGT + Tree + ANNpointArray annClusters; + ANNkd_tree * annClustersKdTree; + + // params for Direct + Tree + ANNpointArray annSources; + ANNkd_tree * annSourcesKdTree; + +} FigtreeData; + +FigtreeData figtreeCreateData() +{ + FigtreeData data; + + data.pMax = 0; + data.pMaxTotal = 0; + data.K = 0; + data.clusterIndex = NULL; + data.clusterCenters = NULL; + data.clusterRadii = NULL; + data.numPoints = NULL; + data.r = 0; + data.rx = 0; + + data.annClusters = NULL; + data.annClustersKdTree = NULL; + + data.annSources = NULL; + data.annSourcesKdTree = NULL; + + return data; +} + +void figtreeReleaseData( FigtreeData * data ) +{ + data->pMax = 0; + data->pMaxTotal = 0; + data->K = 0; + if( data->clusterIndex != NULL ) + { + delete [] data->clusterIndex; + data->clusterIndex = NULL; + } + if( data->clusterCenters != NULL ) + { + delete [] data->clusterCenters; + data->clusterCenters = NULL; + } + if( data->clusterRadii != NULL ) + { + delete [] data->clusterRadii; + data->clusterRadii = NULL; + } + if( data->numPoints != NULL ) + { + delete [] data->numPoints; + data->numPoints = NULL; + } + data->r = 0; + data->rx = 0; + +#ifndef FIGTREE_NO_ANN + if( data->annClusters != NULL ) + { + annDeallocPts(data->annClusters); + data->annClusters = NULL; + } + if( data->annClustersKdTree != NULL ) + { + delete data->annClustersKdTree; + data->annClustersKdTree = NULL; + } + + if( data->annSources != NULL ) + { + annDeallocPts(data->annSources); + data->annSources = NULL; + } + if( data->annSourcesKdTree != NULL ) + { + delete data->annSourcesKdTree; + data->annSourcesKdTree = NULL; + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Helper functions (their prototpyes do not appear in the header file). +//////////////////////////////////////////////////////////////////////////////// + +//------------------------------------------------------------------------------ +// Compute the combinatorial number nchoosek. +// Originally from ImprovedFastGaussTransform.cpp (IFGT source code) +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +int nchoosek(int n, int k) +{ + int n_k = n - k; + + if (k < n_k) + { + k = n_k; + n_k = n - k; + } + + int nchsk = 1; + for ( int i = 1; i <= n_k; i++) + { + nchsk *= (++k); + nchsk /= i; + } + + return nchsk; +} + +//------------------------------------------------------------------------------ +// Compute the combinatorial number nchoosek, using double precision. +// This prevents some overflow issues for large n. +// +// Created by Vlad Morariu on 2008-02-20. +//------------------------------------------------------------------------------ +double nchoosek_double(int n, int k) +{ + int n_k = n - k; + + if (k < n_k) + { + k = n_k; + n_k = n - k; + } + + double nchsk = 1; + for ( int i = 1; i <= n_k; i++) + { + nchsk *= (++k); + nchsk /= i; + } + + return nchsk; +} + +//------------------------------------------------------------------------------ +// This function computes the constants 2^alpha/alpha!. +// Originally compute_constant_series from ImprovedFastGaussTransform.cpp (IFGT +// source code). +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +void computeConstantSeries( int d, int pMaxTotal, int pMax, double * constantSeries ) +{ + int *heads = new int[d+1]; + int *cinds = new int[pMaxTotal]; + + for (int i = 0; i < d; i++) + heads[i] = 0; + heads[d] = INT_MAX; + + cinds[0] = 0; + constantSeries[0] = 1.0; + for (int k = 1, t = 1, tail = 1; k < pMax; k++, tail = t) + { + for (int i = 0; i < d; i++) + { + int head = heads[i]; + heads[i] = t; + for ( int j = head; j < tail; j++, t++) + { + cinds[t] = (j < heads[i+1])? cinds[j] + 1 : 1; + constantSeries[t] = 2.0 * constantSeries[j]; + constantSeries[t] /= (double) cinds[t]; + } + } + } + + delete [] cinds; + delete [] heads; +} + +//------------------------------------------------------------------------------ +// This function computes the monomials [(x_i-c_k)/h]^{alpha} and +// norm([(x_i-c_k)/h])^2. +// Originally compute_source_center_monomials from +// ImprovedFastGaussTransform.cpp (IFGT source code). +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +void computeSourceCenterMonomials( int d, double h, double * dx, + int p, double * sourceCenterMonomials ) +{ + int * heads = new int[d]; + + for (int i = 0; i < d; i++) + { + dx[i]=dx[i]/h; + heads[i] = 0; + } + + sourceCenterMonomials[0] = 1.0; + for (int k = 1, t = 1, tail = 1; k < p; k++, tail = t) + { + for (int i = 0; i < d; i++) + { + int head = heads[i]; + heads[i] = t; + for ( int j = head; j < tail; j++, t++) + sourceCenterMonomials[t] = dx[i] * sourceCenterMonomials[j]; + } + } + + delete [] heads; +} + +//------------------------------------------------------------------------------ +// This function computes the monomials [(y_j-c_k)/h]^{alpha} +// Originally compute_target_center_monomials from +// ImprovedFastGaussTransform.cpp (IFGT source code). +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +void computeTargetCenterMonomials( int d, double h, double * dy, + int pMax, double * targetCenterMonomials ) +{ + int *heads = new int[d]; + + for (int i = 0; i < d; i++) + { + dy[i] = dy[i]/h; + heads[i] = 0; + } + + targetCenterMonomials[0] = 1.0; + for (int k = 1, t = 1, tail = 1; k < pMax; k++, tail = t) + { + for (int i = 0; i < d; i++) + { + int head = heads[i]; + heads[i] = t; + for ( int j = head; j < tail; j++, t++) + targetCenterMonomials[t] = dy[i] * targetCenterMonomials[j]; + } + } + + delete [] heads; +} +//------------------------------------------------------------------------------ +// Given error(a,b,p) = (2^p/p!) * (a/h)^p * (b/h)^p * e^(-(a-b)^2/h^2), +// calculates the maximum error given only a and the maximum possible b value +// a - radius of source (target) point +// b_max - maximum radius of target (source) point +// c - constant term (2^p/p!) +// h2 - bandwidth, squared +// p - truncation number +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +inline +double figtreeOneSidedErrorBound( double a, double b_max, double c, double h2, int p ) +{ + double b = MIN( b_max, .5*(a + sqrt(a*a + 2*p*h2)) ); // this is the value of at which error(a,b,p) reaches maximum for a given 'a' and 'p' + double d_ab = a-b; + return c * pow(a*b/h2,p) * exp( -d_ab*d_ab/h2 ); +} + + +//------------------------------------------------------------------------------ +// Let error(a,b_max,p) = (2^p/p!) * (a/h)^p * (b/h)^p * e^(-(a-b)^2/h^2). This function +// finds radius values of lo_out and hi_out such that error(a_lo,b_max,p) <= epsilon < error(a_hi,b_max,p) +// We assume that the input arguments a_hi and a_lo initially satisfy this property. +// a - radius of source (target) point +// b_max - maximum radius of target (source) point +// c - constant term (2^p/p!) +// h2 - bandwidth, squared +// p - truncation number +// epsilon - desired error bound +// max_it - number of iterations of halving the interval [lo,hi] +// +// Created by Vlad Morariu on 2008-06-04 +//------------------------------------------------------------------------------ +void figtreeFindRadiusBounds( double a_lo, double a_hi, double b_max, + double c, double h2, int p, double epsilon, + int max_it, double * lo_out, double * hi_out ) +{ + // compute bounds at hi + bool sat_hi = (figtreeOneSidedErrorBound( a_hi, b_max, c, h2 ,p ) <= epsilon); + if( sat_hi ) + { + // the bounds are already satisfied even at a_hi, where error is highest + *hi_out = a_hi; + *lo_out = a_hi; + } + else + { + bool sat_lo = (figtreeOneSidedErrorBound( a_lo, b_max, c, h2 ,p ) <= epsilon); + if( !sat_lo ) + { + // the bounds are not satisfied at a_lo (and since we assume error to increase + // monotonically from a_lo to a_hi, it is not satisfied in this range) + *hi_out = a_hi; + *lo_out = 2*a_lo - a_hi; // go a little past a_lo to signal that not even a_lo satisfied error + } + else + { + for( int i = 0; i < max_it; i++ ) + { + double a_mid = .5*(a_lo + a_hi); + bool sat_mid = (figtreeOneSidedErrorBound( a_mid, b_max, c, h2 ,p ) <= epsilon); + if( sat_mid ) // move the lo or hi value to keep property that error is not satisfied at a_hi, but is satisfied at a_lo + a_lo = a_mid; + else + a_hi = a_mid; + } + *hi_out = a_hi; + *lo_out = a_lo; + } + } +} + + +//------------------------------------------------------------------------------ +// This function precomputes, for each truncation number, the range in the +// distance of a source from the cluster center so that error is still satisfied. +// This is used in the point-wise adaptive version of the IFGT. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void figtreeSourceTruncationRanges( double r, double rx, double h, double epsilon, int pMax, double * max_source_dists2 ) +{ + double h2 = h*h; + for( int i = 0; i < pMax-1; i++ ) + max_source_dists2[i] = -1; // negative numbers indicate no distance satisfies error bounds for the particular value of p + max_source_dists2[pMax-1] = rx; + + double c = 1; + for( int i = 0; i < pMax-1; i++ ) + { + c *= (2.0/(i+1)); + double a_lo = 0, a_hi = rx; + figtreeFindRadiusBounds( a_lo, a_hi, r + rx, c, h2, i+1, epsilon, 10, &a_lo, &a_hi ); + max_source_dists2[i] = a_lo*a_lo; + } +} + +//------------------------------------------------------------------------------ +// This function precomputes, for each truncation number, the range in the +// distance of a target from the cluster center so that error is still satisfied. +// This is used in the point-wise adaptive version of the IFGT. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void figtreeTargetTruncationRanges( double r, double rx, double h, double epsilon, int pMax, double * max_target_dists2, double * min_target_dists2 ) +{ + double h2 = h*h; + double ry = r + rx; + for( int i = 0; i < pMax-1; i++ ) + { + max_target_dists2[i] = -1; + min_target_dists2[i] = ry*ry+1; + } + + double c = 1; + for( int i = 0; i < pMax-1; i++ ) + { + c *= (2.0/(i+1)); + + double peak_dist = .5*(rx + sqrt( rx*rx + 2*h2*(i+1) )); + + // here we calculate for each value of p the maximum distance from a cluster center + // that a target can be to satisfy the error bounds, provided the distance is + // in the portion of the error bound that monotonically increases with distance + double a_lo = 0, a_hi = MIN(ry,peak_dist); + figtreeFindRadiusBounds( a_lo, a_hi, rx, c, h2, i+1, epsilon, 10, &a_lo, &a_hi ); + max_target_dists2[i] = a_lo*a_lo; + + // here we calculate for each value of p the minimum distance from a cluster center + // that a target can be to satisfy the error bounds, provided the radius is + // in the portion of the error bound that monotonically increases with distance + if( peak_dist <= ry ) + { + a_lo = ry, a_hi = peak_dist; + figtreeFindRadiusBounds( a_lo, a_hi, rx, c, h2, i+1, epsilon, 10, &a_lo, &a_hi ); + min_target_dists2[i] = a_lo*a_lo; + } // otherwise we leave it at ry*ry+1 (it should have been initialized to this + + if( i > 0 && min_target_dists2[i] > min_target_dists2[i-1] ) + { + min_target_dists2[i] = min_target_dists2[i-1]; + } + } + if( pMax > 1 && min_target_dists2[pMax-1] > min_target_dists2[pMax-2] ) + { + min_target_dists2[pMax-1] = min_target_dists2[pMax-2]; + } + +} + + +//------------------------------------------------------------------------------ +// Given the precomputed distances from the cluster center for which +// the error bound is satisfied for each truncation number, and the actual +// distance from the cluster center, this function finds the lowest truncation +// number so that error is still satisfied. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +inline +int figtreeSourceTruncationNumber( double dx2, int pMax, double * max_source_dists2 ) +{ + return (int)(std::lower_bound( max_source_dists2, max_source_dists2 + pMax - 1, dx2) - max_source_dists2) + 1; +} + +//------------------------------------------------------------------------------ +// Given the precomputed distances from the cluster center for which +// the error bound is satisfied for each truncation number, and the actual +// distance from the cluster center, this function finds the lowest truncation +// number so that error is still satisfied. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +inline +int figtreeTargetTruncationNumber( double dy2, int pMax, double * max_target_dists2, double * min_target_dists2 ) +{ + if( dy2 <= max_target_dists2[pMax-2] ) + return (int)(std::lower_bound( max_target_dists2, max_target_dists2 + pMax - 1, dy2) - max_target_dists2) + 1; + else if( dy2 >= min_target_dists2[pMax-2] ) + return (int)(std::lower_bound( min_target_dists2, min_target_dists2 + pMax - 1, dy2, std::greater() ) - min_target_dists2) + 1; + else + return pMax; +} + +//------------------------------------------------------------------------------ +// This function computes the coefficients C_k for all clusters. +// Originally compute_C from ImprovedFastGaussTransform.cpp (IFGT source code) +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +void computeC( int d, int N, int W, int K, int pMaxTotal, int pMax, + double h, int * clusterIndex, double * x, double * q, + double * clusterCenter, double * C ) +{ + double * sourceCenterMonomials = new double[pMaxTotal]; + double * constantSeries = new double[pMaxTotal]; + double hSquare = h*h; + double * dx = new double[d]; + + for (int i = 0; i < W*K*pMaxTotal; i++) + { + C[i] = 0.0; + } + + for(int i = 0; i < N; i++) + { + int k = clusterIndex[i]; + int sourceBase = i*d; + int centerBase = k*d; + double sourceCenterDistanceSquare = 0.0; + + for (int j = 0; j < d; j++) + { + dx[j] = (x[sourceBase+j] - clusterCenter[centerBase+j]); + sourceCenterDistanceSquare += (dx[j]*dx[j]); + } + + computeSourceCenterMonomials( d, h, dx, pMax, sourceCenterMonomials ); + + for(int w = 0; w < W; w++ ) + { + double f = q[N*w + i]*exp(-sourceCenterDistanceSquare/hSquare); + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] += (f*sourceCenterMonomials[alpha]); + } + } + } + + computeConstantSeries( d, pMaxTotal, pMax, constantSeries ); + + for(int w = 0; w < W; w++) + { + for(int k = 0; k < K; k++) + { + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] *= constantSeries[alpha]; + } + } + } + + delete [] sourceCenterMonomials; + delete [] constantSeries; + delete [] dx; +} + +//------------------------------------------------------------------------------ +// This function computes a separate truncation number for each cluster that +// satisfies the total allowed cluster-wise error. This means that some +// sources are allowed to contribute more error as long as others contribute +// less. The speedup is observed mostly in higher dimensions since finding +// the cluster-wise truncation numbers adds to the overhead cost. The +// truncations for each cluster are found by doing a binary search over +// the truncation number, p. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) This function currently only works when only one set of weights 'q' +// are used (i.e. W=1). It can be extended to W>1, but I have not had +// time to clean up that part of the code for release yet. +// +// 2) Also, this function does not currently compute multiple 'regions' +// for targets where different cluster-wise truncation numbers are used +// depending on what region targets are in. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void figtreeFindClusterTruncations( int d, int N, double * x, double * q, double h, double epsilon, double r, int pMax, int K, int * clusterIndex, int * numPoints, double * clusterCenters, double * clusterRadii, int * clusterTruncations ) +{ + double * clusterWeights = new double[K]; + double * pointClusterDists = new double[N]; + double h2 = h*h; + + double * q_reordered = new double[N]; + + memset(clusterTruncations,0,sizeof(int)*K); + memset(clusterWeights,0,sizeof(double)*K); + memset(pointClusterDists,0,sizeof(double)*N); + + // find out total sum of weights for each cluster + for( int i = 0; i < N; i++ ) + clusterWeights[ clusterIndex[i] ] += fabs(q[i]); + + // precompute a list of points for each cluster so that we can reorganize + // some frequently used data in memory to make memory is accessed + // sequentially. + int * clusterMembers = new int[N]; + int * clusterStart = new int[K], * clusterEnd = new int[K]; + clusterStart[0] = 0; + clusterEnd[0] = clusterStart[0]; + for( int i = 1; i < K; i++ ) + { + clusterStart[i] = clusterStart[i-1] + numPoints[i-1]; + clusterEnd[i] = clusterStart[i]; + } + + for( int i = 0; i < N; i++ ) + clusterMembers[clusterEnd[clusterIndex[i]]++] = i; + + // compute the distance from points to clusters, and + // reorder them so that the weights 'q_reordered' and cluster + // distances 'pointClusterDists' for points that belong to the + // same cluster are contiguous in memory (reduces memory access overhead). + for( int k = 0; k < K; k++ ) + { + int start = clusterStart[k], end = clusterEnd[k]; + for( int i = start; i < end; i++ ) + { + q_reordered[i] = fabs(q[clusterMembers[i]]) / clusterWeights[k]; + for( int j = 0; j < d; j++ ) + { + double dx = clusterCenters[k*d+j] - x[clusterMembers[i]*d+j]; + pointClusterDists[i] += dx*dx; + } + pointClusterDists[i] = sqrt(pointClusterDists[i]); + } + } + + // precompute constant in front of error term that depends only on p + double * constants = new double[pMax]; + constants[0] = 2; + for( int p = 2; p <= pMax; p++ ) + constants[p-1] = constants[p-2]*2.0/p; + + // find the lowest p for each cluster such that the total error per cluster meets the error bound using + // a binary search based algorithm. If for some reason, there exists a p_i > p_j such that + // error is met for p_j but not for p_i, (i.e. the p's are not ordered), the resulting p is still guaranteed + // to satisfy error, though it may not be the lowest p that satisfies error. + for( int k = 0; k < K; k++ ) + { + int start = clusterStart[k], end = clusterEnd[k]; + + int p_lo = 1, p_hi = pMax; + while( p_lo < p_hi ) + { + int p_mid = (p_hi + p_lo)/2; + double clusterBound = 0; + for( int i = start; i < end && clusterBound <= epsilon; i++ ) + { + double error = q_reordered[i]*figtreeOneSidedErrorBound( pointClusterDists[i], clusterRadii[k]+r, constants[p_mid-1], h2 , p_mid ); + clusterBound += error; + } + + if( clusterBound > epsilon ) + p_lo = p_mid + 1; + else + p_hi = p_mid; + } + + clusterTruncations[k] = p_hi; + } + + delete [] constants; + delete [] clusterWeights; + delete [] pointClusterDists; + delete [] clusterMembers; + delete [] clusterStart; + delete [] clusterEnd; + delete [] q_reordered; +} + +//------------------------------------------------------------------------------ +// This function computes the cluster coefficients using a separate truncation +// number for each cluster that satisfies the total allowed cluster-wise error. +// The clusterwise truncation numbers are returned by the function +// figtreeFindClusterTruncations(). +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Because figtreeFindClusterTruncations() only takes one set of weights +// into account when computing cluster-wise truncations, this function +// will not give accurate results for multiple sets of weights (W>1). +// When figtreeFindClusterTruncations is modified to consider all W sets +// of weights, this function should work properly. Thus, W=1 is assumed +// for now even though it is part of the input arguments. +// +// 2) Also, this function does not currently use multiple 'regions' +// for targets where different cluster-wise truncation numbers are used +// depending on what region targets are in. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void computeCAdaptiveCluster( int d, int N, int W, int K, int pMaxTotal, int pMax, + double h, int * clusterIndex, double * x, double * q, + double * clusterCenter, int * clusterTruncations, int * pMaxTotals, double * C ) +{ + double * sourceCenterMonomials = new double[pMaxTotal]; + double * constantSeries = new double[pMaxTotal]; + double hSquare = h*h; + double * dx = new double[d]; + + memset( C, 0, sizeof(double)*W*K*pMaxTotal ); + + for(int i = 0; i < N; i++) + { + int k = clusterIndex[i]; + int sourceBase = i*d; + int centerBase = k*d; + double sourceCenterDistanceSquare = 0.0; + + for (int j = 0; j < d; j++) + { + dx[j] = (x[sourceBase+j] - clusterCenter[centerBase+j]); + sourceCenterDistanceSquare += (dx[j]*dx[j]); + } + + int p = clusterTruncations[k]; + int pTotal = pMaxTotals[p-1]; + computeSourceCenterMonomials( d, h, dx, p, sourceCenterMonomials ); + + for(int w = 0; w < W; w++ ) + { + double f = q[N*w + i]*exp(-sourceCenterDistanceSquare/hSquare); + for(int alpha = 0; alpha < pTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] += (f*sourceCenterMonomials[alpha]); + } + } + } + + computeConstantSeries( d, pMaxTotal, pMax, constantSeries ); + + for(int w = 0; w < W; w++) + { + for(int k = 0; k < K; k++) + { + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] *= constantSeries[alpha]; + } + } + } + + delete [] sourceCenterMonomials; + delete [] constantSeries; + delete [] dx; +} + +//------------------------------------------------------------------------------ +// This function computes the cluster coefficients allowing each source point +// to have a variable truncation number that still satisfies the desired error +// assuming the worst-case target point. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +void computeCAdaptivePoint( int d, int N, int W, int K, int pMaxTotal, int pMax, + double h, int * clusterIndex, double * x, double * q, + double * clusterCenter, double * maxSourceDists2, int * pMaxTotals, double * C ) +{ + double * sourceCenterMonomials = new double[pMaxTotal]; + double * constantSeries = new double[pMaxTotal]; + double hSquare = h*h; + double * dx = new double[d]; + + memset( C, 0, sizeof(double)*W*K*pMaxTotal ); + + //int * pHistogram = new int[pMax]; + //memset(pHistogram,0,sizeof(int)*pMax); + + for(int i = 0; i < N; i++) + { + int k = clusterIndex[i]; + int sourceBase = i*d; + int centerBase = k*d; + double sourceCenterDistanceSquare = 0.0; + + for (int j = 0; j < d; j++) + { + dx[j] = (x[sourceBase+j] - clusterCenter[centerBase+j]); + sourceCenterDistanceSquare += (dx[j]*dx[j]); + } + + int p = figtreeSourceTruncationNumber( sourceCenterDistanceSquare, pMax, maxSourceDists2 ); + int pTotal = pMaxTotals[p-1]; + //pHistogram[p-1]++; + computeSourceCenterMonomials( d, h, dx, p, sourceCenterMonomials ); + + for(int w = 0; w < W; w++ ) + { + double f = q[N*w + i]*exp(-sourceCenterDistanceSquare/hSquare); + for(int alpha = 0; alpha < pTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] += (f*sourceCenterMonomials[alpha]); + } + } + } + + computeConstantSeries( d, pMaxTotal, pMax, constantSeries ); + + for(int w = 0; w < W; w++) + { + for(int k = 0; k < K; k++) + { + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + C[(K*w + k)*pMaxTotal + alpha] *= constantSeries[alpha]; + } + } + } + + //printf( "source p histogram: "); + //for( int i = 0; i < pMax; i++ ) + // printf( " %i", pHistogram[i] ); + //printf( "\n" ); + //delete [] pHistogram; + + delete [] sourceCenterMonomials; + delete [] constantSeries; + delete [] dx; +} + +//------------------------------------------------------------------------------ +// This function provides a simple interface for evaluation of gauss transforms +// in several ways (direct, direct with approximate nearest-neighbors +// structure on sources, ifgt, and ifgt with approximate nearest-neighbors) and +// using different parameter selection methods (can assume uniform distribution +// or use the actual distribution in estimating parameters). +// +// Created by Vlad Morariu on 2006-11-03. +// +// Modified by Vlad Morariu on 2007-06-21. +// +// Modified by Vlad Morariu on 2008-06-04. +// +// - Added changes described in 'Automatic online tuning for fast Gaussian +// summation,' by Morariu et al, NIPS 2008 for details). +// - added FIGTREE_EVAL_AUTO eval method which allows FIGTREE to pick +// the evaluation method that is predicted to be the fastest, making +// FIGTREE a black box apprach +// - added point-wise and cluster-wise adaptive versions of the IFGT (instead +// of using the max truncation number for all sources, clusters, and targets, +// the truncation number is varied either point-wise or cluster-wise to improve +// performance while still satisfying the desired error bound). +// +// Modified by Vlad Morariu on 2008-12-01 +// - add a third parameter ifgtTruncMethod to reduce the number of evalMethod +// possibilities, separating evaluation method from truncation number choices +// - removed 'forceK' option, since it was used only for debugging +//------------------------------------------------------------------------------ +int figtree( int d, int N, int M, int W, double * x, double h, + double * q, double * y, double epsilon, double * g, + int evalMethod, int ifgtParamMethod, int ifgtTruncMethod, int verbose ) +{ + int ret = 0; + + FigtreeData data = figtreeCreateData(); + + // if the evalMethod is FIGTREE_EVAL_AUTO, choose the method that is estimated to be the fastest + if( evalMethod == FIGTREE_EVAL_AUTO ) + { + ret = figtreeChooseEvaluationMethod( d, N, M, W, x, h, y, epsilon, ifgtParamMethod, verbose, &evalMethod, NULL, &data ); + } + + // for FIGTREE_EVAL_DIRECT and FIGTREE_EVAL_DIRECT_TREE, we don't need to compute + // parameters, so we just run the fcns directly, once for each set of weights + if( evalMethod == FIGTREE_EVAL_DIRECT ) + { + verbose && printf("figtreeEvalMethod() chose the direct method.\n"); + for( int i = 0; i < W; i++ ) + ret = figtreeEvaluateDirect( d, N, M, x, h, q+i*N, y, g+i*M ); + } + + if( evalMethod == FIGTREE_EVAL_DIRECT_TREE ) + { + verbose && printf("figtreeEvalMethod() chose direct+tree method.\n"); + for( int i = 0; i < W; i++ ) + ret = figtreeEvaluateDirectTree( d, N, M, x, h, q+i*N, y, epsilon, g+i*M ); + } + + // for FIGTREE_EVAL_IFGT and FIGTREE_EVAL_IFGT_TREE, we must first compute + // parameters + if( evalMethod == FIGTREE_EVAL_IFGT || + evalMethod == FIGTREE_EVAL_IFGT_TREE ) + { + if(verbose && evalMethod == FIGTREE_EVAL_IFGT) + verbose && printf("figtreeEvalMethod() chose the IFGT method.\n"); + if(verbose && evalMethod == FIGTREE_EVAL_IFGT_TREE) + verbose && printf("figtreeEvalMethod() chose the IFGT+tree method.\n"); + + bool alreadyHaveClustering = (data.clusterCenters != NULL); // quick and dirty test + double maxRange = 0; + if( !alreadyHaveClustering ) + { + int kLimit = N, kMax; + + // + // calculate R, the diameter of the hypercube that encompasses sources and targets + // + double * mins = new double[d]; + double * maxs = new double[d]; + figtreeCalcMinMax( d, N, x, mins, maxs, 0 ); + figtreeCalcMinMax( d, M, y, mins, maxs, 1 ); + figtreeCalcMaxRange( d, mins, maxs, &maxRange ); + delete [] mins; + delete [] maxs; + + // + // choose parameters for IFGT + // + if( ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM ) + ret = figtreeChooseParametersNonUniform( d, N, x, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + else + ret = figtreeChooseParametersUniform( d, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + if( ret < 0 ) + { + printf("figtree: figtreeChooseParameters%sUniform() failed.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : "")); + return ret; + } + + verbose && printf("figtreeChooseParameters%sUniform() chose p=%i, k=%i.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : ""), data.pMax, kMax ); + + // + // do k-center clustering + // + data.clusterIndex = new int[N]; + data.numPoints = new int[kMax]; + data.clusterCenters = new double[d*kMax]; + data.clusterRadii = new double[kMax]; + + ret = figtreeKCenterClustering( d, N, x, kMax, &data.K, &data.rx, data.clusterIndex, + data.clusterCenters, data.numPoints, data.clusterRadii ); + if( ret < 0 ) + printf("figtree: figtreeKCenterClustering() failed.\n"); + } + + double errorBound = epsilon + 1; + if( ret >= 0 && !alreadyHaveClustering ) + { + // choose truncation number again now that clustering is done + ret = figtreeChooseTruncationNumber( d, h, epsilon, data.rx, maxRange, &data.pMax, &errorBound ); + if( ret < 0 ) + printf("figtreeChooseTruncatoinNumber() failed.\n"); + else + { + if( verbose && errorBound > epsilon ) + printf("figtreeChooseTruncationNumber(): could not find p within limit that satisfies error bound!\n" ); + } + } + + if( ret >= 0 ) + { + // evaluate IFGT + verbose && printf( "Eval IFGT(h= %3.2e, pMax= %i, K= %i, r= %3.2e, rx= %3.2e, eps= %3.2e)\n", + h, data.pMax, data.K, data.r, data.rx, epsilon); + + // if maximum truncation is 1, then nothing can be gained by doing individual truncations + if( data.pMax == 1 && (ifgtTruncMethod != FIGTREE_TRUNC_MAX) ) + { + evalMethod = FIGTREE_EVAL_IFGT; + verbose && printf("figtree(): max truncation is 1, so adaptive truncations are unnecessary.\n Switching to FIGTREE_TRUNC_MAX...\n"); + } + + // if W>1, and we want to use adaptive truncations, we cannot use cluster-wise truncations yet + if( W > 1 && (ifgtTruncMethod == FIGTREE_TRUNC_CLUSTER ) ) + { + ifgtTruncMethod = FIGTREE_TRUNC_POINT; + verbose && printf( "figtree(): FIGTREE_TRUNC_CLUSTER is not yet implemented\n to handle W > 1. Switching to FIGTREE_TRUNC_POINT...\n"); + } + + if( evalMethod == FIGTREE_EVAL_IFGT && ifgtTruncMethod == FIGTREE_TRUNC_POINT ) + { + ret = figtreeEvaluateIfgtAdaptivePoint( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( evalMethod == FIGTREE_EVAL_IFGT_TREE && ifgtTruncMethod == FIGTREE_TRUNC_POINT ) + { + ret = figtreeEvaluateIfgtTreeAdaptivePoint( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( ifgtTruncMethod == FIGTREE_TRUNC_CLUSTER ) + { + int * clusterTruncations = new int[data.K]; + figtreeFindClusterTruncations( d, N, x, q, h, epsilon, data.r, data.pMax, data.K, data.clusterIndex, data.numPoints, data.clusterCenters, data.clusterRadii, clusterTruncations ); + int pMaxNew = 0; + for( int i = 0; i < data.K; i++ ) + pMaxNew = MAX(pMaxNew, clusterTruncations[i]); + if( evalMethod == FIGTREE_EVAL_IFGT ) + { + ret = figtreeEvaluateIfgtAdaptiveCluster( d, N, M, W, x, h, q, y, pMaxNew, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, clusterTruncations, g ); + } + else // evalMethod == FIGTREE_EVAL_IFGT_TREE + { + ret = figtreeEvaluateIfgtTreeAdaptiveCluster( d, N, M, W, x, h, q, y, pMaxNew, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, clusterTruncations, g ); + } + + delete [] clusterTruncations; + } + + if( evalMethod == FIGTREE_EVAL_IFGT && ifgtTruncMethod == FIGTREE_TRUNC_MAX ) + { + ret = figtreeEvaluateIfgt( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( evalMethod == FIGTREE_EVAL_IFGT_TREE && ifgtTruncMethod == FIGTREE_TRUNC_MAX ) + { + ret = figtreeEvaluateIfgtTree( d, N, M, W, x, h, q, y, data.pMax, data.K, data.clusterIndex, + data.clusterCenters, data.clusterRadii, data.r, epsilon, g ); + } + + if( ret < 0 ) + { + printf("figtree: figtreeEvaluateIfgt%s*() failed.\n", + ((evalMethod == FIGTREE_EVAL_IFGT_TREE) ? "Tree" : "")); + } + } + } // if we are doing IFGT + + // release data if any was allocated + figtreeReleaseData( &data ); + + return ret; +} + +//------------------------------------------------------------------------------ +// Chooses minimum truncation number that satisfies desired error, given +// the maximum radius of any cluster (rx). +// +// Originally constructor from +// ImprovedFastGaussTransformChooseTruncationNumber.cpp (IFGT source code) by +// Vikas C. Raykar. +// +// Modified by Vlad Morariu on 2007-06-20 +// Modified by Vlad Morariu on 2007-10-03 - pass R (the max distance between +// any source and target) as argument instead of assuming that data fits +// in unit hypercube +//------------------------------------------------------------------------------ +int figtreeChooseTruncationNumber( int d, double h, double epsilon, + double rx, double maxRange, int * pMax, double * errorBound ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_DOUBLE( rx, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( maxRange, figtreeChooseTruncationNumber ); + FIGTREE_CHECK_NONNULL_PTR( pMax, figtreeChooseTruncationNumber ); + + double R = maxRange*sqrt((double)d); + double hSquare = h*h; + double r = MIN(R, h*sqrt(log(1/epsilon))); + double rxSquare = rx*rx; + + double error = epsilon + 1; + double temp = 1; + int p = 0; + /* + while((error > epsilon) & (p <= P_UPPER_LIMIT)){ + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + r); + double c = rx - b; + temp = temp*(((2*rx*b)/hSquare)/p); + error = temp*(exp(-(c*c)/hSquare)); + } */ + while((error > epsilon) & (p <= P_UPPER_LIMIT)) + { + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + r); + double c = rx - b; + temp = 1; + for( int i = 1; i <= p; i++ ) + temp = temp*((2.0*rx*b/hSquare)/i); + error = temp*(exp(-(c*c)/hSquare)); + } + if( pMax != NULL ) + *pMax = p; + if( errorBound != NULL ) + *errorBound = error; + + return 0; +} + +//------------------------------------------------------------------------------ +// Parameter selection for the Improved Fast Gauss Transform (IFGT). +// +// Implementation based on: +// +// Fast computation of sums of Gaussians in high dimensions. +// Vikas C. Raykar, C. Yang, R. Duraiswami, and N. Gumerov, +// CS-TR-4767, Department of computer science, +// University of Maryland, Collegepark. +// +// Originally constructor from ImprovedFastGaussTransformChooseParameters.cpp +// by Vikas C. Raykar. (IFGT source code) +// +// Modified by Vlad Morariu on 2007-06-20 +// Modified by Vlad Morariu on 2007-10-03 - pass R (the max distance between +// any source and target) as argument instead of assuming that data fits +// in unit hypercube +// Modified by Vlad Morariu on 2008-06-04 - change the way bound is computed to +// be more precise +//------------------------------------------------------------------------------ +int figtreeChooseParametersUniform( int d, double h, double epsilon, + int kLimit, double maxRange, int * K, int * pMax, double * r, double * errorBound ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseParametersUniform ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeChooseParametersUniform ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( maxRange, figtreeChooseParametersUniform ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeChooseParametersUniform ); + FIGTREE_CHECK_POS_NONZERO_INT( kLimit, figtreeChooseParametersUniform ); + + double R = maxRange*sqrt((double)d); + double hSquare = h*h; + double complexityMin = DBL_MAX; + + // These variables will hold the values that will then be returned. + // We use temporary variables in case caller does not care about a variable + // and passes a NULL pointer. + int kTemp = 1; + int pMaxTemp = P_UPPER_LIMIT + 1; + double rTemp = MIN(R,h*sqrt(log(1/epsilon))); + double errorTemp = epsilon + 1; + + for(int i = 0; i < kLimit; i++) + { + double rx = maxRange*pow((double)i + 1,-1.0/(double)d); + double rxSquare = rx*rx; + double n = MIN(i + 1, pow(rTemp/rx,(double)d)); + double error = epsilon + 1; + double temp = 1; + int p = 0; + while((error > epsilon) & (p <= P_UPPER_LIMIT)) + { + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + rTemp); + double c = rx - b; + temp = 1; + for( int j = 1; j <= p; j++ ) + temp = temp*((2.0*rx*b/hSquare)/j); + error = temp*(exp(-(c*c)/hSquare)); + } + double complexity = (i + 1) + log((double)i + 1) + ((1 + n)*nchoosek_double(p - 1 + d, d)); + if (complexity < complexityMin ) + { + complexityMin = complexity; + kTemp = i + 1; + pMaxTemp = p; + errorTemp = error; + } + } + + // added this to catch case where desired error is never reached. + // The best thing is to have as many clusters and terms in the taylor + // series as possible (which will give lowest error) + if( errorTemp > epsilon ) + { + kTemp = kLimit; + } + + // set output variables to computed values + if( K != NULL ) + *K = kTemp; + if( pMax != NULL ) + *pMax = pMaxTemp; + if( r != NULL ) + *r = rTemp; + if( errorBound != NULL ) + *errorBound = errorTemp; + + return 0; +} + +//------------------------------------------------------------------------------ +// Parameter selection scheme that does not assume uniform distribution. +// In cases where sources are not uniformly distribution, this can lead to +// very large performance increases +// because as the number of clusters increases, the max radius of any cluster +// decreases MUCH faster than it would if the sources were uniformly distributed. +// This function is based on ImprovedFastGaussTransformChooseParameters.cpp from +// the IFGT source code, by Vikas C. Raykar. +// +// Initially created by Vlad Morariu on 2007-01-24. +// Modified by Vlad Morariu on 2007-06-20. +// Modified by Vlad Morariu on 2007-10-03 - pass R (the max distance between +// any source and target) as argument instead of assuming that data fits +// in unit hypercube +// Modified by Vlad Morariu on 2008-02-21 - allow rx to be zero. In some cases, +// if there isn't a center at each source pt to give rx=0, an excessively +// large pMax is needed, and it is faster to just have a center at each pt. +// Modified by Vlad Morariu on 2008-06-04 - change the way bound is computed to +// be more precise +// Modified by Vlad Morariu on 2008-12-05 - began changing function to incorporate +// memory limit for coefficient storage... not done yet +//------------------------------------------------------------------------------ +int figtreeChooseParametersNonUniform( int d, int N, double * x, + double h, double epsilon, int kLimit, double maxRange, + int * K, int * pMax, double * r, double * errorBound ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeChooseParametersNonUniform ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeChooseParametersNonUniform ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeChooseParametersNonUniform ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeChooseParametersNonUniform ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeChooseParametersNonUniform ); + FIGTREE_CHECK_POS_NONZERO_INT( kLimit, figtreeChooseParametersNonUniform ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( maxRange, figtreeChooseParametersNonUniform ); + + // allocate temporary memory, and set some variables + int * pClusterIndex = new int[N]; + KCenterClustering * kcc = new KCenterClustering( d, N, x, pClusterIndex, kLimit ); + + double R = maxRange*sqrt((double)d); + double hSquare = h*h; + double complexityMin = DBL_MAX; + double complexityLast = DBL_MAX; + + double rTemp = MIN(R,h*sqrt(log(1/epsilon))); + int kTemp = 1; + int pMaxTemp = P_UPPER_LIMIT + 1; + double errorTemp = epsilon + 1; + + int numClusters; + double rx; + + // Vlad 01/24/07 - add first cluster and get rx + kcc->ClusterIncrement( &numClusters, &rx ); + + // evaluate complexity for increasing values of K + for(int i = 0; i < kLimit; i++) + { + double rxSquare = rx*rx; + double n = MIN(i + 1, pow(rTemp/rx,(double)d)); + double error = epsilon + 1; + double temp = 1; + int p = 0; + /* + while((error > epsilon) & (p <= P_UPPER_LIMIT)) + { + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + rTemp); + double c = rx - b; + temp = temp*(((2*rx*b)/hSquare)/p); + error = temp*(exp(-(c*c)/hSquare)); + }*/ + //double memTotalC = 8*(i+1); // 8 is number of bytes, i+1 is K + while((error > epsilon) && (p <= P_UPPER_LIMIT) ) //&& (memTotalC <= C_UPPER_LIMIT) ) + { + p++; + double b = MIN(((rx + sqrt((rxSquare) + (2*p*hSquare)))/2), rx + rTemp); + double c = rx - b; + temp = 1; + for( int j = 1; j <= p; j++ ) + temp = temp*((2.0*rx*b/hSquare)/j); + error = temp*(exp(-(c*c)/hSquare)); + + //memTotalC *= (d+p); + //memTotalC /= p; + } + double complexity = d*(i + 1) + d*log((double)i + 1) + ((1 + n)*nchoosek_double(p - 1 + d, d)); + if ( (complexity < complexityMin) && (error <= epsilon)) + { + complexityMin = complexity; + kTemp = i + 1; + pMaxTemp = p; + errorTemp = error; + } + + // try to guess if we have gone past the minimum (the complexity function + // zigzags as we increase number of clusters, but if it goes up enough, + // we'll assume we've passed the global minimum). + // Also stop if truncation number is only 1 or if the max number of unique + // clusters are reached (rx = 0). + double nextComplexityEstimate = d*(i + 1) + d*log((double)i + 1) + ((1 + n)*nchoosek_double(p - 2 + d, d)); + if( (p == 1) || (rx <= 0) || ( nextComplexityEstimate > 2*complexityMin || complexity > 2*complexityMin ) ) + { + break; + } + + // add another cluster center, and get new max cluster radius + kcc->ClusterIncrement( &numClusters, &rx ); + complexityLast = complexity; + } + + // added this to catch case where desired error is never reached. + // The best thing is to have as many clusters and terms in the taylor + // series as possible (which will give lowest error) + if( errorTemp > epsilon ) + { + kTemp = kLimit; + } + + //printf("memLimit = %e, memTotalC = %e\n", (double)C_UPPER_LIMIT, kTemp*8*nchoosek_double(pMaxTemp-1+d,d)); + + // copy results + if( K != NULL ) + *K = kTemp; + if( pMax != NULL ) + *pMax = pMaxTemp; + if( r != NULL ) + *r = rTemp; + if( errorBound != NULL ) + *errorBound = errorTemp; + + delete [] pClusterIndex; + delete kcc; + + return 0; +} + +//------------------------------------------------------------------------------ +// This function is an interface to the C++ KCenterClustering class from the +// original IFGT library. +// +// Created by Vlad Morariu 2007-06-19. +//------------------------------------------------------------------------------ +int figtreeKCenterClustering( int d, int N, double * x, int kMax, int * K, + double * rx, int * clusterIndex, double * clusterCenters, + int * numPoints, double * clusterRadii ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeKCenterClustering ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeKCenterClustering ); + FIGTREE_CHECK_POS_NONZERO_INT( kMax, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( K, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( rx, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenters, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( numPoints, figtreeKCenterClustering ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeKCenterClustering ); + + //k-center clustering + KCenterClustering* pKCC = new KCenterClustering( d, N, x, clusterIndex, kMax ); + *K = pKCC->Cluster(); + if( rx != NULL ) + *rx = pKCC->MaxClusterRadius; + pKCC->ComputeClusterCenters(*K, clusterCenters, numPoints, clusterRadii); + + delete pKCC; + return 0; +} + +//------------------------------------------------------------------------------ +// Actual function to evaluate the exact Gauss Transform directly. +// Originally Evaluate() from GaussTransform.cpp, written by Vikas C. Raykar. +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +int figtreeEvaluateDirect( int d, int N, int M, double * x, double h, + double * q, double * y, double * g ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateDirect ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateDirect ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateDirect ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateDirect ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateDirect ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateDirect ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateDirect ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateDirect ); + + // evaluate + double hSquare = h*h; + for(int j = 0; j < M; j++) + { + g[j] = 0.0; + for(int i = 0; i < N; i++) + { + double norm = 0.0; + for (int k = 0; k < d; k++) + { + double temp = x[(d*i) + k] - y[(d*j) + k]; + norm = norm + (temp*temp); + } + g[j] = g[j] + (q[i]*exp(-norm/hSquare)); + } + } + + return 0; +} + +//------------------------------------------------------------------------------ +// This function approximates Gauss Transform. +// Originally constructor, Evaluate(), and destructor from +// ImprovedFastGaussTransform.cpp (IFGT source code). +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgt( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgt ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgt ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgt ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + } + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + computeC( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, C ); + + for(int j = 0; j < M; j++) + { + for( int w = 0; w < W; w++ ) + { + g[M*w + j] = 0.0; + } + + int targetBase = j*d; + for(int k = 0; k < K; k++) + { + int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if(targetCenterDistanceSquare <= rySquare[k]) + { + computeTargetCenterMonomials( d, h, dy, pMax, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + g[M*w + j] += (C[(K*w + k)*pMaxTotal + alpha]*f*targetCenterMonomials[alpha]); + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + return 0; +} + + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtAdaptive ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + double * maxSourceDists2 = new double[pMax]; + figtreeSourceTruncationRanges( r, rx, h, epsilon, pMax, maxSourceDists2 ); + computeCAdaptivePoint( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, maxSourceDists2, pMaxTotals, C ); + delete [] maxSourceDists2; + + // for each cluster, compute distance ranges for each truncation number + double * targetDists2 = new double[2*pMax]; + figtreeTargetTruncationRanges( r, rx, h, epsilon, pMax, targetDists2, targetDists2+pMax ); + + //int * pHistogram = new int[pMax]; + //memset(pHistogram,0,sizeof(int)*pMax); + + memset( g, 0, sizeof(double)*M*W ); + //int targetBase = j*d; + for(int k = 0; k < K; k++) + { + for(int j = 0; j < M; j++) + { + //int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[j*d + i] - clusterCenter[k*d + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if(targetCenterDistanceSquare <= rySquare[k]) + { + int p = figtreeTargetTruncationNumber( targetCenterDistanceSquare, pMax, targetDists2, targetDists2+pMax ); + int pTotal = pMaxTotals[p-1]; + //pHistogram[p-1]++; + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + //printf( "target p histogram: "); + //for( int i = 0; i < pMax; i++ ) + // printf( " %i", pHistogram[i] ); + //printf( "\n" ); + //delete [] pHistogram; + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + delete [] targetDists2; + delete [] pMaxTotals; + + return 0; +} + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtAdaptive ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtAdaptive ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + computeCAdaptiveCluster( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, clusterTruncations, pMaxTotals, C ); + + memset( g, 0, sizeof(double)*M*W ); + //int targetBase = j*d; + for(int k = 0; k < K; k++) + { + int p = clusterTruncations[k]; + int pTotal = pMaxTotals[p-1]; + for(int j = 0; j < M; j++) + { + //int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[j*d + i] - clusterCenter[k*d + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if(targetCenterDistanceSquare <= rySquare[k]) + { + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + delete [] pMaxTotals; + + return 0; +} + +//------------------------------------------------------------------------------ +// This function approximates Gauss Transform using Approximate Nearest +// Neighbors. +// Originally constructor, Evaluate(), and destructor from +// ImprovedFastGaussTransform.cpp of FIGTree code, by Vikas C. Raykar. +// +// Modified by Vlad Morariu on 2007-06-19. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ) +{ +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with 'FIGTREE_NO_ANN' not defined to enable ANN support.\n"); + return -1; +#else + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTree ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTree ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax-1+d,d); + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double hSquare = h*h; + + //Find the maximum cluster radius + double pcr_max = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + if (clusterRadii[i] > pcr_max) + { + pcr_max = clusterRadii[i]; + } + } + double rSquare=(r+pcr_max)*(r+pcr_max); + + //Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(K,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists + + // Copy the cluster centers to the ANN data structure + for (int k = 0; k < K; k++) + { + for ( int j = 0; j < d; j++ ) + dataPts[k][j]= clusterCenter[k*d + j]; + } + + // build search structure + ANNkd_tree * kdTree = new ANNkd_tree( + dataPts, // the data points + K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST); + + //////////////////////////////////////////////////////////////////// + // Evaluate + //////////////////////////////////////////////////////////////////// + computeC( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, C ); + + for(int j = 0; j < M; j++) + { + for( int w = 0; w < W; w++ ) + { + g[M*w+j]=0.0; + } + + int targetBase=j*d; + + ANNpoint queryPt=&(y[targetBase]); + + int NN = kdTree->annkFRSearchUnordered( // search + queryPt, // query point + rSquare, // squared radius + N, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + 0.0 ); + + if (NN>0) + { + for(int l = 0; l < NN; l++) + { + int k = nnIdx[l]; + int centerBase = k*d; + double targetCenterDistanceSquare = dists[l]; + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + } + computeTargetCenterMonomials( d, h, dy, pMax, targetCenterMonomials ); + double e = exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + for(int alpha = 0; alpha < pMaxTotal; alpha++) + { + g[M*w + j] += (C[(K*w+k)*pMaxTotal + alpha]*e*targetCenterMonomials[alpha]); + } + } + } + } + } + + //////////////////////////////////////////////////////////////////// + // Release Memory + //////////////////////////////////////////////////////////////////// + delete [] targetCenterMonomials; + delete [] dy; + delete [] C; + + annDeallocPts(dataPts); + delete [] nnIdx; + delete [] dists; + delete kdTree; + annClose(); + + return 0; +#endif +} + +//------------------------------------------------------------------------------ +// Gauss Transform computed using the ANN library. +// Given a specified epsilon, the code computes the Gauss transform by summing +// the sources only within a certain radius--whose contribution is at least +// epsilon. The neighbors are found using the ANN library. +// http://www.cs.umd.edu/~mount/ANN/. +// Originally constructor, Evaluate(), and destructor from GaussTransformTree.cpp +// of FIGTree code, by Vikas C. Raykar. +// +// Modified by Vlad Morariu on 2007-06-20 +// Modified by Vlad Morariu on 2008-06-10 to use ANN fixed radius search with +// nearest neighbors unordered (saves a significant amt of time), and with +// one call instead of two, as a result. +//------------------------------------------------------------------------------ +int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, + double * q, double * y, double epsilon, double * g ) +{ +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with compiler flag 'FIGTREE_NO_ANN' not set to enable ANN support.\n"); + return -1; +#else + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateDirectTreeUnordered ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateDirectTreeUnordered ); + + double hSquare = h*h; + double epsANN = 0.0; + + // Compute the cutoff radius + double r = h*sqrt(log(1/epsilon)); + double rSquare=r*r; + + // Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(N,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[N]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[N]; // allocate near neighbor dists + + // Copy the source points to the ANN data structure + for (int i = 0; i < N; i++) + { + for ( int j = 0; j < d; j++ ) + dataPts[i][j]= x[i*d + j]; + } + + // build search structure + ANNkd_tree * kdTree = new ANNkd_tree( + dataPts, // the data points + N, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST ); + + /////////////////////////////////////////////////////////////////////// + // Evaluate + /////////////////////////////////////////////////////////////////////// + for(int j = 0; j < M; j++) + { + g[j] = 0.0; + int targetBase = j*d; + ANNpoint queryPt = &(y[targetBase]); + + int NN = kdTree->annkFRSearchUnordered( // fixed radius search + queryPt, // query point + rSquare, // squared radius + N, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + epsANN ); + for(int l = 0; l < NN; l++) + { + int i = nnIdx[l]; + double sourceTargetDistanceSquare = dists[l]; + g[j] += (q[i]*exp(-sourceTargetDistanceSquare/hSquare)); + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Free memory + ////////////////////////////////////////////////////////////////////////////// + annDeallocPts(dataPts); + delete [] nnIdx; + delete [] dists; + delete kdTree; + annClose(); + + return 0; +#endif +} + + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ) +{ +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with compiler flag 'FIGTREE_NO_ANN' not set to enable ANN support.\n"); + return -1; +#else + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( q, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTreeAdaptivePoint ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTreeAdaptivePoint ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } + + // + // Build tree on cluster centers + // + double rSquare = (r+rx)*(r+rx); + //Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(K,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists + + // Copy the cluster centers to the ANN data structure + for (int k = 0; k < K; k++) + { + for ( int j = 0; j < d; j++ ) + dataPts[k][j]= clusterCenter[k*d + j]; + } + + // build search structure + ANNkd_tree * kdTree = new ANNkd_tree( + dataPts, // the data points + K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST); + + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + double * maxSourceDists2 = new double[pMax]; + figtreeSourceTruncationRanges( r, rx, h, epsilon, pMax, maxSourceDists2 ); + computeCAdaptivePoint( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, maxSourceDists2, pMaxTotals, C ); + delete [] maxSourceDists2; + + // for each cluster, compute distance ranges for each truncation number + double * targetDists2 = new double[2*pMax]; + figtreeTargetTruncationRanges( r, rx, h, epsilon, pMax, targetDists2, targetDists2+pMax ); + + //int * pHistogram = new int[pMax]; + //memset(pHistogram,0,sizeof(int)*pMax); + + memset( g, 0, sizeof(double)*M*W ); + + for(int j = 0; j < M; j++) + { + int targetBase = j*d; + ANNpoint queryPt=&(y[targetBase]); + + int NN = kdTree->annkFRSearchUnordered( // search + queryPt, // query point + rSquare, // squared radius + K, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + 0.0 ); + for(int l = 0; l < NN; l++) + { + int k = nnIdx[l]; + + int centerBase = k*d; + double targetCenterDistanceSquare = dists[l]; + if(targetCenterDistanceSquare <= rySquare[k]) + { + int p = figtreeTargetTruncationNumber( targetCenterDistanceSquare, pMax, targetDists2, targetDists2+pMax ); + int pTotal = pMaxTotals[p-1]; + //pHistogram[p-1]++; + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + } + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + //printf( "target p histogram: "); + //for( int i = 0; i < pMax; i++ ) + // printf( " %i", pHistogram[i] ); + //printf( "\n" ); + //delete [] pHistogram; + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + + delete [] targetDists2; + delete [] pMaxTotals; + + annDeallocPts(dataPts); + delete [] nnIdx; + delete [] dists; + delete kdTree; + annClose(); + return 0; +#endif +} + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ) +{ +#ifdef FIGTREE_NO_ANN + printf("This code was not compiled with support for ANN. Please recompile\n"); + printf("with compiler flag 'FIGTREE_NO_ANN' not set to enable ANN support.\n"); + return -1; +#else + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( N, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( M, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( W, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeEvaluateIfgtIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( h, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( y, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( pMax, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_INT( K, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( clusterIndex, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( clusterCenter, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( clusterRadii, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( r, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_POS_NONZERO_DOUBLE( epsilon, figtreeEvaluateIfgtTreeAdaptiveCluster ); + FIGTREE_CHECK_NONNULL_PTR( g, figtreeEvaluateIfgtTreeAdaptiveCluster ); + + //Memory allocation + int pMaxTotal = nchoosek(pMax - 1 + d, d); + int * pMaxTotals = new int[pMax]; + for( int i = 0; i < pMax; i++ ) + pMaxTotals[i] = nchoosek( i + d, d ); + + double hSquare=h*h; + double * targetCenterMonomials = new double[pMaxTotal]; + double * dy = new double[d]; + double * C = new double[W*K*pMaxTotal]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + double rx = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + rx = MAX( rx, clusterRadii[i] ); + } + + // + // Build tree on cluster centers + // + double rSquare = (r+rx)*(r+rx); + //Allocate storage using ANN procedures + ANNpointArray dataPts = annAllocPts(K,d); // allocate data points + ANNidxArray nnIdx = new ANNidx[K]; // allocate near neigh indices + ANNdistArray dists = new ANNdist[K]; // allocate near neighbor dists + + // Copy the cluster centers to the ANN data structure + for (int k = 0; k < K; k++) + { + for ( int j = 0; j < d; j++ ) + dataPts[k][j]= clusterCenter[k*d + j]; + } + + // build search structure + ANNkd_tree * kdTree = new ANNkd_tree( + dataPts, // the data points + K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST); + + ////////////////////////////////////////////////////////////////////////////// + // Evaluate + ////////////////////////////////////////////////////////////////////////////// + // for each cluster, compute max distances at which we can use a certain truncation number + computeCAdaptiveCluster( d, N, W, K, pMaxTotal, pMax, h, clusterIndex, x, q, clusterCenter, clusterTruncations, pMaxTotals, C ); + + memset( g, 0, sizeof(double)*M*W ); + + for(int j = 0; j < M; j++) + { + int targetBase = j*d; + ANNpoint queryPt=&(y[targetBase]); + + int NN = kdTree->annkFRSearchUnordered( // search + queryPt, // query point + rSquare, // squared radius + K, // number of near neighbors + nnIdx, // nearest neighbors (returned) + dists, // distance (returned) + 0.0 ); + for(int l = 0; l < NN; l++) + { + int k = nnIdx[l]; + int centerBase = k*d; + int p = clusterTruncations[k]; + int pTotal = pMaxTotals[p-1]; + + double targetCenterDistanceSquare = dists[l]; + if(targetCenterDistanceSquare <= rySquare[k]) + { + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + } + computeTargetCenterMonomials( d, h, dy, p, targetCenterMonomials ); + double f=exp(-targetCenterDistanceSquare/hSquare); + for(int w = 0; w < W; w++ ) + { + double * C_offset = C + (K*w + k)*pMaxTotal; + for(int alpha = 0; alpha < pTotal; alpha++) + { + g[M*w + j] += *(C_offset++)*f*targetCenterMonomials[alpha]; + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////// + // Release memory + ////////////////////////////////////////////////////////////////////////////// + delete [] rySquare; + delete [] ry; + delete [] C; + delete [] dy; + delete [] targetCenterMonomials; + delete [] pMaxTotals; + + annDeallocPts(dataPts); + delete [] nnIdx; + delete [] dists; + delete kdTree; + annClose(); + return 0; +#endif +} + +int figtreeCalcMinMax( int d, int n, double * x, double * mins, double * maxs, int update ) +{ + // check input arguments + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeCalcMinMax ); + FIGTREE_CHECK_POS_NONZERO_INT( n, figtreeCalcMinMax ); + FIGTREE_CHECK_NONNULL_PTR( x, figtreeCalcMinMax ); + FIGTREE_CHECK_NONNULL_PTR( mins, figtreeCalcMinMax ); + FIGTREE_CHECK_NONNULL_PTR( maxs, figtreeCalcMinMax ); + + // use first sample values as current min and max if we're not updating + // some previously computed min and max values. + if( update != 1 && n > 0 ) + { + for( int i = 0; i < d; i++ ) + { + mins[i] = x[i]; + maxs[i] = x[i]; + } + } + + // go through each sample in x and update mins and maxs for each dimension + for( int i = 0; i < n; i++ ) + { + for( int j = 0; j < d; j++ ) + { + mins[j] = MIN( mins[j], x[i*d+j] ); + maxs[j] = MAX( maxs[j], x[i*d+j] ); + } + } + + return 0; +} + +int figtreeCalcMaxRange( double d, double * mins, double * maxs, double * maxRange ) +{ + FIGTREE_CHECK_POS_NONZERO_INT( d, figtreeCalcMaxRange ); + FIGTREE_CHECK_NONNULL_PTR( mins, figtreeCalcMaxRange ); + FIGTREE_CHECK_NONNULL_PTR( maxs, figtreeCalcMaxRange ); + FIGTREE_CHECK_NONNULL_PTR( maxRange, figtreeCalcMaxRange ); + + double maxRangeTemp = maxs[0] - mins[0]; + for( int i = 0; i < d; i++ ) + maxRangeTemp = MAX( maxRangeTemp, maxs[i] - mins[i] ); + *maxRange = maxRangeTemp; + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////// +// +// +// Methods for automatic selection of evaluation method. +// Functions created by Vlad Morariu 05-02-2008. +// Functions modified by Vlad Morariu 06-06-2008. +// Functions modified by Vlad Morariu 11-02-2008. +// - Added code to perform sub-sampling w/o replacement, and cleaned up code a +// little for release. +// +/////////////////////////////////////////////////////////////////////////////////// + +//------------------------------------------------------------------------------ +// The functions below are used to estimate avg number of neighbors in the source set +// given a query point from the target set. +// +// Created by Vlad Morariu 2008-06-04. +//------------------------------------------------------------------------------ +#ifndef FIGTREE_NO_ANN +inline void figtreeGetAverageNumNeighbors( ANNkd_tree * kdTree, int d, int M, double * y, double r, int Msample, double * avgNbrs, double * avgAnnFlops ) +{ + int numNbrs = 0; + int flopsAccum = 0, flops =0; + double rSquare = r*r; + double epsANN = 0.0; + + for(int i = 0; i < Msample; i++) + { + int idx = rand() % M; + ANNpoint queryPt = &(y[ idx*d ]); + + int NN = kdTree->annkFRSearchUnorderedFlops( // fixed radius search + queryPt, // query point + rSquare, // squared radius + 0, // number of near neighbors + NULL, // nearest neighbors (returned) + NULL, // distance (returned) + epsANN, + &flops ); + numNbrs += NN; + flopsAccum += flops; + } + + *avgNbrs = numNbrs / (double)Msample; + *avgAnnFlops = flopsAccum / (double)Msample; +} + +inline void figtreeEstimatedNeighborSources( int d, int M, double * y, double h, double epsilon, ANNkd_tree * sourcesKdTree, int Msample, double * avgNbrSources, double * avgAnnFlopsSources ) +{ + // Compute the cutoff radius + double r = h*sqrt(log(1/epsilon)); + + // estimate avg number of neighbors + figtreeGetAverageNumNeighbors( sourcesKdTree, d, M, y, r, Msample, avgNbrSources, avgAnnFlopsSources ); +} + +inline void figtreeEstimatedNeighborClusters( int d, int M, double * y, int K, double * clusterRadii, double r, ANNkd_tree * clustersKdTree, int Msample, double * avgNbrClusters, double * avgAnnFlopsClusters ) +{ + //Find the maximum cluster radius + double pcrMax = clusterRadii[0]; + for(int i = 0; i < K; i++) + { + if (clusterRadii[i] > pcrMax) + { + pcrMax = clusterRadii[i]; + } + } + double rMax =(r+pcrMax); + + // estimate numbers of pts with more than 1 neighbor and avg number of neighbors + figtreeGetAverageNumNeighbors( clustersKdTree, d, M, y, rMax, Msample, avgNbrClusters, avgAnnFlopsClusters ); +} +#endif +inline void figtreeEstimatedNeighborClustersNoAnn( int d, int N, int M, double h, double * y, + int K, double * clusterCenter, double * clusterRadii, double r, int Msample, + double * avgNbrClustersNoAnn, double * avgFindCentersFlops ) +{ + double flops = 0; + double avgNbrClusters = 0; + double * dy = new double[d]; + double * ry = new double[K]; + double * rySquare = new double[K]; + + for(int i = 0; i < K; i++) + { + ry[i] = r + clusterRadii[i]; + rySquare[i] = ry[i]*ry[i]; + } + + for(int j = 0; j < Msample; j++) + { + int targetBase = (rand()%M)*d; + for(int k = 0; k < K; k++) + { + int centerBase = k*d; + double targetCenterDistanceSquare = 0.0; + for(int i = 0; i < d; i++) + { + dy[i] = y[targetBase + i] - clusterCenter[centerBase + i]; + targetCenterDistanceSquare += dy[i]*dy[i]; + flops += 3; + if(targetCenterDistanceSquare > rySquare[k]) break; + } + + if( targetCenterDistanceSquare <= rySquare[k] ) + avgNbrClusters++; + } + } + + *avgFindCentersFlops = flops/Msample; + *avgNbrClustersNoAnn = avgNbrClusters/Msample; + + delete [] dy; + delete [] ry; + delete [] rySquare; +} + + +//------------------------------------------------------------------------------ +// +// The functions below estimate the number of floating point operations (flops) +// for different parts of the figtree code. +// Where possible the estimates are made directly by counting the number of +// floating point operations in the code itself, but for things such as +// building the kd-Tree and clustering, we use the theoretical complexity. +// +// Created by Vlad Morariu 2008-05-03 to 2008-06-04. +// Modified by Vlad Morariu 2008-12-05 +// Changed floating op estimation functions to reflect revised versions of code. +//------------------------------------------------------------------------------ +inline double figtreeEstimatedFlopsComputeSourceCenterMonomials( int d, int pMaxTotal ) +{ + return (d + (double)pMaxTotal); +} + +inline double figtreeEstimatedFlopsComputeTargetCenterMonomials( int d, int pMaxTotal ) +{ + return (d + (double)pMaxTotal); +} + +inline double figtreeEstimatedFlopsComputeConstantSeries( int pMaxTotal ) +{ + return (2.0*pMaxTotal); +} + +inline double figtreeEstimatedFlopsComputeC( int d, int N, int W, int K, int pMaxTotal, double flopsExp ) +{ + double computeSourceCenterMonomials = figtreeEstimatedFlopsComputeSourceCenterMonomials( d, pMaxTotal ); + double computeConstantSeries = figtreeEstimatedFlopsComputeConstantSeries( pMaxTotal ); + return N*(3*d + computeSourceCenterMonomials + W*(2+flopsExp+2*pMaxTotal)) + computeConstantSeries + W*K*pMaxTotal; +} + +inline double figtreeEstimatedFlopsBuildTree( int d, int N ) +{ + return d*N*log((double)N); +} + +inline double figtreeEstimatedFlopsKCenterClustering( int d, int N, int K ) +{ + return 3*d*(N*log((double)K) + K*(double)K); // not using the NlogK version yet +} + +inline double figtreeEstimatedFlopsDirect( int d, int N, int M, int W, double flopsExp ) +{ + return W*(1 + ((double)M)*((double)N)*(d*3 + 3 + flopsExp)); +} + +inline double figtreeEstimatedFlopsDirectTree( int d, int N, int M, int W, double avgNbrSources, double avgAnnFlopsSources, double flopsExp ) +{ + return W*(7 + ((double)M)*( avgAnnFlopsSources + avgNbrSources*(3+flopsExp) )); +} + +inline double figtreeEstimatedFlopsIfgt( int d, int N, int M, int W, int K, int pMaxTotal, double avgNbrClustersNoAnn, double avgFindCentersFlops, double flopsExp ) +{ + // cost of computing coeffs from sources + double computeC = figtreeEstimatedFlopsComputeC( d, N, W, K, pMaxTotal, flopsExp ); + double source = 2*K + 1 + computeC; + + // cost of computing target monomials and evaluating + double computeTargetCenterMonomials = figtreeEstimatedFlopsComputeTargetCenterMonomials( d, pMaxTotal ); + double target = ((double)M)*(avgFindCentersFlops + avgNbrClustersNoAnn*(computeTargetCenterMonomials + 1 + flopsExp + W*3*((double)pMaxTotal))); + + return source + target; +} + +inline double figtreeEstimatedFlopsIfgtTree( int d, int N, int M, int W, int K, int pMaxTotal, double avgNbrClusters, double avgAnnFlopsClusters, double flopsExp ) +{ + // cost of computing coeffs from sources + double computeC = figtreeEstimatedFlopsComputeC( d, N, W, K, pMaxTotal, flopsExp ); + double source = 4 + computeC; + + // cost of computing target monomials and evaluating + double computeTargetCenterMonomials = figtreeEstimatedFlopsComputeTargetCenterMonomials( d, pMaxTotal ); + double target = ((double)M)*( avgAnnFlopsClusters + avgNbrClusters*(d + computeTargetCenterMonomials + 1 + flopsExp + W*3*((double)pMaxTotal) ) ); + + return source + target; +} + +//------------------------------------------------------------------------------ +// This function chooses the evaluation method for figtree, given the input +// parameters and data. +// +// Created by Vlad Morariu 2008-05-03 to 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeChooseEvaluationMethod( int d, int N, int M, int W, double * x, double h, + double * y, double epsilon, int ifgtParamMethod, int verbose, + int * bestMethod, double * flops, void * data_struct ) +{ + int ret = 0; // return value (0 is no error, -1 is error) + + // + // Parameters for estimating avg number of neighbors, flops needed to find neighbors using tree, + // and setting k limit. + // + // In future releases of the code, users should be able to choose these parameters as they affect the + // quality of method selection. For now, users will have to recompileif they want to change these + // parameters. + // + int Msample = M_SAMPLE; // how many of the target points do we sample to estimate avg number of neighbors and flops? + int Nss = MAX( MIN(N,N_SS_MIN), (int)pow(N,N_SS_POW) ); // number of subsampled sources + double kLimitToAvgNbrRatio = K_LIMIT_TO_AVG_NBR_RATIO; // set k limit to this times avg number of source neighbors + double flopsExp = FLOPS_EXP; // floating point ops per exp() call + + // other values computed fromthe parameters above + double ss = N/(double)Nss; // how much subsampling to do for building kd-Tree + int kLimit = N, kMax; // kLimit is the highest K that we allow, kMax is the max K-value chosen by param selection + + // initialize flop estimates; -1 indicates flop estimation was not completed + double flopsDirect = figtreeEstimatedFlopsDirect( d, N, M, W, flopsExp ); + double flopsDirectTree = -1; + double flopsIfgt = -1; + double flopsIfgtTree = -1; + + // avg number of neighboring clusters for IFGT (no tree), and avg flops spent finding + // the neighboring clusters + double avgNbrClustersNoAnn, avgFindCentersFlops; + + // this datastructure will hold the kd-Trees, cluster centers, etc + FigtreeData data = figtreeCreateData(); // obtain data structure filled with 0's + +#ifndef FIGTREE_NO_ANN + + // these variables will represent statistics of source distribution (avg neighbors) + double avgNbrSources, avgNbrClusters; + + // these variables contain avg cost of each kd-Tree query for finding neighbors + double avgAnnFlopsSources, avgAnnFlopsClusters; + + // get a random sampling of Nss points, w/o replacement + int * shuffled_indexes = new int[N]; + for( int i = 0; i < N; i++ ) + shuffled_indexes[i] = i; + std::random_shuffle( shuffled_indexes, shuffled_indexes+N ); // could also use random_sample, if available + + // Allocate storage using ANN procedures + data.annSources = annAllocPts(Nss,d); // allocate data points + + // Copy the source points to the ANN data structure + for (int i = 0; i < Nss; i++) + { + for ( int j = 0; j < d; j++ ) + data.annSources[i][j]= x[shuffled_indexes[i]*d + j]; + } + + delete [] shuffled_indexes; + + // Build search structure + data.annSourcesKdTree = new ANNkd_tree( + data.annSources, // the data points + Nss, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST ); + + figtreeEstimatedNeighborSources( d, M, y, h, epsilon, data.annSourcesKdTree, Msample, &avgNbrSources, &avgAnnFlopsSources); + flopsDirectTree = figtreeEstimatedFlopsBuildTree( d, N ) + figtreeEstimatedFlopsDirectTree( d, N, M, W, ss*avgNbrSources, ss*avgAnnFlopsSources*(log((double)N)/log((double)Nss)), flopsExp ); + + // set kLimit based on how many source points, on average, are within radius of each query pt + kLimit = MIN((int)(kLimitToAvgNbrRatio*ss*avgNbrSources),N); + +#endif // #ifndef FIGTREE_NO_ANN + + if( kLimit > 0 ) + { + double maxRange=0; + + // calculate R, the diameter of the hypercube that encompasses sources and targets + double * mins = new double[d]; + double * maxs = new double[d]; + figtreeCalcMinMax( d, N, x, mins, maxs, 0 ); + figtreeCalcMinMax( d, M, y, mins, maxs, 1 ); + figtreeCalcMaxRange( d, mins, maxs, &maxRange ); + delete [] mins; + delete [] maxs; + + if( ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM ) + ret = figtreeChooseParametersNonUniform( d, N, x, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + else + ret = figtreeChooseParametersUniform( d, h, epsilon, kLimit, maxRange, &kMax, &data.pMax, &data.r, NULL ); + if( ret < 0 ) + { + printf("figtree: figtreeChooseParameters%sUniform() failed.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : "")); + return ret; + } + + verbose && printf("figtreeChooseParameters%sUniform() chose p=%i, k=%i.\n", + ((ifgtParamMethod == FIGTREE_PARAM_NON_UNIFORM) ? "Non" : ""), data.pMax, kMax ); + + // do k-center clustering + data.clusterIndex = new int[N]; + data.numPoints = new int[kMax]; + data.clusterCenters = new double[d*kMax]; + data.clusterRadii = new double[kMax]; + + ret = figtreeKCenterClustering( d, N, x, kMax, &data.K, &data.rx, data.clusterIndex, + data.clusterCenters, data.numPoints, data.clusterRadii ); + if( ret >= 0 ) + { + double errorBound = epsilon + 1; + // choose truncation number again now that clustering is done + ret = figtreeChooseTruncationNumber( d, h, epsilon, data.rx, maxRange, &data.pMax, &errorBound ); + if( ret >= 0 ) + { + // these are the params we would evaluate IFGT with + verbose && printf( "Eval IFGT(h= %3.2e, pMax= %i, K= %i, r= %3.2e, rx= %3.2e, epsilon= %3.2e, bound = %3.2e)\n", + h, data.pMax, data.K, data.r, data.rx, epsilon, errorBound); + + double pMaxTotalDouble = nchoosek_double(data.pMax-1+d,d); + if( errorBound <= epsilon && pMaxTotalDouble < INT_MAX ) + { + data.pMaxTotal = (int)pMaxTotalDouble; + + // + // Estimate number of flops for performing IFGT + // + figtreeEstimatedNeighborClustersNoAnn( d, N, M, h, y, data.K, data.clusterCenters, data.clusterRadii, data.r, Msample, &avgNbrClustersNoAnn, &avgFindCentersFlops ); + flopsIfgt = figtreeEstimatedFlopsIfgt( d, N, M, W, data.K, data.pMaxTotal, avgNbrClustersNoAnn, avgFindCentersFlops, flopsExp ); + +#ifndef FIGTREE_NO_ANN + // + // Estimate number of flops for performing IFGT with kd-Tree + // + + // Allocate storage using ANN procedures + data.annClusters = annAllocPts(data.K,d); // allocate data points + + // Copy the source points to the ANN data structure + for (int i = 0; i < data.K; i++) + { + for ( int j = 0; j < d; j++ ) + data.annClusters[i][j]= data.clusterCenters[i*d + j]; + } + + // build search structure + data.annClustersKdTree = new ANNkd_tree( + data.annClusters, // the data points + data.K, // number of points + d, // dimension of space + 1, + ANN_KD_SUGGEST ); + + figtreeEstimatedNeighborClusters( d, M, y, data.K, data.clusterRadii, data.r, data.annClustersKdTree, Msample, &avgNbrClusters, &avgAnnFlopsClusters ); + flopsIfgtTree = figtreeEstimatedFlopsIfgtTree( d, N, M, W, data.K, data.pMaxTotal, avgNbrClusters, avgAnnFlopsClusters, flopsExp ); +#endif + } + } + else // if figtreeChooseTruncationNumber fails... + { + printf("figtree: figtreeChooseTruncationNumber() failed.\n"); + } + } // if figtreeKCenterClustering fails... + else + { + printf("figtree: figtreeKCenterClustering() failed.\n"); + } + } + + // save clustering and parameter selection data if desired + if( data_struct != NULL ) + { + FigtreeData * data_out = (FigtreeData*)data_struct; + // copy all data except for ANN data structures + *data_out = data; + data_out->annClusters = NULL; + data_out->annClustersKdTree = NULL; + data_out->annSources = NULL; + data_out->annSourcesKdTree = NULL; + + // set copied data to NULL, or else it will be deallocated + data.clusterCenters = NULL; + data.clusterIndex = NULL; + data.clusterRadii = NULL; + data.numPoints = NULL; + } + + figtreeReleaseData( &data ); + + // return flops per method if user supplies non-NULL pointer + if( flops != NULL ) + { + flops[ FIGTREE_EVAL_DIRECT ] = flopsDirect; + flops[ FIGTREE_EVAL_DIRECT_TREE ] = flopsDirectTree; + flops[ FIGTREE_EVAL_IFGT ] = flopsIfgt; + flops[ FIGTREE_EVAL_IFGT_TREE ] = flopsIfgtTree; + } + + // choose best method if user supplies non-NULL pointer + if( bestMethod!= NULL ) + { + double bestFlops = flopsDirect; + *bestMethod = FIGTREE_EVAL_DIRECT; + + if( flopsDirectTree != -1 && flopsDirectTree < bestFlops ) + { + *bestMethod = FIGTREE_EVAL_DIRECT_TREE; + bestFlops = flopsDirectTree; + } + + if( flopsIfgt!= -1 && flopsIfgt < bestFlops ) + { + *bestMethod = FIGTREE_EVAL_IFGT; + bestFlops = flopsIfgt; + } + + if( flopsIfgtTree != -1 && flopsIfgtTree < bestFlops ) + { + *bestMethod = FIGTREE_EVAL_IFGT_TREE; + bestFlops = flopsIfgtTree; + } + } + +#ifndef FIGTREE_NO_ANN + annClose(); +#endif + + return ret; +} diff --git a/dep/figtree/figtree.h b/dep/figtree/figtree.h new file mode 100755 index 00000000..113b7a3e --- /dev/null +++ b/dep/figtree/figtree.h @@ -0,0 +1,306 @@ +// File: figtree.h +// Created: 11-03-06 by Vlad Morariu +// +// Modified: 6-22-07 by Vlad Morariu +// Initial changes from previous version of the IFGT code (written by Vikas C. +// Raykar and Changjiang Yang) and FIGTree code (written by Vikas C. Raykar). +// +// Modifications include: +// 1) Code can compile into a dynamic library that provides C-style interface +// without requiring Matlab. +// +// 2) Added an improved parameter selection method that removes assumption that +// sources are uniformly distributed (observed large speedup in cases where +// sources were not uniformly distributed, and often little slowdown from +// overhead when the sources were actually uniformly distributed). +// +// 3) Changed the IFGT code to take multiple sets of weights for same set of +// sources and targets instead of having to call IFGT code multiple times. +// By computing a set of coefficients for each weight set, much overhead is +// saved (eg. computing monomials, and so on), resulting in significant +// speedup. +// +// 4) Added function (figtree()) that performs all parameter selection/clustering +// using any choice of parameter selection and evaluation algorithms. +// +// 5) Some bugs/problem cases were fixed (some bugs caused seg faults, others +// were certain problem cases that could result in bad parameter selection +// and, as a result, memory allocation errors or seg faults). +// +// 6) In the original implementation, most code resided in the constructor and +// Evaluate() functions of a class, and was actually called in sequential +// order as if it were a C function (thus not using any real advantages of +// C++ classes). Thus, all code except for that of KCenterClustering, which +// seems to fit better in a class, has been put in C-style functions inside +// of figtree.cpp. The original location of the original source is indicated +// in figtree.cpp before each function. +// +// 7) Stylistic changes (eg. variable naming conventions, function names, ...) +// +// Modified: 9-23-07 by Vlad Morariu +// Change code to compile on linux and solaris. +// +// Modified: 10-03-07 by Vlad Morariu +// Remove requirement that data is in unit hypercube by adding +// maxRange parameter to figtreeChoose* functions. +// +// Modified: 01-22-08 by Vlad Morariu +// Rename library to FIGTree (and some other function renamimg) +// +// Modified: 05-03-08 by Vlad Morariu +// Add initial version of method selection code. +// +// Modified: 05-27-08 by Vlad Morariu +// Change figtreeChooseParameters* and figtreeChooseTruncationNumber functions +// to return the predicted errorBound. This can then be used to check if +// the parameters chosen will satisfy the desired error bound (they may not +// since we enforce a limit on pMax (the truncation number). +// +// Modified: 05-29-08 to 06-10-08 by Vlad Morariu +// Make changes for 'Automatic online tuning for fast Gaussian summation,' by +// Morariu et al, NIPS 2008. Changes include automatic parameter selection +// improvements, point-wise and cluster-wise truncation number selection, and +// automatic method selection. These changes make this approach much easier +// to use since the user does not need to choose parameters. +// 1) Added code to choose individual truncation numbers for both targets and sources +// using pointwise error bounds. +// 2) Added code to choose individual truncation numbers for targets and sources +// using clusterwise error bounds. +// 3) Reuse K-center clustering computed during method selection if +// FIGTREE_EVAL_AUTO is chosen. +// 4) Changed ANN code to compute unordered nearest neighbors, saving time +// by not using a priority queue and also because now the fixed radius +// nearest neighbor computation and retrieval is done in one step, +// instead of first finding # of nn's and then doing the search again to +// retrieve the nn's. This really speeds up direct+tree since the ANN +// priority queue was implemented using insertion sort. +// +// Modified: 11-02-08, 12-01-08 to 12-05-08 by Vlad Morariu +// Made some revisions before posting new version online. +// 1) Changed interface of figtree so users can choose truncation method +// (also changed figtree() to automatically revert to the simplest +// truncation method in cases where the two more complex methods +// cannot give a speedup). +// 2) Revised some comments +// 3) Found all parameters used throughout code and defined constants for them +// so that users can change them and recompile. In future releases, +// these should only be defaults, and users should be able to modify them +// at runtime. +// 4) Removed most helper functions from figtree.h (all but figtree(), +// figtreeChooseEvaluationMethod(), and figtreeKCenterClustering() ) and +// placed them in figtree_internal.h. +// 5) Changed floating op estimation functions to reflect revised versions +// of code + +//------------------------------------------------------------------------------ +// The code was written by Vlad Morariu, Vikas Raykar, and Changjiang Yang +// and is copyrighted under the Lesser GPL: +// +// Copyright (C) 2008 Vlad Morariu, Vikas Raykar, and Changjiang Yang +// +// This program 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; version 2.1 or later. +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// You should have received a copy of the GNU Lesser General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. +// +// The author may be contacted via email at: +// morariu(at)umd(.)edu, vikas(at)umiacs(.)umd(.)edu, cyang(at)sarnoff(.)com +//------------------------------------------------------------------------------ +#ifndef FIGTREE_H +#define FIGTREE_H + +#ifdef WIN32 + //---------------------------------------------------------------------- + // To compile the code into a windows DLL, you must define the + // symbol FIGTREE_DLL_EXPORTS. + // + // To compile the code statically into a windows executable + // (i.e. not using a separate DLL) define FIGTREE_DLL_STATIC. + //---------------------------------------------------------------------- + #ifdef FIGTREE_STATIC + #define FIGTREE_DLL_API // since FIGTREE_STATIC is defined, code is statically + // linked and no exports or imports are needed + #else + #ifdef FIGTREE_DLL_EXPORTS + #define FIGTREE_DLL_API __declspec(dllexport) + #else + #define FIGTREE_DLL_API __declspec(dllimport) + #endif + #endif +#else + //---------------------------------------------------------------------- + // FIGTREE_DLL_API is ignored for all other systems + //---------------------------------------------------------------------- + #define FIGTREE_DLL_API +#endif + +// we want to export C functions if using DLL +#if defined(__cplusplus) && !defined(FIGTREE_STATIC) +extern "C" { +#endif + + + + +//------------------------------------------------------------------------------ +// +// Some useful constants for the figtree() function call +// +//------------------------------------------------------------------------------ + +// Constants for choosing evaluation method +#define FIGTREE_EVAL_DIRECT 0 // direct evaluation of gauss transform +#define FIGTREE_EVAL_IFGT 1 // truncated taylor series evaluation +#define FIGTREE_EVAL_DIRECT_TREE 2 // direct evaluation +#define FIGTREE_EVAL_IFGT_TREE 3 // ifgt+tree +#define FIGTREE_EVAL_AUTO 4 // automatically chooses one of the four +#define FIGTREE_EVAL_SIZE 5 // total number of eval methods + +// Constants for choosing parameter selection method for IFGT +#define FIGTREE_PARAM_UNIFORM 0 // estimate params assuming sources are + // uniformly distributed (not recommended + // for non-uniform data) +#define FIGTREE_PARAM_NON_UNIFORM 1 // estimate params by using actual source + // distribution (runs k-center clustering + // twice, but speedup during evaluation + // more than makes up for it in general) +#define FIGTREE_PARAM_SIZE 2 // total number of param estimation methods + +// Constants for choosing truncation selection method for IFGT +#define FIGTREE_TRUNC_MAX 0 // use worst case truncation number for all pts +#define FIGTREE_TRUNC_POINT 1 // use point-wise error bounds for individual truncations +#define FIGTREE_TRUNC_CLUSTER 2 // use cluster-wise error bounds for individual truncations +#define FIGTREE_TRUNC_SIZE 3 // total number of truncation selection methods + +//------------------------------------------------------------------------------ +// +// Main functions exported by the library. For more control over internal +// workings of figtree, see figtree_internal.h and figtree.cpp. +// +//------------------------------------------------------------------------------ + + +// Note: All matrix pointers are assumed to point to a contiguous one +// dimensional array containing the entries of the matrx in row major format. +// Thus, for an M x N matrix and a pointer ptr to its data, +// ptr[0] ... ptr[N-1] contains the first row of the matrix, and so on. + +// Evaluates gauss transform in one shot (chooses parameters and does clustering +// if necessary, and evaluates). +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This is useful if one needs multiple gauss transforms that have +// the same sources, targets, and bandwidth, but different +// weights/strengths (q). By computing coefficients for all W weight +// sets at once, we avoid duplicating much of the overhead. However, +// more memory is needed to store a set of coefficients for each set +// of weights. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> W x N matrix of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * epsilon --> desired error +// * evalMethod --> the evaluation method to use in evaluating gauss +// transform. Can be FIGTREE_EVAL_[DIRECT,IFGT,DIRECT_TREE, +// IFGT_TREE], defined above. epsilon is needed for all but +// DIRECT method. Parameter selection is done only in the IFGT +// or IFGT_TREE case. +// * ifgtParamMethod --> the method to use for determining parameters. +// Can be FIGTREE_PARAM_UNIFORM or FIGTREE_PARAM_NON_UNIFORM. +// * ifgtTruncMethod --> the method to use for determining where to truncate +// Taylor series for each source and target point. Can be +// FIGTREE_TRUNC_MAX, FIGTREE_TRUNC_POINT, and FIGTREE_TRUNC_CLUSTER +// * verbose --> if nonzero, prints parameters chosen for evaluation +// +// Output +// * g --> W x M vector of the Gauss Transform evaluated at each target point. +// The ith row is the result of the transform using the ith set of +// weights. +FIGTREE_DLL_API +int figtree( int d, int N, int M, int W, double * x, double h, + double * q, double * y, double epsilon, double * g, + int evalMethod = FIGTREE_EVAL_AUTO, + int ifgtParamMethod = FIGTREE_PARAM_NON_UNIFORM, + int ifgtTruncMethod = FIGTREE_TRUNC_CLUSTER, + int verbose = 0 ); + +// Chooses between evaluation methods +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This is useful if one needs multiple gauss transforms that have +// the same sources, targets, and bandwidth, but different +// weights/strengths (q). By computing coefficients for all W weight +// sets at once, we avoid duplicating much of the overhead. However, +// more memory is needed to store a set of coefficients for each set +// of weights. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * y --> M x d matrix of M target points in d dimensions. +// * epsilon --> desired error +// * paramMethod --> the method to use for determining parameters. +// Can be FIGTREE_PARAM_UNIFORM or FIGTREE_PARAM_NON_UNIFORM. +// * verbose --> if nonzero, prints parameters chosen for evaluation +// +// Output +// * bestEvalMethod --> if non-NULL, the evaluation method to use in evaluating gauss +// transform. Can be FIGTREE_EVAL_[DIRECT,IFGT,DIRECT_TREE, +// IFGT_TREE], defined above. +// +// * flops --> if non-NULL, a double array of size FIGTREE_EVAL_SIZE, indexed by eval method +// type where flops[evalMethod] = estimated number of flops if we use this method. +// For evalMethod=FIGTREE_EVAL_IFGT or evalMethod=FIGTREE_EVAL_IFGT_TREE, +// it is possible that flops[.] = -1 in the case that it is decided early (before +// finishing the estimation) that these two methods will be slower than +// FIGTREE_EVAL_DIRECT or FIGTREE_EVAL_DIRECT_TREE +// * data_struct --> a structure that keeps some structures (k-center clustering, other params) +// that were computed during method selection that can be reused +// +FIGTREE_DLL_API +int figtreeChooseEvaluationMethod( int d, int N, int M, int W, double * x, double h, + double * y, double epsilon, int paramMethod=FIGTREE_PARAM_NON_UNIFORM, int verbose=0, + int * bestEvalMethod=0, double * flops=0, void * data_struct=0 ); + + +// Gonzalez's farthest-point clustering algorithm. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * x --> N x d matrix of N source points in d dimensions +// (in one contiguous array, row major format where each row is a point). +// * kMax --> maximum number of clusters. +// +// Output +// * K --> actual number of clusters (less than kMax if duplicate pts exist) +// * rx --> maximum radius of the clusters (rx). +// * clusterIndex --> vector of length N where the i th element is the +// cluster number to which the i th point belongs. +// ClusterIndex[i] varies between 0 to K-1. +// * clusterCenters --> K x d matrix of K cluster centers +// (contiguous 1-d array, row major format). +// * numPoints --> number of points in each cluster. +// * clusterRadii --> radius of each cluster. +FIGTREE_DLL_API +int figtreeKCenterClustering( int d, int N, double * x, int kMax, int * K, + double * rx, int * clusterIndex, double * clusterCenters, + int * numPoints, double * clusterRadii ); + +#if defined(__cplusplus) && !defined(FIGTREE_STATIC) +} // extern "C" +#endif + +#endif //FIGTREE_H diff --git a/dep/figtree/figtree_internal.h b/dep/figtree/figtree_internal.h new file mode 100755 index 00000000..8554f17c --- /dev/null +++ b/dep/figtree/figtree_internal.h @@ -0,0 +1,341 @@ +#ifndef FIGTREE_INTERNAL_H +#define FIGTREE_INTERNAL_H + +#include "figtree.h" + +// we want to export C functions if using DLL +#if defined(__cplusplus) && !defined(FIGTREE_STATIC) +extern "C" { +#endif + +// Given the maximum cluster radius, this function computes the maximum +// truncation number that guarantees results within the desired error bound. +//Input +// * d --> dimension of the points. +// * h --> the source bandwidth. +// * epsilon --> the desired error. +// * rx --> maximum cluster radius +// * maxRange --> max dimension range. The range along a dimension is +// the difference between the max and min values that can ever +// occur along that dimension. The max dimension range is the +// maximum range among all dimensions. For example, if all +// points lie in unit hypercube, then maxRange = 1. +// +//Output +// * pMax --> maximum truncation number for the Taylor series. +// * errorBound --> the error bound (if desired error bound is not reached, then it will be epsilon+1) +FIGTREE_DLL_API +int figtreeChooseTruncationNumber( int d, double h, double epsilon, + double rx, double maxRange, int * pMax, double * errorBound ); + +// Chooses parameters for IFGT and FIGTree by assuming that sources are +// uniformly distributed in a unit cube. +//Input +// * d --> dimension of the points. +// * h --> the source bandwidth. +// * epsilon --> the desired error. +// * kLimit --> upper limit on the number of clusters, kLimit. +// * maxRange --> max dimension range. The range along a dimension is +// the difference between the max and min values that can ever +// occur along that dimension. The max dimension range is the +// maximum range among all dimensions. For example, if all +// points lie in unit hypercube, then maxRange = 1. +// +//Note : [ Use roughly kLimit=round(40*sqrt(d)/h) ] +//Output +// * K --> number of clusters. +// * pMax --> maximum truncation number for the Taylor series. +// * r --> source cutoff radius. +// * errorBound --> the expected error bound (if desired error bound is not reached, then it will be epsilon+1) +FIGTREE_DLL_API +int figtreeChooseParametersUniform( int d, double h, double epsilon, + int kLimit, double maxRange, + int * K, int * pMax, double * r, double * errorBound ); + +// Chooses parameters for IFGT and FIGTree without assumption that sources are +// uniformly distributed. In this case, k-center clustering is done as part +// of the parameter selection so that the radius of each cluster is not +// estimated but computed directly for the sources. This results in an +// additional k-center clustering operation, but the speedup when sources are +// not uniformly distributed can be large because +// optimal parameters are much more accurately estimated. Even when sources are +// uniformly distributed, the slowdown is often small compared to +// figtreeChooseParametersUniform. +// +// Input +// * d --> dimension of the points. +// * N --> number of source points. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source bandwidth. +// * epsilon --> the desired error. +// * kLimit --> upper limit on the number of clusters, K. +// Note : Use kLimit=N to allow for optimal param estimation. +// * maxRange --> max dimension range. The range along a dimension is +// the difference between the max and min values that can ever +// occur along that dimension. The max dimension range is the +// maximum range among all dimensions. For example, if all +// points lie in unit hypercube, then maxRange = 1. +// Output +// * K --> number of clusters. +// * pMax --> maximum truncation number for the Taylor series. +// * r --> source cutoff radius. +// * errorBound --> the expected error bound (if desired error bound is not reached, then it will be epsilon+1) +FIGTREE_DLL_API +int figtreeChooseParametersNonUniform( int d, int N, double * x, + double h, double epsilon, int kLimit, double maxRange, + int * K, int * pMax, double * r, double * errorBound ); + +// Computes exact gauss transform (within machine precision) using direct +// evaluation. Provided for time/error comparison. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> 1 x N or N x 1 vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// +// Output +// * g --> 1 x M vector of the Gauss Transform evaluated at each target +// point. +FIGTREE_DLL_API +int figtreeEvaluateDirect( int d, int N, int M, double * x, double h, + double * q, double * y, double * g ); + +// Computes an approximation to Gauss Transform. Implementation based on: +// Fast computation of sums of Gaussians in high dimensions. Vikas C. Raykar, +// C. Yang, R. Duraiswami, and N. Gumerov, CS-TR-4767, Department of computer +// science, University of Maryland, College Park. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This really does multiple transforms, with different weights each +// time but with same sources and targets. This saves a lot of time +// since most of the work is not duplicated. However, it requires +// more memory to store the coefficients for each set of weights. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> W x N vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * pMax --> maximum truncation number for the Taylor series. +// * K --> the number of clusters. +// * clusterIndex --> N x 1 vector the i th element is the cluster number +// to which the i th point belongs. [ ClusterIndex[i] varies between +// 0 to K-1. ] +// * clusterCenter --> K x d matrix of K cluster centers. +// * clusterRadii --> K x 1 matrix of the radius of each cluster. +// * r --> cutoff radius +// * epsilon --> desired error +// +//Output +// * g --> W x M vector of the Gauss Transform evaluated at each target +// point. Each row q is the result of the transform using the qth set +// of weights. +FIGTREE_DLL_API +int figtreeEvaluateIfgt( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ); + +// Computes an approximation to Gauss Transform using approximate +// nearest-neighbors. Same as figtreeEvaluateIfgt() but uses Approximate +// Nearest-Neighbors library to find source clusters which influence each target +// (part of FIGTree). Parameters for this function can be computed using +// figtreeChooseParameters[Non]Uniform and figtreeKCenterClustering. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * W --> number of weights that will be used for each source point. +// This really does multiple transforms, with different weights each +// time but with same sources and targets. This saves a lot of time +// since most of the work is not duplicated. However, it requires +// more memory to store the coefficients for each set of weights. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> W x N vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * pMax --> maximum truncation number for the Taylor series. +// * K --> the number of clusters. +// * clusterIndex --> N x 1 vector the i th element is the cluster number +// to which the i th point belongs. [ ClusterIndex[i] varies between +// 0 to K-1. ] +// * clusterCenter --> K x d matrix of K cluster centers. +// * clusterRadii --> K x 1 matrix of the radius of each cluster. +// * r --> cutoff radius +// * epsilon --> desired error +// +// Output +// * g --> W x M vector of the Gauss Transform evaluated at each target +// point. Each row of g is the result of the transform using one set +// of weights. +FIGTREE_DLL_API +int figtreeEvaluateIfgtTree( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +FIGTREE_DLL_API +int figtreeEvaluateIfgtAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +FIGTREE_DLL_API +int figtreeEvaluateIfgtAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different for each source assuming +// the worst-case placement of any target and for each target assuming the +// worst-case placement of any source. Because the error bound is guaranteed +// to be satisfied for each source-target point pair, it is a point-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: Unlike the cluster-wise adaptive version, this does work for W>1. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptivePoint( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, + double * g ); + +//------------------------------------------------------------------------------ +// This function evaluates the IFGT by using a different truncation number for +// each cluster to ensure that the total error contribution from each +// cluster satisfies the error bound. Thus, this is the cluster-wise adaptive +// version of the IFGT. +// +// This function uses a tree for finding nearby cluster centers. +// +// See 'Automatic online tuning for fast Gaussian summation,' by Morariu et al, +// NIPS 2008 for details. +// +// NOTES: 1) Currently is not implemented to work for W>1. For W>1, use the +// point-wise adaptive version instead. +// +// 2) The method could be extended to use different truncation numbers +// for each target by splitting targets into concentric regions and +// computing the cluster-wise truncation for each concentric region +// separately (because each region will have a different max distance +// from the cluster center, the truncations will differ by region). +// However, the current implementation uses only one region for the +// targets, and varies the truncation by cluster for that region. +// +// Created by Vlad Morariu on 2008-06-04. +//------------------------------------------------------------------------------ +int figtreeEvaluateIfgtTreeAdaptiveCluster( int d, int N, int M, int W, double * x, + double h, double * q, double * y, + int pMax, int K, int * clusterIndex, + double * clusterCenter, double * clusterRadii, + double r, double epsilon, int * clusterTruncations, + double * g ); + +// Computes an approximation to Gauss Transform using approximate +// nearest-neighbors. Direct method (no taylor expansion is done), with tree +// directly on samples (part of FIGTree). Requires Approximate +// Nearest-Neighbor(ANN) library. +// +// Input +// * d --> data dimensionality. +// * N --> number of source points. +// * M --> number of target points. +// * x --> N x d matrix of N source points in d dimensions. +// * h --> the source scale or bandwidth. +// * q --> 1 x N vector of the source strengths. +// * y --> M x d matrix of M target points in d dimensions. +// * epsilon --> desired error +// +// Output +// * g --> 1 x M vector of the Gauss Transform evaluated at each target +// point. +FIGTREE_DLL_API +int figtreeEvaluateDirectTree( int d, int N, int M, double * x, double h, + double * q, double * y, double epsilon, double * g ); + +// Computes min and max values along each dimension. Used to determine +// the size of the hypercube (and the max distance R that any two pts +// can be from each other). +// +// Input +// * d --> data dimensionality. +// * n --> number of source points. +// * x --> n x d matrix of n source points in d dimensions. +// * mins --> d x 1 vector of minimum values; input values ignored if update == 0 +// * maxs --> d x 1 vector of maximum values; input values ignored if update == 0 +// * update --> if set to 1, then max[i] will contain +// max(max of values of all samples along dimension i, max[i] input value), and +// similarly for min[i]. +// +// Output +// * mins --> d x 1 vector of minimum values +// * maxs --> d x 1 vector of maximum values +FIGTREE_DLL_API +int figtreeCalcMinMax( int d, int n, double * x, double * mins, double * maxs, int update=0 ); + +FIGTREE_DLL_API +int figtreeCalcMaxRange( double d, double * mins, double * maxs, double * R ); + +#if defined(__cplusplus) && !defined(FIGTREE_STATIC) +} // extern "C" +#endif + +#endif // FIGTREE_INTERNAL_H diff --git a/dep/lapack/CMakeLists.txt b/dep/lapack/CMakeLists.txt new file mode 100644 index 00000000..e4467974 --- /dev/null +++ b/dep/lapack/CMakeLists.txt @@ -0,0 +1,13 @@ + +enable_language(Fortran) + +FILE(GLOB slsrc "*.f") +add_library(deplapack ${slsrc}) + +INSTALL(TARGETS deplapack DESTINATION lib) + +SET(lapack_HEADERS + deplapack.h + ) + +INSTALL(FILES ${lapack_HEADERS} DESTINATION include/dep) diff --git a/dep/lapack/LICENSE b/dep/lapack/LICENSE new file mode 100644 index 00000000..fd8276fc --- /dev/null +++ b/dep/lapack/LICENSE @@ -0,0 +1,52 @@ +http://www.netlib.org/lapack/LICENSE.txt +http://www.netlib.org/lapack/#_licensing + +Copyright (c) 1992-2011 The University of Tennessee and The University + of Tennessee Research Foundation. All rights + reserved. +Copyright (c) 2000-2011 The University of California Berkeley. All + rights reserved. +Copyright (c) 2006-2011 The University of Colorado Denver. All rights + reserved. + +$COPYRIGHT$ + +Additional copyrights may follow + +$HEADER$ + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +- Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer listed + in this license in the documentation and/or other materials + provided with the distribution. + +- Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +The copyright holders provide no reassurances that the source code +provided does not infringe any patent, copyright, or any other +intellectual property rights of third parties. The copyright holders +disclaim any liability to any recipient for claims brought against +recipient by any third party for infringement of that parties +intellectual property rights. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/dep/lapack/dbdsqr.f b/dep/lapack/dbdsqr.f new file mode 100644 index 00000000..4881a69f --- /dev/null +++ b/dep/lapack/dbdsqr.f @@ -0,0 +1,750 @@ + SUBROUTINE DBDSQR( UPLO, N, NCVT, NRU, NCC, D, E, VT, LDVT, U, + $ LDU, C, LDC, WORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* January 2007 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDC, LDU, LDVT, N, NCC, NCVT, NRU +* .. +* .. Array Arguments .. + DOUBLE PRECISION C( LDC, * ), D( * ), E( * ), U( LDU, * ), + $ VT( LDVT, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DBDSQR computes the singular values and, optionally, the right and/or +* left singular vectors from the singular value decomposition (SVD) of +* a real N-by-N (upper or lower) bidiagonal matrix B using the implicit +* zero-shift QR algorithm. The SVD of B has the form +* +* B = Q * S * P**T +* +* where S is the diagonal matrix of singular values, Q is an orthogonal +* matrix of left singular vectors, and P is an orthogonal matrix of +* right singular vectors. If left singular vectors are requested, this +* subroutine actually returns U*Q instead of Q, and, if right singular +* vectors are requested, this subroutine returns P**T*VT instead of +* P**T, for given real input matrices U and VT. When U and VT are the +* orthogonal matrices that reduce a general matrix A to bidiagonal +* form: A = U*B*VT, as computed by DGEBRD, then +* +* A = (U*Q) * S * (P**T*VT) +* +* is the SVD of A. Optionally, the subroutine may also compute Q**T*C +* for a given real input matrix C. +* +* See "Computing Small Singular Values of Bidiagonal Matrices With +* Guaranteed High Relative Accuracy," by J. Demmel and W. Kahan, +* LAPACK Working Note #3 (or SIAM J. Sci. Statist. Comput. vol. 11, +* no. 5, pp. 873-912, Sept 1990) and +* "Accurate singular values and differential qd algorithms," by +* B. Parlett and V. Fernando, Technical Report CPAM-554, Mathematics +* Department, University of California at Berkeley, July 1992 +* for a detailed description of the algorithm. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': B is upper bidiagonal; +* = 'L': B is lower bidiagonal. +* +* N (input) INTEGER +* The order of the matrix B. N >= 0. +* +* NCVT (input) INTEGER +* The number of columns of the matrix VT. NCVT >= 0. +* +* NRU (input) INTEGER +* The number of rows of the matrix U. NRU >= 0. +* +* NCC (input) INTEGER +* The number of columns of the matrix C. NCC >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the bidiagonal matrix B. +* On exit, if INFO=0, the singular values of B in decreasing +* order. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the N-1 offdiagonal elements of the bidiagonal +* matrix B. +* On exit, if INFO = 0, E is destroyed; if INFO > 0, D and E +* will contain the diagonal and superdiagonal elements of a +* bidiagonal matrix orthogonally equivalent to the one given +* as input. +* +* VT (input/output) DOUBLE PRECISION array, dimension (LDVT, NCVT) +* On entry, an N-by-NCVT matrix VT. +* On exit, VT is overwritten by P**T * VT. +* Not referenced if NCVT = 0. +* +* LDVT (input) INTEGER +* The leading dimension of the array VT. +* LDVT >= max(1,N) if NCVT > 0; LDVT >= 1 if NCVT = 0. +* +* U (input/output) DOUBLE PRECISION array, dimension (LDU, N) +* On entry, an NRU-by-N matrix U. +* On exit, U is overwritten by U * Q. +* Not referenced if NRU = 0. +* +* LDU (input) INTEGER +* The leading dimension of the array U. LDU >= max(1,NRU). +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC, NCC) +* On entry, an N-by-NCC matrix C. +* On exit, C is overwritten by Q**T * C. +* Not referenced if NCC = 0. +* +* LDC (input) INTEGER +* The leading dimension of the array C. +* LDC >= max(1,N) if NCC > 0; LDC >=1 if NCC = 0. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (4*N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: If INFO = -i, the i-th argument had an illegal value +* > 0: +* if NCVT = NRU = NCC = 0, +* = 1, a split was marked by a positive value in E +* = 2, current block of Z not diagonalized after 30*N +* iterations (in inner while loop) +* = 3, termination criterion of outer while loop not met +* (program created more than N unreduced blocks) +* else NCVT = NRU = NCC = 0, +* the algorithm did not converge; D and E contain the +* elements of a bidiagonal matrix which is orthogonally +* similar to the input matrix B; if INFO = i, i +* elements of E have not converged to zero. +* +* Internal Parameters +* =================== +* +* TOLMUL DOUBLE PRECISION, default = max(10,min(100,EPS**(-1/8))) +* TOLMUL controls the convergence criterion of the QR loop. +* If it is positive, TOLMUL*EPS is the desired relative +* precision in the computed singular values. +* If it is negative, abs(TOLMUL*EPS*sigma_max) is the +* desired absolute accuracy in the computed singular +* values (corresponds to relative accuracy +* abs(TOLMUL*EPS) in the largest singular value. +* abs(TOLMUL) should be between 1 and 1/EPS, and preferably +* between 10 (for fast convergence) and .1/EPS +* (for there to be some accuracy in the results). +* Default is to lose at either one eighth or 2 of the +* available decimal digits in each computed singular value +* (whichever is smaller). +* +* MAXITR INTEGER, default = 6 +* MAXITR controls the maximum number of passes of the +* algorithm through its inner loop. The algorithms stops +* (and so fails to converge) if the number of passes +* through the inner loop exceeds MAXITR*N**2. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION NEGONE + PARAMETER ( NEGONE = -1.0D0 ) + DOUBLE PRECISION HNDRTH + PARAMETER ( HNDRTH = 0.01D0 ) + DOUBLE PRECISION TEN + PARAMETER ( TEN = 10.0D0 ) + DOUBLE PRECISION HNDRD + PARAMETER ( HNDRD = 100.0D0 ) + DOUBLE PRECISION MEIGTH + PARAMETER ( MEIGTH = -0.125D0 ) + INTEGER MAXITR + PARAMETER ( MAXITR = 6 ) +* .. +* .. Local Scalars .. + LOGICAL LOWER, ROTATE + INTEGER I, IDIR, ISUB, ITER, J, LL, LLL, M, MAXIT, NM1, + $ NM12, NM13, OLDLL, OLDM + DOUBLE PRECISION ABSE, ABSS, COSL, COSR, CS, EPS, F, G, H, MU, + $ OLDCS, OLDSN, R, SHIFT, SIGMN, SIGMX, SINL, + $ SINR, SLL, SMAX, SMIN, SMINL, SMINOA, + $ SN, THRESH, TOL, TOLMUL, UNFL +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DLARTG, DLAS2, DLASQ1, DLASR, DLASV2, DROT, + $ DSCAL, DSWAP, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, MAX, MIN, SIGN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + LOWER = LSAME( UPLO, 'L' ) + IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LOWER ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NCVT.LT.0 ) THEN + INFO = -3 + ELSE IF( NRU.LT.0 ) THEN + INFO = -4 + ELSE IF( NCC.LT.0 ) THEN + INFO = -5 + ELSE IF( ( NCVT.EQ.0 .AND. LDVT.LT.1 ) .OR. + $ ( NCVT.GT.0 .AND. LDVT.LT.MAX( 1, N ) ) ) THEN + INFO = -9 + ELSE IF( LDU.LT.MAX( 1, NRU ) ) THEN + INFO = -11 + ELSE IF( ( NCC.EQ.0 .AND. LDC.LT.1 ) .OR. + $ ( NCC.GT.0 .AND. LDC.LT.MAX( 1, N ) ) ) THEN + INFO = -13 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DBDSQR', -INFO ) + RETURN + END IF + IF( N.EQ.0 ) + $ RETURN + IF( N.EQ.1 ) + $ GO TO 160 +* +* ROTATE is true if any singular vectors desired, false otherwise +* + ROTATE = ( NCVT.GT.0 ) .OR. ( NRU.GT.0 ) .OR. ( NCC.GT.0 ) +* +* If no singular vectors desired, use qd algorithm +* + IF( .NOT.ROTATE ) THEN + CALL DLASQ1( N, D, E, WORK, INFO ) + RETURN + END IF +* + NM1 = N - 1 + NM12 = NM1 + NM1 + NM13 = NM12 + NM1 + IDIR = 0 +* +* Get machine constants +* + EPS = DLAMCH( 'Epsilon' ) + UNFL = DLAMCH( 'Safe minimum' ) +* +* If matrix lower bidiagonal, rotate to be upper bidiagonal +* by applying Givens rotations on the left +* + IF( LOWER ) THEN + DO 10 I = 1, N - 1 + CALL DLARTG( D( I ), E( I ), CS, SN, R ) + D( I ) = R + E( I ) = SN*D( I+1 ) + D( I+1 ) = CS*D( I+1 ) + WORK( I ) = CS + WORK( NM1+I ) = SN + 10 CONTINUE +* +* Update singular vectors if desired +* + IF( NRU.GT.0 ) + $ CALL DLASR( 'R', 'V', 'F', NRU, N, WORK( 1 ), WORK( N ), U, + $ LDU ) + IF( NCC.GT.0 ) + $ CALL DLASR( 'L', 'V', 'F', N, NCC, WORK( 1 ), WORK( N ), C, + $ LDC ) + END IF +* +* Compute singular values to relative accuracy TOL +* (By setting TOL to be negative, algorithm will compute +* singular values to absolute accuracy ABS(TOL)*norm(input matrix)) +* + TOLMUL = MAX( TEN, MIN( HNDRD, EPS**MEIGTH ) ) + TOL = TOLMUL*EPS +* +* Compute approximate maximum, minimum singular values +* + SMAX = ZERO + DO 20 I = 1, N + SMAX = MAX( SMAX, ABS( D( I ) ) ) + 20 CONTINUE + DO 30 I = 1, N - 1 + SMAX = MAX( SMAX, ABS( E( I ) ) ) + 30 CONTINUE + SMINL = ZERO + IF( TOL.GE.ZERO ) THEN +* +* Relative accuracy desired +* + SMINOA = ABS( D( 1 ) ) + IF( SMINOA.EQ.ZERO ) + $ GO TO 50 + MU = SMINOA + DO 40 I = 2, N + MU = ABS( D( I ) )*( MU / ( MU+ABS( E( I-1 ) ) ) ) + SMINOA = MIN( SMINOA, MU ) + IF( SMINOA.EQ.ZERO ) + $ GO TO 50 + 40 CONTINUE + 50 CONTINUE + SMINOA = SMINOA / SQRT( DBLE( N ) ) + THRESH = MAX( TOL*SMINOA, MAXITR*N*N*UNFL ) + ELSE +* +* Absolute accuracy desired +* + THRESH = MAX( ABS( TOL )*SMAX, MAXITR*N*N*UNFL ) + END IF +* +* Prepare for main iteration loop for the singular values +* (MAXIT is the maximum number of passes through the inner +* loop permitted before nonconvergence signalled.) +* + MAXIT = MAXITR*N*N + ITER = 0 + OLDLL = -1 + OLDM = -1 +* +* M points to last element of unconverged part of matrix +* + M = N +* +* Begin main iteration loop +* + 60 CONTINUE +* +* Check for convergence or exceeding iteration count +* + IF( M.LE.1 ) + $ GO TO 160 + IF( ITER.GT.MAXIT ) + $ GO TO 200 +* +* Find diagonal block of matrix to work on +* + IF( TOL.LT.ZERO .AND. ABS( D( M ) ).LE.THRESH ) + $ D( M ) = ZERO + SMAX = ABS( D( M ) ) + SMIN = SMAX + DO 70 LLL = 1, M - 1 + LL = M - LLL + ABSS = ABS( D( LL ) ) + ABSE = ABS( E( LL ) ) + IF( TOL.LT.ZERO .AND. ABSS.LE.THRESH ) + $ D( LL ) = ZERO + IF( ABSE.LE.THRESH ) + $ GO TO 80 + SMIN = MIN( SMIN, ABSS ) + SMAX = MAX( SMAX, ABSS, ABSE ) + 70 CONTINUE + LL = 0 + GO TO 90 + 80 CONTINUE + E( LL ) = ZERO +* +* Matrix splits since E(LL) = 0 +* + IF( LL.EQ.M-1 ) THEN +* +* Convergence of bottom singular value, return to top of loop +* + M = M - 1 + GO TO 60 + END IF + 90 CONTINUE + LL = LL + 1 +* +* E(LL) through E(M-1) are nonzero, E(LL-1) is zero +* + IF( LL.EQ.M-1 ) THEN +* +* 2 by 2 block, handle separately +* + CALL DLASV2( D( M-1 ), E( M-1 ), D( M ), SIGMN, SIGMX, SINR, + $ COSR, SINL, COSL ) + D( M-1 ) = SIGMX + E( M-1 ) = ZERO + D( M ) = SIGMN +* +* Compute singular vectors, if desired +* + IF( NCVT.GT.0 ) + $ CALL DROT( NCVT, VT( M-1, 1 ), LDVT, VT( M, 1 ), LDVT, COSR, + $ SINR ) + IF( NRU.GT.0 ) + $ CALL DROT( NRU, U( 1, M-1 ), 1, U( 1, M ), 1, COSL, SINL ) + IF( NCC.GT.0 ) + $ CALL DROT( NCC, C( M-1, 1 ), LDC, C( M, 1 ), LDC, COSL, + $ SINL ) + M = M - 2 + GO TO 60 + END IF +* +* If working on new submatrix, choose shift direction +* (from larger end diagonal element towards smaller) +* + IF( LL.GT.OLDM .OR. M.LT.OLDLL ) THEN + IF( ABS( D( LL ) ).GE.ABS( D( M ) ) ) THEN +* +* Chase bulge from top (big end) to bottom (small end) +* + IDIR = 1 + ELSE +* +* Chase bulge from bottom (big end) to top (small end) +* + IDIR = 2 + END IF + END IF +* +* Apply convergence tests +* + IF( IDIR.EQ.1 ) THEN +* +* Run convergence test in forward direction +* First apply standard test to bottom of matrix +* + IF( ABS( E( M-1 ) ).LE.ABS( TOL )*ABS( D( M ) ) .OR. + $ ( TOL.LT.ZERO .AND. ABS( E( M-1 ) ).LE.THRESH ) ) THEN + E( M-1 ) = ZERO + GO TO 60 + END IF +* + IF( TOL.GE.ZERO ) THEN +* +* If relative accuracy desired, +* apply convergence criterion forward +* + MU = ABS( D( LL ) ) + SMINL = MU + DO 100 LLL = LL, M - 1 + IF( ABS( E( LLL ) ).LE.TOL*MU ) THEN + E( LLL ) = ZERO + GO TO 60 + END IF + MU = ABS( D( LLL+1 ) )*( MU / ( MU+ABS( E( LLL ) ) ) ) + SMINL = MIN( SMINL, MU ) + 100 CONTINUE + END IF +* + ELSE +* +* Run convergence test in backward direction +* First apply standard test to top of matrix +* + IF( ABS( E( LL ) ).LE.ABS( TOL )*ABS( D( LL ) ) .OR. + $ ( TOL.LT.ZERO .AND. ABS( E( LL ) ).LE.THRESH ) ) THEN + E( LL ) = ZERO + GO TO 60 + END IF +* + IF( TOL.GE.ZERO ) THEN +* +* If relative accuracy desired, +* apply convergence criterion backward +* + MU = ABS( D( M ) ) + SMINL = MU + DO 110 LLL = M - 1, LL, -1 + IF( ABS( E( LLL ) ).LE.TOL*MU ) THEN + E( LLL ) = ZERO + GO TO 60 + END IF + MU = ABS( D( LLL ) )*( MU / ( MU+ABS( E( LLL ) ) ) ) + SMINL = MIN( SMINL, MU ) + 110 CONTINUE + END IF + END IF + OLDLL = LL + OLDM = M +* +* Compute shift. First, test if shifting would ruin relative +* accuracy, and if so set the shift to zero. +* + IF( TOL.GE.ZERO .AND. N*TOL*( SMINL / SMAX ).LE. + $ MAX( EPS, HNDRTH*TOL ) ) THEN +* +* Use a zero shift to avoid loss of relative accuracy +* + SHIFT = ZERO + ELSE +* +* Compute the shift from 2-by-2 block at end of matrix +* + IF( IDIR.EQ.1 ) THEN + SLL = ABS( D( LL ) ) + CALL DLAS2( D( M-1 ), E( M-1 ), D( M ), SHIFT, R ) + ELSE + SLL = ABS( D( M ) ) + CALL DLAS2( D( LL ), E( LL ), D( LL+1 ), SHIFT, R ) + END IF +* +* Test if shift negligible, and if so set to zero +* + IF( SLL.GT.ZERO ) THEN + IF( ( SHIFT / SLL )**2.LT.EPS ) + $ SHIFT = ZERO + END IF + END IF +* +* Increment iteration count +* + ITER = ITER + M - LL +* +* If SHIFT = 0, do simplified QR iteration +* + IF( SHIFT.EQ.ZERO ) THEN + IF( IDIR.EQ.1 ) THEN +* +* Chase bulge from top to bottom +* Save cosines and sines for later singular vector updates +* + CS = ONE + OLDCS = ONE + DO 120 I = LL, M - 1 + CALL DLARTG( D( I )*CS, E( I ), CS, SN, R ) + IF( I.GT.LL ) + $ E( I-1 ) = OLDSN*R + CALL DLARTG( OLDCS*R, D( I+1 )*SN, OLDCS, OLDSN, D( I ) ) + WORK( I-LL+1 ) = CS + WORK( I-LL+1+NM1 ) = SN + WORK( I-LL+1+NM12 ) = OLDCS + WORK( I-LL+1+NM13 ) = OLDSN + 120 CONTINUE + H = D( M )*CS + D( M ) = H*OLDCS + E( M-1 ) = H*OLDSN +* +* Update singular vectors +* + IF( NCVT.GT.0 ) + $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCVT, WORK( 1 ), + $ WORK( N ), VT( LL, 1 ), LDVT ) + IF( NRU.GT.0 ) + $ CALL DLASR( 'R', 'V', 'F', NRU, M-LL+1, WORK( NM12+1 ), + $ WORK( NM13+1 ), U( 1, LL ), LDU ) + IF( NCC.GT.0 ) + $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCC, WORK( NM12+1 ), + $ WORK( NM13+1 ), C( LL, 1 ), LDC ) +* +* Test convergence +* + IF( ABS( E( M-1 ) ).LE.THRESH ) + $ E( M-1 ) = ZERO +* + ELSE +* +* Chase bulge from bottom to top +* Save cosines and sines for later singular vector updates +* + CS = ONE + OLDCS = ONE + DO 130 I = M, LL + 1, -1 + CALL DLARTG( D( I )*CS, E( I-1 ), CS, SN, R ) + IF( I.LT.M ) + $ E( I ) = OLDSN*R + CALL DLARTG( OLDCS*R, D( I-1 )*SN, OLDCS, OLDSN, D( I ) ) + WORK( I-LL ) = CS + WORK( I-LL+NM1 ) = -SN + WORK( I-LL+NM12 ) = OLDCS + WORK( I-LL+NM13 ) = -OLDSN + 130 CONTINUE + H = D( LL )*CS + D( LL ) = H*OLDCS + E( LL ) = H*OLDSN +* +* Update singular vectors +* + IF( NCVT.GT.0 ) + $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCVT, WORK( NM12+1 ), + $ WORK( NM13+1 ), VT( LL, 1 ), LDVT ) + IF( NRU.GT.0 ) + $ CALL DLASR( 'R', 'V', 'B', NRU, M-LL+1, WORK( 1 ), + $ WORK( N ), U( 1, LL ), LDU ) + IF( NCC.GT.0 ) + $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCC, WORK( 1 ), + $ WORK( N ), C( LL, 1 ), LDC ) +* +* Test convergence +* + IF( ABS( E( LL ) ).LE.THRESH ) + $ E( LL ) = ZERO + END IF + ELSE +* +* Use nonzero shift +* + IF( IDIR.EQ.1 ) THEN +* +* Chase bulge from top to bottom +* Save cosines and sines for later singular vector updates +* + F = ( ABS( D( LL ) )-SHIFT )* + $ ( SIGN( ONE, D( LL ) )+SHIFT / D( LL ) ) + G = E( LL ) + DO 140 I = LL, M - 1 + CALL DLARTG( F, G, COSR, SINR, R ) + IF( I.GT.LL ) + $ E( I-1 ) = R + F = COSR*D( I ) + SINR*E( I ) + E( I ) = COSR*E( I ) - SINR*D( I ) + G = SINR*D( I+1 ) + D( I+1 ) = COSR*D( I+1 ) + CALL DLARTG( F, G, COSL, SINL, R ) + D( I ) = R + F = COSL*E( I ) + SINL*D( I+1 ) + D( I+1 ) = COSL*D( I+1 ) - SINL*E( I ) + IF( I.LT.M-1 ) THEN + G = SINL*E( I+1 ) + E( I+1 ) = COSL*E( I+1 ) + END IF + WORK( I-LL+1 ) = COSR + WORK( I-LL+1+NM1 ) = SINR + WORK( I-LL+1+NM12 ) = COSL + WORK( I-LL+1+NM13 ) = SINL + 140 CONTINUE + E( M-1 ) = F +* +* Update singular vectors +* + IF( NCVT.GT.0 ) + $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCVT, WORK( 1 ), + $ WORK( N ), VT( LL, 1 ), LDVT ) + IF( NRU.GT.0 ) + $ CALL DLASR( 'R', 'V', 'F', NRU, M-LL+1, WORK( NM12+1 ), + $ WORK( NM13+1 ), U( 1, LL ), LDU ) + IF( NCC.GT.0 ) + $ CALL DLASR( 'L', 'V', 'F', M-LL+1, NCC, WORK( NM12+1 ), + $ WORK( NM13+1 ), C( LL, 1 ), LDC ) +* +* Test convergence +* + IF( ABS( E( M-1 ) ).LE.THRESH ) + $ E( M-1 ) = ZERO +* + ELSE +* +* Chase bulge from bottom to top +* Save cosines and sines for later singular vector updates +* + F = ( ABS( D( M ) )-SHIFT )*( SIGN( ONE, D( M ) )+SHIFT / + $ D( M ) ) + G = E( M-1 ) + DO 150 I = M, LL + 1, -1 + CALL DLARTG( F, G, COSR, SINR, R ) + IF( I.LT.M ) + $ E( I ) = R + F = COSR*D( I ) + SINR*E( I-1 ) + E( I-1 ) = COSR*E( I-1 ) - SINR*D( I ) + G = SINR*D( I-1 ) + D( I-1 ) = COSR*D( I-1 ) + CALL DLARTG( F, G, COSL, SINL, R ) + D( I ) = R + F = COSL*E( I-1 ) + SINL*D( I-1 ) + D( I-1 ) = COSL*D( I-1 ) - SINL*E( I-1 ) + IF( I.GT.LL+1 ) THEN + G = SINL*E( I-2 ) + E( I-2 ) = COSL*E( I-2 ) + END IF + WORK( I-LL ) = COSR + WORK( I-LL+NM1 ) = -SINR + WORK( I-LL+NM12 ) = COSL + WORK( I-LL+NM13 ) = -SINL + 150 CONTINUE + E( LL ) = F +* +* Test convergence +* + IF( ABS( E( LL ) ).LE.THRESH ) + $ E( LL ) = ZERO +* +* Update singular vectors if desired +* + IF( NCVT.GT.0 ) + $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCVT, WORK( NM12+1 ), + $ WORK( NM13+1 ), VT( LL, 1 ), LDVT ) + IF( NRU.GT.0 ) + $ CALL DLASR( 'R', 'V', 'B', NRU, M-LL+1, WORK( 1 ), + $ WORK( N ), U( 1, LL ), LDU ) + IF( NCC.GT.0 ) + $ CALL DLASR( 'L', 'V', 'B', M-LL+1, NCC, WORK( 1 ), + $ WORK( N ), C( LL, 1 ), LDC ) + END IF + END IF +* +* QR iteration finished, go back and check convergence +* + GO TO 60 +* +* All singular values converged, so make them positive +* + 160 CONTINUE + DO 170 I = 1, N + IF( D( I ).LT.ZERO ) THEN + D( I ) = -D( I ) +* +* Change sign of singular vectors, if desired +* + IF( NCVT.GT.0 ) + $ CALL DSCAL( NCVT, NEGONE, VT( I, 1 ), LDVT ) + END IF + 170 CONTINUE +* +* Sort the singular values into decreasing order (insertion sort on +* singular values, but only one transposition per singular vector) +* + DO 190 I = 1, N - 1 +* +* Scan for smallest D(I) +* + ISUB = 1 + SMIN = D( 1 ) + DO 180 J = 2, N + 1 - I + IF( D( J ).LE.SMIN ) THEN + ISUB = J + SMIN = D( J ) + END IF + 180 CONTINUE + IF( ISUB.NE.N+1-I ) THEN +* +* Swap singular values and vectors +* + D( ISUB ) = D( N+1-I ) + D( N+1-I ) = SMIN + IF( NCVT.GT.0 ) + $ CALL DSWAP( NCVT, VT( ISUB, 1 ), LDVT, VT( N+1-I, 1 ), + $ LDVT ) + IF( NRU.GT.0 ) + $ CALL DSWAP( NRU, U( 1, ISUB ), 1, U( 1, N+1-I ), 1 ) + IF( NCC.GT.0 ) + $ CALL DSWAP( NCC, C( ISUB, 1 ), LDC, C( N+1-I, 1 ), LDC ) + END IF + 190 CONTINUE + GO TO 220 +* +* Maximum number of iterations exceeded, failure to converge +* + 200 CONTINUE + INFO = 0 + DO 210 I = 1, N - 1 + IF( E( I ).NE.ZERO ) + $ INFO = INFO + 1 + 210 CONTINUE + 220 CONTINUE + RETURN +* +* End of DBDSQR +* + END diff --git a/dep/lapack/deplapack.h b/dep/lapack/deplapack.h new file mode 100644 index 00000000..1ab3565f --- /dev/null +++ b/dep/lapack/deplapack.h @@ -0,0 +1,67 @@ +#ifndef LAPACK_H +#define LAPACK_H + +#include "ftndefs.h" + +// Computes eigenvalues and eigenvectors of a real symmetric matrix A +// See dsyevx.f for details on the arguments. +extern FTN_FUNC void FTN_NAME(dsyevx)(char*, char*, char*, int*, + double*, int*, double*, double*, + int*, int*, double*, int*, + double*, double*, int*, double*, int*, + int*, int*, int*); + +// Computes Cholesky decomposition of a real symmetric matrix A +// See dpotrf.f for details on the arguments. +extern FTN_FUNC void FTN_NAME(dpotrf)(char*, int*, double*, int*, int*); + +// Computes the inverse of a real symmetric matrix A +// See dpotri.f for details on the arguments. +extern FTN_FUNC void FTN_NAME(dpotri)(char*, int*, double*, int*, int*); + +// Computes the inverse of a complex matrix +// see zgetri.f for details on the arguments. +extern FTN_FUNC void FTN_NAME(zgetri)(int*, double*, int*, int*, double*, int*, int*); + + +// Computes the least squares solution of an over-determined Ax=b +// see dgels.f for details on the arguments +extern FTN_FUNC void FTN_NAME(dgels)(char*, int*, int*, int*, double*, int*, double*, int*, double*, int*, int*); + +// Computes the LU factorization of a general matrix +// see dgetrf.f for details on the arguments +extern FTN_FUNC void FTN_NAME(dgetrf)(int*, int*, double*, int*, int*, int*); + +// Computes the inverse of a general matrix using its LU factorization +// see dgetri.f for details on the arguments +extern FTN_FUNC void FTN_NAME(dgetri)(int*, double*, int*, int*, double*, int*, int*); + +// Computes the solution to a real system of linear equations AX = B +// see dgesv.f for details on the arguments +extern FTN_FUNC void FTN_NAME(dgesv)(int*, int*, double*, int*, int*, double*, int*, int*); + +// +extern FTN_FUNC void FTN_NAME(dstev)( char *, int *, double *, double *, double *, int *, double *, int* ) ; + +// +extern FTN_FUNC void FTN_NAME(dsteqr)( char *, int *, double *, double *, double *, int *, double *, int* ) ; + +/***************************************** +New routines +*****************************************/ + +//DGEQRF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) +extern FTN_FUNC void FTN_NAME(dgeqrf)(int*, int*, double*, int*, double*, double*, int*, int*); + +// DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) +extern FTN_FUNC void FTN_NAME(dorgqr)(int*, int*, int*, double*, int*, double*, double*, int*, int*); + +// DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, +// $ WORK, LWORK, INFO ) +extern FTN_FUNC void FTN_NAME(dgesvd)(char*, char*, int*, int*, double*, int*, double*, double*, int*, double*, int*, double*, int*, int*); + +// DPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) +extern FTN_FUNC void FTN_NAME(dposv)(char*, int*, int*, double*, int*, double*, int*, int*); + + +#endif /* LAPACK_H */ diff --git a/dep/lapack/dgbsv.f b/dep/lapack/dgbsv.f new file mode 100644 index 00000000..9db11f68 --- /dev/null +++ b/dep/lapack/dgbsv.f @@ -0,0 +1,143 @@ + SUBROUTINE DGBSV( N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, INFO ) +* +* -- LAPACK driver routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, KL, KU, LDAB, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION AB( LDAB, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DGBSV computes the solution to a real system of linear equations +* A * X = B, where A is a band matrix of order N with KL subdiagonals +* and KU superdiagonals, and X and B are N-by-NRHS matrices. +* +* The LU decomposition with partial pivoting and row interchanges is +* used to factor A as A = L * U, where L is a product of permutation +* and unit lower triangular matrices with KL subdiagonals, and U is +* upper triangular with KL+KU superdiagonals. The factored form of A +* is then used to solve the system of equations A * X = B. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of linear equations, i.e., the order of the +* matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N) +* On entry, the matrix A in band storage, in rows KL+1 to +* 2*KL+KU+1; rows 1 to KL of the array need not be set. +* The j-th column of A is stored in the j-th column of the +* array AB as follows: +* AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL) +* On exit, details of the factorization: U is stored as an +* upper triangular band matrix with KL+KU superdiagonals in +* rows 1 to KL+KU+1, and the multipliers used during the +* factorization are stored in rows KL+KU+2 to 2*KL+KU+1. +* See below for further details. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices that define the permutation matrix P; +* row i of the matrix was interchanged with row IPIV(i). +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the N-by-NRHS right hand side matrix B. +* On exit, if INFO = 0, the N-by-NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and the solution has not been computed. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* M = N = 6, KL = 2, KU = 1: +* +* On entry: On exit: +* +* * * * + + + * * * u14 u25 u36 +* * * + + + + * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* a21 a32 a43 a54 a65 * m21 m32 m43 m54 m65 * +* a31 a42 a53 a64 * * m31 m42 m53 m64 * * +* +* Array elements marked * are not used by the routine; elements marked +* + need not be set on entry, but are required by the routine to store +* elements of U because of fill-in resulting from the row interchanges. +* +* ===================================================================== +* +* .. External Subroutines .. + EXTERNAL DGBTRF, DGBTRS, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( KL.LT.0 ) THEN + INFO = -2 + ELSE IF( KU.LT.0 ) THEN + INFO = -3 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.2*KL+KU+1 ) THEN + INFO = -6 + ELSE IF( LDB.LT.MAX( N, 1 ) ) THEN + INFO = -9 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGBSV ', -INFO ) + RETURN + END IF +* +* Compute the LU factorization of the band matrix A. +* + CALL DGBTRF( N, N, KL, KU, AB, LDAB, IPIV, INFO ) + IF( INFO.EQ.0 ) THEN +* +* Solve the system A*X = B, overwriting B with X. +* + CALL DGBTRS( 'No transpose', N, KL, KU, NRHS, AB, LDAB, IPIV, + $ B, LDB, INFO ) + END IF + RETURN +* +* End of DGBSV +* + END diff --git a/dep/lapack/dgbtf2.f b/dep/lapack/dgbtf2.f new file mode 100644 index 00000000..9d71af43 --- /dev/null +++ b/dep/lapack/dgbtf2.f @@ -0,0 +1,203 @@ + SUBROUTINE DGBTF2( M, N, KL, KU, AB, LDAB, IPIV, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + INTEGER INFO, KL, KU, LDAB, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* DGBTF2 computes an LU factorization of a real m-by-n band matrix A +* using partial pivoting with row interchanges. +* +* This is the unblocked version of the algorithm, calling Level 2 BLAS. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N) +* On entry, the matrix A in band storage, in rows KL+1 to +* 2*KL+KU+1; rows 1 to KL of the array need not be set. +* The j-th column of A is stored in the j-th column of the +* array AB as follows: +* AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) +* +* On exit, details of the factorization: U is stored as an +* upper triangular band matrix with KL+KU superdiagonals in +* rows 1 to KL+KU+1, and the multipliers used during the +* factorization are stored in rows KL+KU+2 to 2*KL+KU+1. +* See below for further details. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = +i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* M = N = 6, KL = 2, KU = 1: +* +* On entry: On exit: +* +* * * * + + + * * * u14 u25 u36 +* * * + + + + * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* a21 a32 a43 a54 a65 * m21 m32 m43 m54 m65 * +* a31 a42 a53 a64 * * m31 m42 m53 m64 * * +* +* Array elements marked * are not used by the routine; elements marked +* + need not be set on entry, but are required by the routine to store +* elements of U, because of fill-in resulting from the row +* interchanges. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J, JP, JU, KM, KV +* .. +* .. External Functions .. + INTEGER IDAMAX + EXTERNAL IDAMAX +* .. +* .. External Subroutines .. + EXTERNAL DGER, DSCAL, DSWAP, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* KV is the number of superdiagonals in the factor U, allowing for +* fill-in. +* + KV = KU + KL +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.KL+KV+1 ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGBTF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Gaussian elimination with partial pivoting +* +* Set fill-in elements in columns KU+2 to KV to zero. +* + DO 20 J = KU + 2, MIN( KV, N ) + DO 10 I = KV - J + 2, KL + AB( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* JU is the index of the last column affected by the current stage +* of the factorization. +* + JU = 1 +* + DO 40 J = 1, MIN( M, N ) +* +* Set fill-in elements in column J+KV to zero. +* + IF( J+KV.LE.N ) THEN + DO 30 I = 1, KL + AB( I, J+KV ) = ZERO + 30 CONTINUE + END IF +* +* Find pivot and test for singularity. KM is the number of +* subdiagonal elements in the current column. +* + KM = MIN( KL, M-J ) + JP = IDAMAX( KM+1, AB( KV+1, J ), 1 ) + IPIV( J ) = JP + J - 1 + IF( AB( KV+JP, J ).NE.ZERO ) THEN + JU = MAX( JU, MIN( J+KU+JP-1, N ) ) +* +* Apply interchange to columns J to JU. +* + IF( JP.NE.1 ) + $ CALL DSWAP( JU-J+1, AB( KV+JP, J ), LDAB-1, + $ AB( KV+1, J ), LDAB-1 ) +* + IF( KM.GT.0 ) THEN +* +* Compute multipliers. +* + CALL DSCAL( KM, ONE / AB( KV+1, J ), AB( KV+2, J ), 1 ) +* +* Update trailing submatrix within the band. +* + IF( JU.GT.J ) + $ CALL DGER( KM, JU-J, -ONE, AB( KV+2, J ), 1, + $ AB( KV, J+1 ), LDAB-1, AB( KV+1, J+1 ), + $ LDAB-1 ) + END IF + ELSE +* +* If pivot is zero, set INFO to the index of the pivot +* unless a zero pivot has already been found. +* + IF( INFO.EQ.0 ) + $ INFO = J + END IF + 40 CONTINUE + RETURN +* +* End of DGBTF2 +* + END diff --git a/dep/lapack/dgbtrf.f b/dep/lapack/dgbtrf.f new file mode 100644 index 00000000..850cbeda --- /dev/null +++ b/dep/lapack/dgbtrf.f @@ -0,0 +1,442 @@ + SUBROUTINE DGBTRF( M, N, KL, KU, AB, LDAB, IPIV, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + INTEGER INFO, KL, KU, LDAB, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION AB( LDAB, * ) +* .. +* +* Purpose +* ======= +* +* DGBTRF computes an LU factorization of a real m-by-n band matrix A +* using partial pivoting with row interchanges. +* +* This is the blocked version of the algorithm, calling Level 3 BLAS. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* AB (input/output) DOUBLE PRECISION array, dimension (LDAB,N) +* On entry, the matrix A in band storage, in rows KL+1 to +* 2*KL+KU+1; rows 1 to KL of the array need not be set. +* The j-th column of A is stored in the j-th column of the +* array AB as follows: +* AB(kl+ku+1+i-j,j) = A(i,j) for max(1,j-ku)<=i<=min(m,j+kl) +* +* On exit, details of the factorization: U is stored as an +* upper triangular band matrix with KL+KU superdiagonals in +* rows 1 to KL+KU+1, and the multipliers used during the +* factorization are stored in rows KL+KU+2 to 2*KL+KU+1. +* See below for further details. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = +i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* Further Details +* =============== +* +* The band storage scheme is illustrated by the following example, when +* M = N = 6, KL = 2, KU = 1: +* +* On entry: On exit: +* +* * * * + + + * * * u14 u25 u36 +* * * + + + + * * u13 u24 u35 u46 +* * a12 a23 a34 a45 a56 * u12 u23 u34 u45 u56 +* a11 a22 a33 a44 a55 a66 u11 u22 u33 u44 u55 u66 +* a21 a32 a43 a54 a65 * m21 m32 m43 m54 m65 * +* a31 a42 a53 a64 * * m31 m42 m53 m64 * * +* +* Array elements marked * are not used by the routine; elements marked +* + need not be set on entry, but are required by the routine to store +* elements of U because of fill-in resulting from the row interchanges. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) + INTEGER NBMAX, LDWORK + PARAMETER ( NBMAX = 64, LDWORK = NBMAX+1 ) +* .. +* .. Local Scalars .. + INTEGER I, I2, I3, II, IP, J, J2, J3, JB, JJ, JM, JP, + $ JU, K2, KM, KV, NB, NW + DOUBLE PRECISION TEMP +* .. +* .. Local Arrays .. + DOUBLE PRECISION WORK13( LDWORK, NBMAX ), + $ WORK31( LDWORK, NBMAX ) +* .. +* .. External Functions .. + INTEGER IDAMAX, ILAENV + EXTERNAL IDAMAX, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DGBTF2, DGEMM, DGER, DLASWP, DSCAL, + $ DSWAP, DTRSM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* KV is the number of superdiagonals in the factor U, allowing for +* fill-in +* + KV = KU + KL +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( LDAB.LT.KL+KV+1 ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGBTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment +* + NB = ILAENV( 1, 'DGBTRF', ' ', M, N, KL, KU ) +* +* The block size must not exceed the limit set by the size of the +* local arrays WORK13 and WORK31. +* + NB = MIN( NB, NBMAX ) +* + IF( NB.LE.1 .OR. NB.GT.KL ) THEN +* +* Use unblocked code +* + CALL DGBTF2( M, N, KL, KU, AB, LDAB, IPIV, INFO ) + ELSE +* +* Use blocked code +* +* Zero the superdiagonal elements of the work array WORK13 +* + DO 20 J = 1, NB + DO 10 I = 1, J - 1 + WORK13( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* Zero the subdiagonal elements of the work array WORK31 +* + DO 40 J = 1, NB + DO 30 I = J + 1, NB + WORK31( I, J ) = ZERO + 30 CONTINUE + 40 CONTINUE +* +* Gaussian elimination with partial pivoting +* +* Set fill-in elements in columns KU+2 to KV to zero +* + DO 60 J = KU + 2, MIN( KV, N ) + DO 50 I = KV - J + 2, KL + AB( I, J ) = ZERO + 50 CONTINUE + 60 CONTINUE +* +* JU is the index of the last column affected by the current +* stage of the factorization +* + JU = 1 +* + DO 180 J = 1, MIN( M, N ), NB + JB = MIN( NB, MIN( M, N )-J+1 ) +* +* The active part of the matrix is partitioned +* +* A11 A12 A13 +* A21 A22 A23 +* A31 A32 A33 +* +* Here A11, A21 and A31 denote the current block of JB columns +* which is about to be factorized. The number of rows in the +* partitioning are JB, I2, I3 respectively, and the numbers +* of columns are JB, J2, J3. The superdiagonal elements of A13 +* and the subdiagonal elements of A31 lie outside the band. +* + I2 = MIN( KL-JB, M-J-JB+1 ) + I3 = MIN( JB, M-J-KL+1 ) +* +* J2 and J3 are computed after JU has been updated. +* +* Factorize the current block of JB columns +* + DO 80 JJ = J, J + JB - 1 +* +* Set fill-in elements in column JJ+KV to zero +* + IF( JJ+KV.LE.N ) THEN + DO 70 I = 1, KL + AB( I, JJ+KV ) = ZERO + 70 CONTINUE + END IF +* +* Find pivot and test for singularity. KM is the number of +* subdiagonal elements in the current column. +* + KM = MIN( KL, M-JJ ) + JP = IDAMAX( KM+1, AB( KV+1, JJ ), 1 ) + IPIV( JJ ) = JP + JJ - J + IF( AB( KV+JP, JJ ).NE.ZERO ) THEN + JU = MAX( JU, MIN( JJ+KU+JP-1, N ) ) + IF( JP.NE.1 ) THEN +* +* Apply interchange to columns J to J+JB-1 +* + IF( JP+JJ-1.LT.J+KL ) THEN +* + CALL DSWAP( JB, AB( KV+1+JJ-J, J ), LDAB-1, + $ AB( KV+JP+JJ-J, J ), LDAB-1 ) + ELSE +* +* The interchange affects columns J to JJ-1 of A31 +* which are stored in the work array WORK31 +* + CALL DSWAP( JJ-J, AB( KV+1+JJ-J, J ), LDAB-1, + $ WORK31( JP+JJ-J-KL, 1 ), LDWORK ) + CALL DSWAP( J+JB-JJ, AB( KV+1, JJ ), LDAB-1, + $ AB( KV+JP, JJ ), LDAB-1 ) + END IF + END IF +* +* Compute multipliers +* + CALL DSCAL( KM, ONE / AB( KV+1, JJ ), AB( KV+2, JJ ), + $ 1 ) +* +* Update trailing submatrix within the band and within +* the current block. JM is the index of the last column +* which needs to be updated. +* + JM = MIN( JU, J+JB-1 ) + IF( JM.GT.JJ ) + $ CALL DGER( KM, JM-JJ, -ONE, AB( KV+2, JJ ), 1, + $ AB( KV, JJ+1 ), LDAB-1, + $ AB( KV+1, JJ+1 ), LDAB-1 ) + ELSE +* +* If pivot is zero, set INFO to the index of the pivot +* unless a zero pivot has already been found. +* + IF( INFO.EQ.0 ) + $ INFO = JJ + END IF +* +* Copy current column of A31 into the work array WORK31 +* + NW = MIN( JJ-J+1, I3 ) + IF( NW.GT.0 ) + $ CALL DCOPY( NW, AB( KV+KL+1-JJ+J, JJ ), 1, + $ WORK31( 1, JJ-J+1 ), 1 ) + 80 CONTINUE + IF( J+JB.LE.N ) THEN +* +* Apply the row interchanges to the other blocks. +* + J2 = MIN( JU-J+1, KV ) - JB + J3 = MAX( 0, JU-J-KV+1 ) +* +* Use DLASWP to apply the row interchanges to A12, A22, and +* A32. +* + CALL DLASWP( J2, AB( KV+1-JB, J+JB ), LDAB-1, 1, JB, + $ IPIV( J ), 1 ) +* +* Adjust the pivot indices. +* + DO 90 I = J, J + JB - 1 + IPIV( I ) = IPIV( I ) + J - 1 + 90 CONTINUE +* +* Apply the row interchanges to A13, A23, and A33 +* columnwise. +* + K2 = J - 1 + JB + J2 + DO 110 I = 1, J3 + JJ = K2 + I + DO 100 II = J + I - 1, J + JB - 1 + IP = IPIV( II ) + IF( IP.NE.II ) THEN + TEMP = AB( KV+1+II-JJ, JJ ) + AB( KV+1+II-JJ, JJ ) = AB( KV+1+IP-JJ, JJ ) + AB( KV+1+IP-JJ, JJ ) = TEMP + END IF + 100 CONTINUE + 110 CONTINUE +* +* Update the relevant part of the trailing submatrix +* + IF( J2.GT.0 ) THEN +* +* Update A12 +* + CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Unit', + $ JB, J2, ONE, AB( KV+1, J ), LDAB-1, + $ AB( KV+1-JB, J+JB ), LDAB-1 ) +* + IF( I2.GT.0 ) THEN +* +* Update A22 +* + CALL DGEMM( 'No transpose', 'No transpose', I2, J2, + $ JB, -ONE, AB( KV+1+JB, J ), LDAB-1, + $ AB( KV+1-JB, J+JB ), LDAB-1, ONE, + $ AB( KV+1, J+JB ), LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Update A32 +* + CALL DGEMM( 'No transpose', 'No transpose', I3, J2, + $ JB, -ONE, WORK31, LDWORK, + $ AB( KV+1-JB, J+JB ), LDAB-1, ONE, + $ AB( KV+KL+1-JB, J+JB ), LDAB-1 ) + END IF + END IF +* + IF( J3.GT.0 ) THEN +* +* Copy the lower triangle of A13 into the work array +* WORK13 +* + DO 130 JJ = 1, J3 + DO 120 II = JJ, JB + WORK13( II, JJ ) = AB( II-JJ+1, JJ+J+KV-1 ) + 120 CONTINUE + 130 CONTINUE +* +* Update A13 in the work array +* + CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Unit', + $ JB, J3, ONE, AB( KV+1, J ), LDAB-1, + $ WORK13, LDWORK ) +* + IF( I2.GT.0 ) THEN +* +* Update A23 +* + CALL DGEMM( 'No transpose', 'No transpose', I2, J3, + $ JB, -ONE, AB( KV+1+JB, J ), LDAB-1, + $ WORK13, LDWORK, ONE, AB( 1+JB, J+KV ), + $ LDAB-1 ) + END IF +* + IF( I3.GT.0 ) THEN +* +* Update A33 +* + CALL DGEMM( 'No transpose', 'No transpose', I3, J3, + $ JB, -ONE, WORK31, LDWORK, WORK13, + $ LDWORK, ONE, AB( 1+KL, J+KV ), LDAB-1 ) + END IF +* +* Copy the lower triangle of A13 back into place +* + DO 150 JJ = 1, J3 + DO 140 II = JJ, JB + AB( II-JJ+1, JJ+J+KV-1 ) = WORK13( II, JJ ) + 140 CONTINUE + 150 CONTINUE + END IF + ELSE +* +* Adjust the pivot indices. +* + DO 160 I = J, J + JB - 1 + IPIV( I ) = IPIV( I ) + J - 1 + 160 CONTINUE + END IF +* +* Partially undo the interchanges in the current block to +* restore the upper triangular form of A31 and copy the upper +* triangle of A31 back into place +* + DO 170 JJ = J + JB - 1, J, -1 + JP = IPIV( JJ ) - JJ + 1 + IF( JP.NE.1 ) THEN +* +* Apply interchange to columns J to JJ-1 +* + IF( JP+JJ-1.LT.J+KL ) THEN +* +* The interchange does not affect A31 +* + CALL DSWAP( JJ-J, AB( KV+1+JJ-J, J ), LDAB-1, + $ AB( KV+JP+JJ-J, J ), LDAB-1 ) + ELSE +* +* The interchange does affect A31 +* + CALL DSWAP( JJ-J, AB( KV+1+JJ-J, J ), LDAB-1, + $ WORK31( JP+JJ-J-KL, 1 ), LDWORK ) + END IF + END IF +* +* Copy the current column of A31 back into place +* + NW = MIN( I3, JJ-J+1 ) + IF( NW.GT.0 ) + $ CALL DCOPY( NW, WORK31( 1, JJ-J+1 ), 1, + $ AB( KV+KL+1-JJ+J, JJ ), 1 ) + 170 CONTINUE + 180 CONTINUE + END IF +* + RETURN +* +* End of DGBTRF +* + END diff --git a/dep/lapack/dgbtrs.f b/dep/lapack/dgbtrs.f new file mode 100644 index 00000000..b18018dc --- /dev/null +++ b/dep/lapack/dgbtrs.f @@ -0,0 +1,187 @@ + SUBROUTINE DGBTRS( TRANS, N, KL, KU, NRHS, AB, LDAB, IPIV, B, LDB, + $ INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* March 31, 1993 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, KL, KU, LDAB, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION AB( LDAB, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DGBTRS solves a system of linear equations +* A * X = B or A' * X = B +* with a general band matrix A using the LU factorization computed +* by DGBTRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER*1 +* Specifies the form of the system of equations. +* = 'N': A * X = B (No transpose) +* = 'T': A'* X = B (Transpose) +* = 'C': A'* X = B (Conjugate transpose = Transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* KL (input) INTEGER +* The number of subdiagonals within the band of A. KL >= 0. +* +* KU (input) INTEGER +* The number of superdiagonals within the band of A. KU >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* AB (input) DOUBLE PRECISION array, dimension (LDAB,N) +* Details of the LU factorization of the band matrix A, as +* computed by DGBTRF. U is stored as an upper triangular band +* matrix with KL+KU superdiagonals in rows 1 to KL+KU+1, and +* the multipliers used during the factorization are stored in +* rows KL+KU+2 to 2*KL+KU+1. +* +* LDAB (input) INTEGER +* The leading dimension of the array AB. LDAB >= 2*KL+KU+1. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= N, row i of the matrix was +* interchanged with row IPIV(i). +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LNOTI, NOTRAN + INTEGER I, J, KD, L, LM +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DGER, DSWAP, DTBSV, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( KL.LT.0 ) THEN + INFO = -3 + ELSE IF( KU.LT.0 ) THEN + INFO = -4 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -5 + ELSE IF( LDAB.LT.( 2*KL+KU+1 ) ) THEN + INFO = -7 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGBTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + KD = KU + KL + 1 + LNOTI = KL.GT.0 +* + IF( NOTRAN ) THEN +* +* Solve A*X = B. +* +* Solve L*X = B, overwriting B with X. +* +* L is represented as a product of permutations and unit lower +* triangular matrices L = P(1) * L(1) * ... * P(n-1) * L(n-1), +* where each transformation L(i) is a rank-one modification of +* the identity matrix. +* + IF( LNOTI ) THEN + DO 10 J = 1, N - 1 + LM = MIN( KL, N-J ) + L = IPIV( J ) + IF( L.NE.J ) + $ CALL DSWAP( NRHS, B( L, 1 ), LDB, B( J, 1 ), LDB ) + CALL DGER( LM, NRHS, -ONE, AB( KD+1, J ), 1, B( J, 1 ), + $ LDB, B( J+1, 1 ), LDB ) + 10 CONTINUE + END IF +* + DO 20 I = 1, NRHS +* +* Solve U*X = B, overwriting B with X. +* + CALL DTBSV( 'Upper', 'No transpose', 'Non-unit', N, KL+KU, + $ AB, LDAB, B( 1, I ), 1 ) + 20 CONTINUE +* + ELSE +* +* Solve A'*X = B. +* + DO 30 I = 1, NRHS +* +* Solve U'*X = B, overwriting B with X. +* + CALL DTBSV( 'Upper', 'Transpose', 'Non-unit', N, KL+KU, AB, + $ LDAB, B( 1, I ), 1 ) + 30 CONTINUE +* +* Solve L'*X = B, overwriting B with X. +* + IF( LNOTI ) THEN + DO 40 J = N - 1, 1, -1 + LM = MIN( KL, N-J ) + CALL DGEMV( 'Transpose', LM, NRHS, -ONE, B( J+1, 1 ), + $ LDB, AB( KD+1, J ), 1, ONE, B( J, 1 ), LDB ) + L = IPIV( J ) + IF( L.NE.J ) + $ CALL DSWAP( NRHS, B( L, 1 ), LDB, B( J, 1 ), LDB ) + 40 CONTINUE + END IF + END IF + RETURN +* +* End of DGBTRS +* + END diff --git a/dep/lapack/dgebak.f b/dep/lapack/dgebak.f new file mode 100644 index 00000000..b8e9be56 --- /dev/null +++ b/dep/lapack/dgebak.f @@ -0,0 +1,188 @@ + SUBROUTINE DGEBAK( JOB, SIDE, N, ILO, IHI, SCALE, M, V, LDV, + $ INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER JOB, SIDE + INTEGER IHI, ILO, INFO, LDV, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION SCALE( * ), V( LDV, * ) +* .. +* +* Purpose +* ======= +* +* DGEBAK forms the right or left eigenvectors of a real general matrix +* by backward transformation on the computed eigenvectors of the +* balanced matrix output by DGEBAL. +* +* Arguments +* ========= +* +* JOB (input) CHARACTER*1 +* Specifies the type of backward transformation required: +* = 'N', do nothing, return immediately; +* = 'P', do backward transformation for permutation only; +* = 'S', do backward transformation for scaling only; +* = 'B', do backward transformations for both permutation and +* scaling. +* JOB must be the same as the argument JOB supplied to DGEBAL. +* +* SIDE (input) CHARACTER*1 +* = 'R': V contains right eigenvectors; +* = 'L': V contains left eigenvectors. +* +* N (input) INTEGER +* The number of rows of the matrix V. N >= 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* The integers ILO and IHI determined by DGEBAL. +* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0. +* +* SCALE (input) DOUBLE PRECISION array, dimension (N) +* Details of the permutation and scaling factors, as returned +* by DGEBAL. +* +* M (input) INTEGER +* The number of columns of the matrix V. M >= 0. +* +* V (input/output) DOUBLE PRECISION array, dimension (LDV,M) +* On entry, the matrix of right or left eigenvectors to be +* transformed, as returned by DHSEIN or DTREVC. +* On exit, V is overwritten by the transformed eigenvectors. +* +* LDV (input) INTEGER +* The leading dimension of the array V. LDV >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LEFTV, RIGHTV + INTEGER I, II, K + DOUBLE PRECISION S +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DSCAL, DSWAP, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Decode and Test the input parameters +* + RIGHTV = LSAME( SIDE, 'R' ) + LEFTV = LSAME( SIDE, 'L' ) +* + INFO = 0 + IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.LSAME( JOB, 'P' ) .AND. + $ .NOT.LSAME( JOB, 'S' ) .AND. .NOT.LSAME( JOB, 'B' ) ) THEN + INFO = -1 + ELSE IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN + INFO = -5 + ELSE IF( M.LT.0 ) THEN + INFO = -7 + ELSE IF( LDV.LT.MAX( 1, N ) ) THEN + INFO = -9 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEBAK', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN + IF( M.EQ.0 ) + $ RETURN + IF( LSAME( JOB, 'N' ) ) + $ RETURN +* + IF( ILO.EQ.IHI ) + $ GO TO 30 +* +* Backward balance +* + IF( LSAME( JOB, 'S' ) .OR. LSAME( JOB, 'B' ) ) THEN +* + IF( RIGHTV ) THEN + DO 10 I = ILO, IHI + S = SCALE( I ) + CALL DSCAL( M, S, V( I, 1 ), LDV ) + 10 CONTINUE + END IF +* + IF( LEFTV ) THEN + DO 20 I = ILO, IHI + S = ONE / SCALE( I ) + CALL DSCAL( M, S, V( I, 1 ), LDV ) + 20 CONTINUE + END IF +* + END IF +* +* Backward permutation +* +* For I = ILO-1 step -1 until 1, +* IHI+1 step 1 until N do -- +* + 30 CONTINUE + IF( LSAME( JOB, 'P' ) .OR. LSAME( JOB, 'B' ) ) THEN + IF( RIGHTV ) THEN + DO 40 II = 1, N + I = II + IF( I.GE.ILO .AND. I.LE.IHI ) + $ GO TO 40 + IF( I.LT.ILO ) + $ I = ILO - II + K = SCALE( I ) + IF( K.EQ.I ) + $ GO TO 40 + CALL DSWAP( M, V( I, 1 ), LDV, V( K, 1 ), LDV ) + 40 CONTINUE + END IF +* + IF( LEFTV ) THEN + DO 50 II = 1, N + I = II + IF( I.GE.ILO .AND. I.LE.IHI ) + $ GO TO 50 + IF( I.LT.ILO ) + $ I = ILO - II + K = SCALE( I ) + IF( K.EQ.I ) + $ GO TO 50 + CALL DSWAP( M, V( I, 1 ), LDV, V( K, 1 ), LDV ) + 50 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEBAK +* + END diff --git a/dep/lapack/dgebal.f b/dep/lapack/dgebal.f new file mode 100644 index 00000000..e40c4453 --- /dev/null +++ b/dep/lapack/dgebal.f @@ -0,0 +1,331 @@ + SUBROUTINE DGEBAL( JOB, N, A, LDA, ILO, IHI, SCALE, INFO ) +* +* -- LAPACK routine (version 3.2.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* June 2010 +* +* .. Scalar Arguments .. + CHARACTER JOB + INTEGER IHI, ILO, INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), SCALE( * ) +* .. +* +* Purpose +* ======= +* +* DGEBAL balances a general real matrix A. This involves, first, +* permuting A by a similarity transformation to isolate eigenvalues +* in the first 1 to ILO-1 and last IHI+1 to N elements on the +* diagonal; and second, applying a diagonal similarity transformation +* to rows and columns ILO to IHI to make the rows and columns as +* close in norm as possible. Both steps are optional. +* +* Balancing may reduce the 1-norm of the matrix, and improve the +* accuracy of the computed eigenvalues and/or eigenvectors. +* +* Arguments +* ========= +* +* JOB (input) CHARACTER*1 +* Specifies the operations to be performed on A: +* = 'N': none: simply set ILO = 1, IHI = N, SCALE(I) = 1.0 +* for i = 1,...,N; +* = 'P': permute only; +* = 'S': scale only; +* = 'B': both permute and scale. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the input matrix A. +* On exit, A is overwritten by the balanced matrix. +* If JOB = 'N', A is not referenced. +* See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* ILO (output) INTEGER +* IHI (output) INTEGER +* ILO and IHI are set to integers such that on exit +* A(i,j) = 0 if i > j and j = 1,...,ILO-1 or I = IHI+1,...,N. +* If JOB = 'N' or 'S', ILO = 1 and IHI = N. +* +* SCALE (output) DOUBLE PRECISION array, dimension (N) +* Details of the permutations and scaling factors applied to +* A. If P(j) is the index of the row and column interchanged +* with row and column j and D(j) is the scaling factor +* applied to row and column j, then +* SCALE(j) = P(j) for j = 1,...,ILO-1 +* = D(j) for j = ILO,...,IHI +* = P(j) for j = IHI+1,...,N. +* The order in which the interchanges are made is N to IHI+1, +* then 1 to ILO-1. +* +* INFO (output) INTEGER +* = 0: successful exit. +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* Further Details +* =============== +* +* The permutations consist of row and column interchanges which put +* the matrix in the form +* +* ( T1 X Y ) +* P A P = ( 0 B Z ) +* ( 0 0 T2 ) +* +* where T1 and T2 are upper triangular matrices whose eigenvalues lie +* along the diagonal. The column indices ILO and IHI mark the starting +* and ending columns of the submatrix B. Balancing consists of applying +* a diagonal similarity transformation inv(D) * B * D to make the +* 1-norms of each row of B and its corresponding column nearly equal. +* The output matrix is +* +* ( T1 X*D Y ) +* ( 0 inv(D)*B*D inv(D)*Z ). +* ( 0 0 T2 ) +* +* Information about the permutations P and the diagonal matrix D is +* returned in the vector SCALE. +* +* This subroutine is based on the EISPACK routine BALANC. +* +* Modified by Tzu-Yi Chen, Computer Science Division, University of +* California at Berkeley, USA +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) + DOUBLE PRECISION SCLFAC + PARAMETER ( SCLFAC = 2.0D+0 ) + DOUBLE PRECISION FACTOR + PARAMETER ( FACTOR = 0.95D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOCONV + INTEGER I, ICA, IEXC, IRA, J, K, L, M + DOUBLE PRECISION C, CA, F, G, R, RA, S, SFMAX1, SFMAX2, SFMIN1, + $ SFMIN2 +* .. +* .. External Functions .. + LOGICAL DISNAN, LSAME + INTEGER IDAMAX + DOUBLE PRECISION DLAMCH + EXTERNAL DISNAN, LSAME, IDAMAX, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DSCAL, DSWAP, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.LSAME( JOB, 'P' ) .AND. + $ .NOT.LSAME( JOB, 'S' ) .AND. .NOT.LSAME( JOB, 'B' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEBAL', -INFO ) + RETURN + END IF +* + K = 1 + L = N +* + IF( N.EQ.0 ) + $ GO TO 210 +* + IF( LSAME( JOB, 'N' ) ) THEN + DO 10 I = 1, N + SCALE( I ) = ONE + 10 CONTINUE + GO TO 210 + END IF +* + IF( LSAME( JOB, 'S' ) ) + $ GO TO 120 +* +* Permutation to isolate eigenvalues if possible +* + GO TO 50 +* +* Row and column exchange. +* + 20 CONTINUE + SCALE( M ) = J + IF( J.EQ.M ) + $ GO TO 30 +* + CALL DSWAP( L, A( 1, J ), 1, A( 1, M ), 1 ) + CALL DSWAP( N-K+1, A( J, K ), LDA, A( M, K ), LDA ) +* + 30 CONTINUE + GO TO ( 40, 80 )IEXC +* +* Search for rows isolating an eigenvalue and push them down. +* + 40 CONTINUE + IF( L.EQ.1 ) + $ GO TO 210 + L = L - 1 +* + 50 CONTINUE + DO 70 J = L, 1, -1 +* + DO 60 I = 1, L + IF( I.EQ.J ) + $ GO TO 60 + IF( A( J, I ).NE.ZERO ) + $ GO TO 70 + 60 CONTINUE +* + M = L + IEXC = 1 + GO TO 20 + 70 CONTINUE +* + GO TO 90 +* +* Search for columns isolating an eigenvalue and push them left. +* + 80 CONTINUE + K = K + 1 +* + 90 CONTINUE + DO 110 J = K, L +* + DO 100 I = K, L + IF( I.EQ.J ) + $ GO TO 100 + IF( A( I, J ).NE.ZERO ) + $ GO TO 110 + 100 CONTINUE +* + M = K + IEXC = 2 + GO TO 20 + 110 CONTINUE +* + 120 CONTINUE + DO 130 I = K, L + SCALE( I ) = ONE + 130 CONTINUE +* + IF( LSAME( JOB, 'P' ) ) + $ GO TO 210 +* +* Balance the submatrix in rows K to L. +* +* Iterative loop for norm reduction +* + SFMIN1 = DLAMCH( 'S' ) / DLAMCH( 'P' ) + SFMAX1 = ONE / SFMIN1 + SFMIN2 = SFMIN1*SCLFAC + SFMAX2 = ONE / SFMIN2 + 140 CONTINUE + NOCONV = .FALSE. +* + DO 200 I = K, L + C = ZERO + R = ZERO +* + DO 150 J = K, L + IF( J.EQ.I ) + $ GO TO 150 + C = C + ABS( A( J, I ) ) + R = R + ABS( A( I, J ) ) + 150 CONTINUE + ICA = IDAMAX( L, A( 1, I ), 1 ) + CA = ABS( A( ICA, I ) ) + IRA = IDAMAX( N-K+1, A( I, K ), LDA ) + RA = ABS( A( I, IRA+K-1 ) ) +* +* Guard against zero C or R due to underflow. +* + IF( C.EQ.ZERO .OR. R.EQ.ZERO ) + $ GO TO 200 + G = R / SCLFAC + F = ONE + S = C + R + 160 CONTINUE + IF( C.GE.G .OR. MAX( F, C, CA ).GE.SFMAX2 .OR. + $ MIN( R, G, RA ).LE.SFMIN2 )GO TO 170 + IF( DISNAN( C+F+CA+R+G+RA ) ) THEN +* +* Exit if NaN to avoid infinite loop +* + INFO = -3 + CALL XERBLA( 'DGEBAL', -INFO ) + RETURN + END IF + F = F*SCLFAC + C = C*SCLFAC + CA = CA*SCLFAC + R = R / SCLFAC + G = G / SCLFAC + RA = RA / SCLFAC + GO TO 160 +* + 170 CONTINUE + G = C / SCLFAC + 180 CONTINUE + IF( G.LT.R .OR. MAX( R, RA ).GE.SFMAX2 .OR. + $ MIN( F, C, G, CA ).LE.SFMIN2 )GO TO 190 + F = F / SCLFAC + C = C / SCLFAC + G = G / SCLFAC + CA = CA / SCLFAC + R = R*SCLFAC + RA = RA*SCLFAC + GO TO 180 +* +* Now balance. +* + 190 CONTINUE + IF( ( C+R ).GE.FACTOR*S ) + $ GO TO 200 + IF( F.LT.ONE .AND. SCALE( I ).LT.ONE ) THEN + IF( F*SCALE( I ).LE.SFMIN1 ) + $ GO TO 200 + END IF + IF( F.GT.ONE .AND. SCALE( I ).GT.ONE ) THEN + IF( SCALE( I ).GE.SFMAX1 / F ) + $ GO TO 200 + END IF + G = ONE / F + SCALE( I ) = SCALE( I )*F + NOCONV = .TRUE. +* + CALL DSCAL( N-K+1, G, A( I, K ), LDA ) + CALL DSCAL( L, F, A( 1, I ), 1 ) +* + 200 CONTINUE +* + IF( NOCONV ) + $ GO TO 140 +* + 210 CONTINUE + ILO = K + IHI = L +* + RETURN +* +* End of DGEBAL +* + END diff --git a/dep/lapack/dgebd2.f b/dep/lapack/dgebd2.f new file mode 100644 index 00000000..d0efbf48 --- /dev/null +++ b/dep/lapack/dgebd2.f @@ -0,0 +1,240 @@ + SUBROUTINE DGEBD2( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ), + $ TAUQ( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGEBD2 reduces a real general m by n matrix A to upper or lower +* bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. +* +* If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows in the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns in the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the m by n general matrix to be reduced. +* On exit, +* if m >= n, the diagonal and the first superdiagonal are +* overwritten with the upper bidiagonal matrix B; the +* elements below the diagonal, with the array TAUQ, represent +* the orthogonal matrix Q as a product of elementary +* reflectors, and the elements above the first superdiagonal, +* with the array TAUP, represent the orthogonal matrix P as +* a product of elementary reflectors; +* if m < n, the diagonal and the first subdiagonal are +* overwritten with the lower bidiagonal matrix B; the +* elements below the first subdiagonal, with the array TAUQ, +* represent the orthogonal matrix Q as a product of +* elementary reflectors, and the elements above the diagonal, +* with the array TAUP, represent the orthogonal matrix P as +* a product of elementary reflectors. +* See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* D (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The diagonal elements of the bidiagonal matrix B: +* D(i) = A(i,i). +* +* E (output) DOUBLE PRECISION array, dimension (min(M,N)-1) +* The off-diagonal elements of the bidiagonal matrix B: +* if m >= n, E(i) = A(i,i+1) for i = 1,2,...,n-1; +* if m < n, E(i) = A(i+1,i) for i = 1,2,...,m-1. +* +* TAUQ (output) DOUBLE PRECISION array dimension (min(M,N)) +* The scalar factors of the elementary reflectors which +* represent the orthogonal matrix Q. See Further Details. +* +* TAUP (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The scalar factors of the elementary reflectors which +* represent the orthogonal matrix P. See Further Details. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (max(M,N)) +* +* INFO (output) INTEGER +* = 0: successful exit. +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* Further Details +* =============== +* +* The matrices Q and P are represented as products of elementary +* reflectors: +* +* If m >= n, +* +* Q = H(1) H(2) . . . H(n) and P = G(1) G(2) . . . G(n-1) +* +* Each H(i) and G(i) has the form: +* +* H(i) = I - tauq * v * v**T and G(i) = I - taup * u * u**T +* +* where tauq and taup are real scalars, and v and u are real vectors; +* v(1:i-1) = 0, v(i) = 1, and v(i+1:m) is stored on exit in A(i+1:m,i); +* u(1:i) = 0, u(i+1) = 1, and u(i+2:n) is stored on exit in A(i,i+2:n); +* tauq is stored in TAUQ(i) and taup in TAUP(i). +* +* If m < n, +* +* Q = H(1) H(2) . . . H(m-1) and P = G(1) G(2) . . . G(m) +* +* Each H(i) and G(i) has the form: +* +* H(i) = I - tauq * v * v**T and G(i) = I - taup * u * u**T +* +* where tauq and taup are real scalars, and v and u are real vectors; +* v(1:i) = 0, v(i+1) = 1, and v(i+2:m) is stored on exit in A(i+2:m,i); +* u(1:i-1) = 0, u(i) = 1, and u(i+1:n) is stored on exit in A(i,i+1:n); +* tauq is stored in TAUQ(i) and taup in TAUP(i). +* +* The contents of A on exit are illustrated by the following examples: +* +* m = 6 and n = 5 (m > n): m = 5 and n = 6 (m < n): +* +* ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) +* ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) +* ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) +* ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) +* ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) +* ( v1 v2 v3 v4 v5 ) +* +* where d and e denote diagonal and off-diagonal elements of B, vi +* denotes an element of the vector defining H(i), and ui an element of +* the vector defining G(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DLARFG, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.LT.0 ) THEN + CALL XERBLA( 'DGEBD2', -INFO ) + RETURN + END IF +* + IF( M.GE.N ) THEN +* +* Reduce to upper bidiagonal form +* + DO 10 I = 1, N +* +* Generate elementary reflector H(i) to annihilate A(i+1:m,i) +* + CALL DLARFG( M-I+1, A( I, I ), A( MIN( I+1, M ), I ), 1, + $ TAUQ( I ) ) + D( I ) = A( I, I ) + A( I, I ) = ONE +* +* Apply H(i) to A(i:m,i+1:n) from the left +* + IF( I.LT.N ) + $ CALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAUQ( I ), + $ A( I, I+1 ), LDA, WORK ) + A( I, I ) = D( I ) +* + IF( I.LT.N ) THEN +* +* Generate elementary reflector G(i) to annihilate +* A(i,i+2:n) +* + CALL DLARFG( N-I, A( I, I+1 ), A( I, MIN( I+2, N ) ), + $ LDA, TAUP( I ) ) + E( I ) = A( I, I+1 ) + A( I, I+1 ) = ONE +* +* Apply G(i) to A(i+1:m,i+1:n) from the right +* + CALL DLARF( 'Right', M-I, N-I, A( I, I+1 ), LDA, + $ TAUP( I ), A( I+1, I+1 ), LDA, WORK ) + A( I, I+1 ) = E( I ) + ELSE + TAUP( I ) = ZERO + END IF + 10 CONTINUE + ELSE +* +* Reduce to lower bidiagonal form +* + DO 20 I = 1, M +* +* Generate elementary reflector G(i) to annihilate A(i,i+1:n) +* + CALL DLARFG( N-I+1, A( I, I ), A( I, MIN( I+1, N ) ), LDA, + $ TAUP( I ) ) + D( I ) = A( I, I ) + A( I, I ) = ONE +* +* Apply G(i) to A(i+1:m,i:n) from the right +* + IF( I.LT.M ) + $ CALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA, + $ TAUP( I ), A( I+1, I ), LDA, WORK ) + A( I, I ) = D( I ) +* + IF( I.LT.M ) THEN +* +* Generate elementary reflector H(i) to annihilate +* A(i+2:m,i) +* + CALL DLARFG( M-I, A( I+1, I ), A( MIN( I+2, M ), I ), 1, + $ TAUQ( I ) ) + E( I ) = A( I+1, I ) + A( I+1, I ) = ONE +* +* Apply H(i) to A(i+1:m,i+1:n) from the left +* + CALL DLARF( 'Left', M-I, N-I, A( I+1, I ), 1, TAUQ( I ), + $ A( I+1, I+1 ), LDA, WORK ) + A( I+1, I ) = E( I ) + ELSE + TAUQ( I ) = ZERO + END IF + 20 CONTINUE + END IF + RETURN +* +* End of DGEBD2 +* + END diff --git a/dep/lapack/dgebrd.f b/dep/lapack/dgebrd.f new file mode 100644 index 00000000..f4118c7d --- /dev/null +++ b/dep/lapack/dgebrd.f @@ -0,0 +1,269 @@ + SUBROUTINE DGEBRD( M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, + $ INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ), + $ TAUQ( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGEBRD reduces a general real M-by-N matrix A to upper or lower +* bidiagonal form B by an orthogonal transformation: Q**T * A * P = B. +* +* If m >= n, B is upper bidiagonal; if m < n, B is lower bidiagonal. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows in the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns in the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the M-by-N general matrix to be reduced. +* On exit, +* if m >= n, the diagonal and the first superdiagonal are +* overwritten with the upper bidiagonal matrix B; the +* elements below the diagonal, with the array TAUQ, represent +* the orthogonal matrix Q as a product of elementary +* reflectors, and the elements above the first superdiagonal, +* with the array TAUP, represent the orthogonal matrix P as +* a product of elementary reflectors; +* if m < n, the diagonal and the first subdiagonal are +* overwritten with the lower bidiagonal matrix B; the +* elements below the first subdiagonal, with the array TAUQ, +* represent the orthogonal matrix Q as a product of +* elementary reflectors, and the elements above the diagonal, +* with the array TAUP, represent the orthogonal matrix P as +* a product of elementary reflectors. +* See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* D (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The diagonal elements of the bidiagonal matrix B: +* D(i) = A(i,i). +* +* E (output) DOUBLE PRECISION array, dimension (min(M,N)-1) +* The off-diagonal elements of the bidiagonal matrix B: +* if m >= n, E(i) = A(i,i+1) for i = 1,2,...,n-1; +* if m < n, E(i) = A(i+1,i) for i = 1,2,...,m-1. +* +* TAUQ (output) DOUBLE PRECISION array dimension (min(M,N)) +* The scalar factors of the elementary reflectors which +* represent the orthogonal matrix Q. See Further Details. +* +* TAUP (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The scalar factors of the elementary reflectors which +* represent the orthogonal matrix P. See Further Details. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The length of the array WORK. LWORK >= max(1,M,N). +* For optimum performance LWORK >= (M+N)*NB, where NB +* is the optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* Further Details +* =============== +* +* The matrices Q and P are represented as products of elementary +* reflectors: +* +* If m >= n, +* +* Q = H(1) H(2) . . . H(n) and P = G(1) G(2) . . . G(n-1) +* +* Each H(i) and G(i) has the form: +* +* H(i) = I - tauq * v * v**T and G(i) = I - taup * u * u**T +* +* where tauq and taup are real scalars, and v and u are real vectors; +* v(1:i-1) = 0, v(i) = 1, and v(i+1:m) is stored on exit in A(i+1:m,i); +* u(1:i) = 0, u(i+1) = 1, and u(i+2:n) is stored on exit in A(i,i+2:n); +* tauq is stored in TAUQ(i) and taup in TAUP(i). +* +* If m < n, +* +* Q = H(1) H(2) . . . H(m-1) and P = G(1) G(2) . . . G(m) +* +* Each H(i) and G(i) has the form: +* +* H(i) = I - tauq * v * v**T and G(i) = I - taup * u * u**T +* +* where tauq and taup are real scalars, and v and u are real vectors; +* v(1:i) = 0, v(i+1) = 1, and v(i+2:m) is stored on exit in A(i+2:m,i); +* u(1:i-1) = 0, u(i) = 1, and u(i+1:n) is stored on exit in A(i,i+1:n); +* tauq is stored in TAUQ(i) and taup in TAUP(i). +* +* The contents of A on exit are illustrated by the following examples: +* +* m = 6 and n = 5 (m > n): m = 5 and n = 6 (m < n): +* +* ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 ) +* ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 ) +* ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 ) +* ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 ) +* ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 ) +* ( v1 v2 v3 v4 v5 ) +* +* where d and e denote diagonal and off-diagonal elements of B, vi +* denotes an element of the vector defining H(i), and ui an element of +* the vector defining G(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IINFO, J, LDWRKX, LDWRKY, LWKOPT, MINMN, NB, + $ NBMIN, NX + DOUBLE PRECISION WS +* .. +* .. External Subroutines .. + EXTERNAL DGEBD2, DGEMM, DLABRD, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + NB = MAX( 1, ILAENV( 1, 'DGEBRD', ' ', M, N, -1, -1 ) ) + LWKOPT = ( M+N )*NB + WORK( 1 ) = DBLE( LWKOPT ) + LQUERY = ( LWORK.EQ.-1 ) + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + ELSE IF( LWORK.LT.MAX( 1, M, N ) .AND. .NOT.LQUERY ) THEN + INFO = -10 + END IF + IF( INFO.LT.0 ) THEN + CALL XERBLA( 'DGEBRD', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + MINMN = MIN( M, N ) + IF( MINMN.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + WS = MAX( M, N ) + LDWRKX = M + LDWRKY = N +* + IF( NB.GT.1 .AND. NB.LT.MINMN ) THEN +* +* Set the crossover point NX. +* + NX = MAX( NB, ILAENV( 3, 'DGEBRD', ' ', M, N, -1, -1 ) ) +* +* Determine when to switch from blocked to unblocked code. +* + IF( NX.LT.MINMN ) THEN + WS = ( M+N )*NB + IF( LWORK.LT.WS ) THEN +* +* Not enough work space for the optimal NB, consider using +* a smaller block size. +* + NBMIN = ILAENV( 2, 'DGEBRD', ' ', M, N, -1, -1 ) + IF( LWORK.GE.( M+N )*NBMIN ) THEN + NB = LWORK / ( M+N ) + ELSE + NB = 1 + NX = MINMN + END IF + END IF + END IF + ELSE + NX = MINMN + END IF +* + DO 30 I = 1, MINMN - NX, NB +* +* Reduce rows and columns i:i+nb-1 to bidiagonal form and return +* the matrices X and Y which are needed to update the unreduced +* part of the matrix +* + CALL DLABRD( M-I+1, N-I+1, NB, A( I, I ), LDA, D( I ), E( I ), + $ TAUQ( I ), TAUP( I ), WORK, LDWRKX, + $ WORK( LDWRKX*NB+1 ), LDWRKY ) +* +* Update the trailing submatrix A(i+nb:m,i+nb:n), using an update +* of the form A := A - V*Y**T - X*U**T +* + CALL DGEMM( 'No transpose', 'Transpose', M-I-NB+1, N-I-NB+1, + $ NB, -ONE, A( I+NB, I ), LDA, + $ WORK( LDWRKX*NB+NB+1 ), LDWRKY, ONE, + $ A( I+NB, I+NB ), LDA ) + CALL DGEMM( 'No transpose', 'No transpose', M-I-NB+1, N-I-NB+1, + $ NB, -ONE, WORK( NB+1 ), LDWRKX, A( I, I+NB ), LDA, + $ ONE, A( I+NB, I+NB ), LDA ) +* +* Copy diagonal and off-diagonal elements of B back into A +* + IF( M.GE.N ) THEN + DO 10 J = I, I + NB - 1 + A( J, J ) = D( J ) + A( J, J+1 ) = E( J ) + 10 CONTINUE + ELSE + DO 20 J = I, I + NB - 1 + A( J, J ) = D( J ) + A( J+1, J ) = E( J ) + 20 CONTINUE + END IF + 30 CONTINUE +* +* Use unblocked code to reduce the remainder of the matrix +* + CALL DGEBD2( M-I+1, N-I+1, A( I, I ), LDA, D( I ), E( I ), + $ TAUQ( I ), TAUP( I ), WORK, IINFO ) + WORK( 1 ) = WS + RETURN +* +* End of DGEBRD +* + END diff --git a/dep/lapack/dgeev.f b/dep/lapack/dgeev.f new file mode 100644 index 00000000..8f8d0b82 --- /dev/null +++ b/dep/lapack/dgeev.f @@ -0,0 +1,424 @@ + SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, + $ LDVR, WORK, LWORK, INFO ) +* +* -- LAPACK driver routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER JOBVL, JOBVR + INTEGER INFO, LDA, LDVL, LDVR, LWORK, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), VL( LDVL, * ), VR( LDVR, * ), + $ WI( * ), WORK( * ), WR( * ) +* .. +* +* Purpose +* ======= +* +* DGEEV computes for an N-by-N real nonsymmetric matrix A, the +* eigenvalues and, optionally, the left and/or right eigenvectors. +* +* The right eigenvector v(j) of A satisfies +* A * v(j) = lambda(j) * v(j) +* where lambda(j) is its eigenvalue. +* The left eigenvector u(j) of A satisfies +* u(j)**H * A = lambda(j) * u(j)**H +* where u(j)**H denotes the conjugate transpose of u(j). +* +* The computed eigenvectors are normalized to have Euclidean norm +* equal to 1 and largest component real. +* +* Arguments +* ========= +* +* JOBVL (input) CHARACTER*1 +* = 'N': left eigenvectors of A are not computed; +* = 'V': left eigenvectors of A are computed. +* +* JOBVR (input) CHARACTER*1 +* = 'N': right eigenvectors of A are not computed; +* = 'V': right eigenvectors of A are computed. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the N-by-N matrix A. +* On exit, A has been overwritten. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* WR (output) DOUBLE PRECISION array, dimension (N) +* WI (output) DOUBLE PRECISION array, dimension (N) +* WR and WI contain the real and imaginary parts, +* respectively, of the computed eigenvalues. Complex +* conjugate pairs of eigenvalues appear consecutively +* with the eigenvalue having the positive imaginary part +* first. +* +* VL (output) DOUBLE PRECISION array, dimension (LDVL,N) +* If JOBVL = 'V', the left eigenvectors u(j) are stored one +* after another in the columns of VL, in the same order +* as their eigenvalues. +* If JOBVL = 'N', VL is not referenced. +* If the j-th eigenvalue is real, then u(j) = VL(:,j), +* the j-th column of VL. +* If the j-th and (j+1)-st eigenvalues form a complex +* conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and +* u(j+1) = VL(:,j) - i*VL(:,j+1). +* +* LDVL (input) INTEGER +* The leading dimension of the array VL. LDVL >= 1; if +* JOBVL = 'V', LDVL >= N. +* +* VR (output) DOUBLE PRECISION array, dimension (LDVR,N) +* If JOBVR = 'V', the right eigenvectors v(j) are stored one +* after another in the columns of VR, in the same order +* as their eigenvalues. +* If JOBVR = 'N', VR is not referenced. +* If the j-th eigenvalue is real, then v(j) = VR(:,j), +* the j-th column of VR. +* If the j-th and (j+1)-st eigenvalues form a complex +* conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and +* v(j+1) = VR(:,j) - i*VR(:,j+1). +* +* LDVR (input) INTEGER +* The leading dimension of the array VR. LDVR >= 1; if +* JOBVR = 'V', LDVR >= N. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,3*N), and +* if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N. For good +* performance, LWORK must generally be larger. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value. +* > 0: if INFO = i, the QR algorithm failed to compute all the +* eigenvalues, and no eigenvectors have been computed; +* elements i+1:N of WR and WI contain eigenvalues which +* have converged. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY, SCALEA, WANTVL, WANTVR + CHARACTER SIDE + INTEGER HSWORK, I, IBAL, IERR, IHI, ILO, ITAU, IWRK, K, + $ MAXWRK, MINWRK, NOUT + DOUBLE PRECISION ANRM, BIGNUM, CS, CSCALE, EPS, R, SCL, SMLNUM, + $ SN +* .. +* .. Local Arrays .. + LOGICAL SELECT( 1 ) + DOUBLE PRECISION DUM( 1 ) +* .. +* .. External Subroutines .. + EXTERNAL DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLABAD, DLACPY, + $ DLARTG, DLASCL, DORGHR, DROT, DSCAL, DTREVC, + $ XERBLA +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IDAMAX, ILAENV + DOUBLE PRECISION DLAMCH, DLANGE, DLAPY2, DNRM2 + EXTERNAL LSAME, IDAMAX, ILAENV, DLAMCH, DLANGE, DLAPY2, + $ DNRM2 +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, SQRT +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LQUERY = ( LWORK.EQ.-1 ) + WANTVL = LSAME( JOBVL, 'V' ) + WANTVR = LSAME( JOBVR, 'V' ) + IF( ( .NOT.WANTVL ) .AND. ( .NOT.LSAME( JOBVL, 'N' ) ) ) THEN + INFO = -1 + ELSE IF( ( .NOT.WANTVR ) .AND. ( .NOT.LSAME( JOBVR, 'N' ) ) ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LDVL.LT.1 .OR. ( WANTVL .AND. LDVL.LT.N ) ) THEN + INFO = -9 + ELSE IF( LDVR.LT.1 .OR. ( WANTVR .AND. LDVR.LT.N ) ) THEN + INFO = -11 + END IF +* +* Compute workspace +* (Note: Comments in the code beginning "Workspace:" describe the +* minimal amount of workspace needed at that point in the code, +* as well as the preferred amount for good performance. +* NB refers to the optimal block size for the immediately +* following subroutine, as returned by ILAENV. +* HSWORK refers to the workspace preferred by DHSEQR, as +* calculated below. HSWORK is computed assuming ILO=1 and IHI=N, +* the worst case.) +* + IF( INFO.EQ.0 ) THEN + IF( N.EQ.0 ) THEN + MINWRK = 1 + MAXWRK = 1 + ELSE + MAXWRK = 2*N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 ) + IF( WANTVL ) THEN + MINWRK = 4*N + MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1, + $ 'DORGHR', ' ', N, 1, N, -1 ) ) + CALL DHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VL, LDVL, + $ WORK, -1, INFO ) + HSWORK = WORK( 1 ) + MAXWRK = MAX( MAXWRK, N + 1, N + HSWORK ) + MAXWRK = MAX( MAXWRK, 4*N ) + ELSE IF( WANTVR ) THEN + MINWRK = 4*N + MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1, + $ 'DORGHR', ' ', N, 1, N, -1 ) ) + CALL DHSEQR( 'S', 'V', N, 1, N, A, LDA, WR, WI, VR, LDVR, + $ WORK, -1, INFO ) + HSWORK = WORK( 1 ) + MAXWRK = MAX( MAXWRK, N + 1, N + HSWORK ) + MAXWRK = MAX( MAXWRK, 4*N ) + ELSE + MINWRK = 3*N + CALL DHSEQR( 'E', 'N', N, 1, N, A, LDA, WR, WI, VR, LDVR, + $ WORK, -1, INFO ) + HSWORK = WORK( 1 ) + MAXWRK = MAX( MAXWRK, N + 1, N + HSWORK ) + END IF + MAXWRK = MAX( MAXWRK, MINWRK ) + END IF + WORK( 1 ) = MAXWRK +* + IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN + INFO = -13 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEEV ', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Get machine constants +* + EPS = DLAMCH( 'P' ) + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM + CALL DLABAD( SMLNUM, BIGNUM ) + SMLNUM = SQRT( SMLNUM ) / EPS + BIGNUM = ONE / SMLNUM +* +* Scale A if max element outside range [SMLNUM,BIGNUM] +* + ANRM = DLANGE( 'M', N, N, A, LDA, DUM ) + SCALEA = .FALSE. + IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN + SCALEA = .TRUE. + CSCALE = SMLNUM + ELSE IF( ANRM.GT.BIGNUM ) THEN + SCALEA = .TRUE. + CSCALE = BIGNUM + END IF + IF( SCALEA ) + $ CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR ) +* +* Balance the matrix +* (Workspace: need N) +* + IBAL = 1 + CALL DGEBAL( 'B', N, A, LDA, ILO, IHI, WORK( IBAL ), IERR ) +* +* Reduce to upper Hessenberg form +* (Workspace: need 3*N, prefer 2*N+N*NB) +* + ITAU = IBAL + N + IWRK = ITAU + N + CALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ), + $ LWORK-IWRK+1, IERR ) +* + IF( WANTVL ) THEN +* +* Want left eigenvectors +* Copy Householder vectors to VL +* + SIDE = 'L' + CALL DLACPY( 'L', N, N, A, LDA, VL, LDVL ) +* +* Generate orthogonal matrix in VL +* (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB) +* + CALL DORGHR( N, ILO, IHI, VL, LDVL, WORK( ITAU ), WORK( IWRK ), + $ LWORK-IWRK+1, IERR ) +* +* Perform QR iteration, accumulating Schur vectors in VL +* (Workspace: need N+1, prefer N+HSWORK (see comments) ) +* + IWRK = ITAU + CALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VL, LDVL, + $ WORK( IWRK ), LWORK-IWRK+1, INFO ) +* + IF( WANTVR ) THEN +* +* Want left and right eigenvectors +* Copy Schur vectors to VR +* + SIDE = 'B' + CALL DLACPY( 'F', N, N, VL, LDVL, VR, LDVR ) + END IF +* + ELSE IF( WANTVR ) THEN +* +* Want right eigenvectors +* Copy Householder vectors to VR +* + SIDE = 'R' + CALL DLACPY( 'L', N, N, A, LDA, VR, LDVR ) +* +* Generate orthogonal matrix in VR +* (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB) +* + CALL DORGHR( N, ILO, IHI, VR, LDVR, WORK( ITAU ), WORK( IWRK ), + $ LWORK-IWRK+1, IERR ) +* +* Perform QR iteration, accumulating Schur vectors in VR +* (Workspace: need N+1, prefer N+HSWORK (see comments) ) +* + IWRK = ITAU + CALL DHSEQR( 'S', 'V', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR, + $ WORK( IWRK ), LWORK-IWRK+1, INFO ) +* + ELSE +* +* Compute eigenvalues only +* (Workspace: need N+1, prefer N+HSWORK (see comments) ) +* + IWRK = ITAU + CALL DHSEQR( 'E', 'N', N, ILO, IHI, A, LDA, WR, WI, VR, LDVR, + $ WORK( IWRK ), LWORK-IWRK+1, INFO ) + END IF +* +* If INFO > 0 from DHSEQR, then quit +* + IF( INFO.GT.0 ) + $ GO TO 50 +* + IF( WANTVL .OR. WANTVR ) THEN +* +* Compute left and/or right eigenvectors +* (Workspace: need 4*N) +* + CALL DTREVC( SIDE, 'B', SELECT, N, A, LDA, VL, LDVL, VR, LDVR, + $ N, NOUT, WORK( IWRK ), IERR ) + END IF +* + IF( WANTVL ) THEN +* +* Undo balancing of left eigenvectors +* (Workspace: need N) +* + CALL DGEBAK( 'B', 'L', N, ILO, IHI, WORK( IBAL ), N, VL, LDVL, + $ IERR ) +* +* Normalize left eigenvectors and make largest component real +* + DO 20 I = 1, N + IF( WI( I ).EQ.ZERO ) THEN + SCL = ONE / DNRM2( N, VL( 1, I ), 1 ) + CALL DSCAL( N, SCL, VL( 1, I ), 1 ) + ELSE IF( WI( I ).GT.ZERO ) THEN + SCL = ONE / DLAPY2( DNRM2( N, VL( 1, I ), 1 ), + $ DNRM2( N, VL( 1, I+1 ), 1 ) ) + CALL DSCAL( N, SCL, VL( 1, I ), 1 ) + CALL DSCAL( N, SCL, VL( 1, I+1 ), 1 ) + DO 10 K = 1, N + WORK( IWRK+K-1 ) = VL( K, I )**2 + VL( K, I+1 )**2 + 10 CONTINUE + K = IDAMAX( N, WORK( IWRK ), 1 ) + CALL DLARTG( VL( K, I ), VL( K, I+1 ), CS, SN, R ) + CALL DROT( N, VL( 1, I ), 1, VL( 1, I+1 ), 1, CS, SN ) + VL( K, I+1 ) = ZERO + END IF + 20 CONTINUE + END IF +* + IF( WANTVR ) THEN +* +* Undo balancing of right eigenvectors +* (Workspace: need N) +* + CALL DGEBAK( 'B', 'R', N, ILO, IHI, WORK( IBAL ), N, VR, LDVR, + $ IERR ) +* +* Normalize right eigenvectors and make largest component real +* + DO 40 I = 1, N + IF( WI( I ).EQ.ZERO ) THEN + SCL = ONE / DNRM2( N, VR( 1, I ), 1 ) + CALL DSCAL( N, SCL, VR( 1, I ), 1 ) + ELSE IF( WI( I ).GT.ZERO ) THEN + SCL = ONE / DLAPY2( DNRM2( N, VR( 1, I ), 1 ), + $ DNRM2( N, VR( 1, I+1 ), 1 ) ) + CALL DSCAL( N, SCL, VR( 1, I ), 1 ) + CALL DSCAL( N, SCL, VR( 1, I+1 ), 1 ) + DO 30 K = 1, N + WORK( IWRK+K-1 ) = VR( K, I )**2 + VR( K, I+1 )**2 + 30 CONTINUE + K = IDAMAX( N, WORK( IWRK ), 1 ) + CALL DLARTG( VR( K, I ), VR( K, I+1 ), CS, SN, R ) + CALL DROT( N, VR( 1, I ), 1, VR( 1, I+1 ), 1, CS, SN ) + VR( K, I+1 ) = ZERO + END IF + 40 CONTINUE + END IF +* +* Undo scaling if necessary +* + 50 CONTINUE + IF( SCALEA ) THEN + CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WR( INFO+1 ), + $ MAX( N-INFO, 1 ), IERR ) + CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-INFO, 1, WI( INFO+1 ), + $ MAX( N-INFO, 1 ), IERR ) + IF( INFO.GT.0 ) THEN + CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WR, N, + $ IERR ) + CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI, N, + $ IERR ) + END IF + END IF +* + WORK( 1 ) = MAXWRK + RETURN +* +* End of DGEEV +* + END diff --git a/dep/lapack/dgehd2.f b/dep/lapack/dgehd2.f new file mode 100644 index 00000000..bf2ffe51 --- /dev/null +++ b/dep/lapack/dgehd2.f @@ -0,0 +1,150 @@ + SUBROUTINE DGEHD2( N, ILO, IHI, A, LDA, TAU, WORK, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGEHD2 reduces a real general matrix A to upper Hessenberg form H by +* an orthogonal similarity transformation: Q' * A * Q = H . +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* It is assumed that A is already upper triangular in rows +* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally +* set by a previous call to DGEBAL; otherwise they should be +* set to 1 and N respectively. See Further Details. +* 1 <= ILO <= IHI <= max(1,N). +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the n by n general matrix to be reduced. +* On exit, the upper triangle and the first subdiagonal of A +* are overwritten with the upper Hessenberg matrix H, and the +* elements below the first subdiagonal, with the array TAU, +* represent the orthogonal matrix Q as a product of elementary +* reflectors. See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* TAU (output) DOUBLE PRECISION array, dimension (N-1) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit. +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of (ihi-ilo) elementary +* reflectors +* +* Q = H(ilo) H(ilo+1) . . . H(ihi-1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(1:i) = 0, v(i+1) = 1 and v(ihi+1:n) = 0; v(i+2:ihi) is stored on +* exit in A(i+2:ihi,i), and tau in TAU(i). +* +* The contents of A are illustrated by the following example, with +* n = 7, ilo = 2 and ihi = 6: +* +* on entry, on exit, +* +* ( a a a a a a a ) ( a a h h h h a ) +* ( a a a a a a ) ( a h h h h a ) +* ( a a a a a a ) ( h h h h h h ) +* ( a a a a a a ) ( v2 h h h h h ) +* ( a a a a a a ) ( v2 v3 h h h h ) +* ( a a a a a a ) ( v2 v3 v4 h h h ) +* ( a ) ( a ) +* +* where a denotes an element of the original matrix A, h denotes a +* modified element of the upper Hessenberg matrix H, and vi denotes an +* element of the vector defining H(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION AII +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DLARFG, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN + INFO = -2 + ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEHD2', -INFO ) + RETURN + END IF +* + DO 10 I = ILO, IHI - 1 +* +* Compute elementary reflector H(i) to annihilate A(i+2:ihi,i) +* + CALL DLARFG( IHI-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1, + $ TAU( I ) ) + AII = A( I+1, I ) + A( I+1, I ) = ONE +* +* Apply H(i) to A(1:ihi,i+1:ihi) from the right +* + CALL DLARF( 'Right', IHI, IHI-I, A( I+1, I ), 1, TAU( I ), + $ A( 1, I+1 ), LDA, WORK ) +* +* Apply H(i) to A(i+1:ihi,i+1:n) from the left +* + CALL DLARF( 'Left', IHI-I, N-I, A( I+1, I ), 1, TAU( I ), + $ A( I+1, I+1 ), LDA, WORK ) +* + A( I+1, I ) = AII + 10 CONTINUE +* + RETURN +* +* End of DGEHD2 +* + END diff --git a/dep/lapack/dgehrd.f b/dep/lapack/dgehrd.f new file mode 100644 index 00000000..339ee400 --- /dev/null +++ b/dep/lapack/dgehrd.f @@ -0,0 +1,273 @@ + SUBROUTINE DGEHRD( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, INFO, LDA, LWORK, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGEHRD reduces a real general matrix A to upper Hessenberg form H by +* an orthogonal similarity transformation: Q' * A * Q = H . +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* It is assumed that A is already upper triangular in rows +* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally +* set by a previous call to DGEBAL; otherwise they should be +* set to 1 and N respectively. See Further Details. +* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the N-by-N general matrix to be reduced. +* On exit, the upper triangle and the first subdiagonal of A +* are overwritten with the upper Hessenberg matrix H, and the +* elements below the first subdiagonal, with the array TAU, +* represent the orthogonal matrix Q as a product of elementary +* reflectors. See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* TAU (output) DOUBLE PRECISION array, dimension (N-1) +* The scalar factors of the elementary reflectors (see Further +* Details). Elements 1:ILO-1 and IHI:N-1 of TAU are set to +* zero. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The length of the array WORK. LWORK >= max(1,N). +* For optimum performance LWORK >= N*NB, where NB is the +* optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of (ihi-ilo) elementary +* reflectors +* +* Q = H(ilo) H(ilo+1) . . . H(ihi-1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(1:i) = 0, v(i+1) = 1 and v(ihi+1:n) = 0; v(i+2:ihi) is stored on +* exit in A(i+2:ihi,i), and tau in TAU(i). +* +* The contents of A are illustrated by the following example, with +* n = 7, ilo = 2 and ihi = 6: +* +* on entry, on exit, +* +* ( a a a a a a a ) ( a a h h h h a ) +* ( a a a a a a ) ( a h h h h a ) +* ( a a a a a a ) ( h h h h h h ) +* ( a a a a a a ) ( v2 h h h h h ) +* ( a a a a a a ) ( v2 v3 h h h h ) +* ( a a a a a a ) ( v2 v3 v4 h h h ) +* ( a ) ( a ) +* +* where a denotes an element of the original matrix A, h denotes a +* modified element of the upper Hessenberg matrix H, and vi denotes an +* element of the vector defining H(i). +* +* This file is a slight modification of LAPACK-3.0's DGEHRD +* subroutine incorporating improvements proposed by Quintana-Orti and +* Van de Geijn (2005). +* +* ===================================================================== +* +* .. Parameters .. + INTEGER NBMAX, LDT + PARAMETER ( NBMAX = 64, LDT = NBMAX+1 ) + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, + $ ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IB, IINFO, IWS, J, LDWORK, LWKOPT, NB, + $ NBMIN, NH, NX + DOUBLE PRECISION EI +* .. +* .. Local Arrays .. + DOUBLE PRECISION T( LDT, NBMAX ) +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DGEHD2, DGEMM, DLAHR2, DLARFB, DTRMM, + $ XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + NB = MIN( NBMAX, ILAENV( 1, 'DGEHRD', ' ', N, ILO, IHI, -1 ) ) + LWKOPT = N*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN + INFO = -2 + ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEHRD', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Set elements 1:ILO-1 and IHI:N-1 of TAU to zero +* + DO 10 I = 1, ILO - 1 + TAU( I ) = ZERO + 10 CONTINUE + DO 20 I = MAX( 1, IHI ), N - 1 + TAU( I ) = ZERO + 20 CONTINUE +* +* Quick return if possible +* + NH = IHI - ILO + 1 + IF( NH.LE.1 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* +* Determine the block size +* + NB = MIN( NBMAX, ILAENV( 1, 'DGEHRD', ' ', N, ILO, IHI, -1 ) ) + NBMIN = 2 + IWS = 1 + IF( NB.GT.1 .AND. NB.LT.NH ) THEN +* +* Determine when to cross over from blocked to unblocked code +* (last block is always handled by unblocked code) +* + NX = MAX( NB, ILAENV( 3, 'DGEHRD', ' ', N, ILO, IHI, -1 ) ) + IF( NX.LT.NH ) THEN +* +* Determine if workspace is large enough for blocked code +* + IWS = N*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: determine the +* minimum value of NB, and reduce NB or force use of +* unblocked code +* + NBMIN = MAX( 2, ILAENV( 2, 'DGEHRD', ' ', N, ILO, IHI, + $ -1 ) ) + IF( LWORK.GE.N*NBMIN ) THEN + NB = LWORK / N + ELSE + NB = 1 + END IF + END IF + END IF + END IF + LDWORK = N +* + IF( NB.LT.NBMIN .OR. NB.GE.NH ) THEN +* +* Use unblocked code below +* + I = ILO +* + ELSE +* +* Use blocked code +* + DO 40 I = ILO, IHI - 1 - NX, NB + IB = MIN( NB, IHI-I ) +* +* Reduce columns i:i+ib-1 to Hessenberg form, returning the +* matrices V and T of the block reflector H = I - V*T*V' +* which performs the reduction, and also the matrix Y = A*V*T +* + CALL DLAHR2( IHI, I, IB, A( 1, I ), LDA, TAU( I ), T, LDT, + $ WORK, LDWORK ) +* +* Apply the block reflector H to A(1:ihi,i+ib:ihi) from the +* right, computing A := A - Y * V'. V(i+ib,ib-1) must be set +* to 1 +* + EI = A( I+IB, I+IB-1 ) + A( I+IB, I+IB-1 ) = ONE + CALL DGEMM( 'No transpose', 'Transpose', + $ IHI, IHI-I-IB+1, + $ IB, -ONE, WORK, LDWORK, A( I+IB, I ), LDA, ONE, + $ A( 1, I+IB ), LDA ) + A( I+IB, I+IB-1 ) = EI +* +* Apply the block reflector H to A(1:i,i+1:i+ib-1) from the +* right +* + CALL DTRMM( 'Right', 'Lower', 'Transpose', + $ 'Unit', I, IB-1, + $ ONE, A( I+1, I ), LDA, WORK, LDWORK ) + DO 30 J = 0, IB-2 + CALL DAXPY( I, -ONE, WORK( LDWORK*J+1 ), 1, + $ A( 1, I+J+1 ), 1 ) + 30 CONTINUE +* +* Apply the block reflector H to A(i+1:ihi,i+ib:n) from the +* left +* + CALL DLARFB( 'Left', 'Transpose', 'Forward', + $ 'Columnwise', + $ IHI-I, N-I-IB+1, IB, A( I+1, I ), LDA, T, LDT, + $ A( I+1, I+IB ), LDA, WORK, LDWORK ) + 40 CONTINUE + END IF +* +* Use unblocked code to reduce the rest of the matrix +* + CALL DGEHD2( N, I, IHI, A, LDA, TAU, WORK, IINFO ) + WORK( 1 ) = IWS +* + RETURN +* +* End of DGEHRD +* + END diff --git a/dep/lapack/dgelq2.f b/dep/lapack/dgelq2.f new file mode 100644 index 00000000..77d45108 --- /dev/null +++ b/dep/lapack/dgelq2.f @@ -0,0 +1,122 @@ + SUBROUTINE DGELQ2( M, N, A, LDA, TAU, WORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGELQ2 computes an LQ factorization of a real m by n matrix A: +* A = L * Q. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the m by n matrix A. +* On exit, the elements on and below the diagonal of the array +* contain the m by min(m,n) lower trapezoidal matrix L (L is +* lower triangular if m <= n); the elements above the diagonal, +* with the array TAU, represent the orthogonal matrix Q as a +* product of elementary reflectors (see Further Details). +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (M) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of elementary reflectors +* +* Q = H(k) . . . H(2) H(1), where k = min(m,n). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v**T +* +* where tau is a real scalar, and v is a real vector with +* v(1:i-1) = 0 and v(i) = 1; v(i+1:n) is stored on exit in A(i,i+1:n), +* and tau in TAU(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, K + DOUBLE PRECISION AII +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DLARFG, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGELQ2', -INFO ) + RETURN + END IF +* + K = MIN( M, N ) +* + DO 10 I = 1, K +* +* Generate elementary reflector H(i) to annihilate A(i,i+1:n) +* + CALL DLARFG( N-I+1, A( I, I ), A( I, MIN( I+1, N ) ), LDA, + $ TAU( I ) ) + IF( I.LT.M ) THEN +* +* Apply H(i) to A(i+1:m,i:n) from the right +* + AII = A( I, I ) + A( I, I ) = ONE + CALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA, TAU( I ), + $ A( I+1, I ), LDA, WORK ) + A( I, I ) = AII + END IF + 10 CONTINUE + RETURN +* +* End of DGELQ2 +* + END diff --git a/dep/lapack/dgelqf.f b/dep/lapack/dgelqf.f new file mode 100644 index 00000000..5a3ceeff --- /dev/null +++ b/dep/lapack/dgelqf.f @@ -0,0 +1,196 @@ + SUBROUTINE DGELQF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGELQF computes an LQ factorization of a real M-by-N matrix A: +* A = L * Q. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the M-by-N matrix A. +* On exit, the elements on and below the diagonal of the array +* contain the m-by-min(m,n) lower trapezoidal matrix L (L is +* lower triangular if m <= n); the elements above the diagonal, +* with the array TAU, represent the orthogonal matrix Q as a +* product of elementary reflectors (see Further Details). +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,M). +* For optimum performance LWORK >= M*NB, where NB is the +* optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of elementary reflectors +* +* Q = H(k) . . . H(2) H(1), where k = min(m,n). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v**T +* +* where tau is a real scalar, and v is a real vector with +* v(1:i-1) = 0 and v(i) = 1; v(i+1:n) is stored on exit in A(i,i+1:n), +* and tau in TAU(i). +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IB, IINFO, IWS, K, LDWORK, LWKOPT, NB, + $ NBMIN, NX +* .. +* .. External Subroutines .. + EXTERNAL DGELQ2, DLARFB, DLARFT, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + NB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + LWKOPT = M*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGELQF', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + K = MIN( M, N ) + IF( K.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NBMIN = 2 + NX = 0 + IWS = M + IF( NB.GT.1 .AND. NB.LT.K ) THEN +* +* Determine when to cross over from blocked to unblocked code. +* + NX = MAX( 0, ILAENV( 3, 'DGELQF', ' ', M, N, -1, -1 ) ) + IF( NX.LT.K ) THEN +* +* Determine if workspace is large enough for blocked code. +* + LDWORK = M + IWS = LDWORK*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: reduce NB and +* determine the minimum value of NB. +* + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DGELQF', ' ', M, N, -1, + $ -1 ) ) + END IF + END IF + END IF +* + IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN +* +* Use blocked code initially +* + DO 10 I = 1, K - NX, NB + IB = MIN( K-I+1, NB ) +* +* Compute the LQ factorization of the current block +* A(i:i+ib-1,i:n) +* + CALL DGELQ2( IB, N-I+1, A( I, I ), LDA, TAU( I ), WORK, + $ IINFO ) + IF( I+IB.LE.M ) THEN +* +* Form the triangular factor of the block reflector +* H = H(i) H(i+1) . . . H(i+ib-1) +* + CALL DLARFT( 'Forward', 'Rowwise', N-I+1, IB, A( I, I ), + $ LDA, TAU( I ), WORK, LDWORK ) +* +* Apply H to A(i+ib:m,i:n) from the right +* + CALL DLARFB( 'Right', 'No transpose', 'Forward', + $ 'Rowwise', M-I-IB+1, N-I+1, IB, A( I, I ), + $ LDA, WORK, LDWORK, A( I+IB, I ), LDA, + $ WORK( IB+1 ), LDWORK ) + END IF + 10 CONTINUE + ELSE + I = 1 + END IF +* +* Use unblocked code to factor the last or only block. +* + IF( I.LE.K ) + $ CALL DGELQ2( M-I+1, N-I+1, A( I, I ), LDA, TAU( I ), WORK, + $ IINFO ) +* + WORK( 1 ) = IWS + RETURN +* +* End of DGELQF +* + END diff --git a/dep/lapack/dgels.f b/dep/lapack/dgels.f new file mode 100644 index 00000000..25176bfb --- /dev/null +++ b/dep/lapack/dgels.f @@ -0,0 +1,423 @@ + SUBROUTINE DGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK, + $ INFO ) +* +* -- LAPACK driver routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGELS solves overdetermined or underdetermined real linear systems +* involving an M-by-N matrix A, or its transpose, using a QR or LQ +* factorization of A. It is assumed that A has full rank. +* +* The following options are provided: +* +* 1. If TRANS = 'N' and m >= n: find the least squares solution of +* an overdetermined system, i.e., solve the least squares problem +* minimize || B - A*X ||. +* +* 2. If TRANS = 'N' and m < n: find the minimum norm solution of +* an underdetermined system A * X = B. +* +* 3. If TRANS = 'T' and m >= n: find the minimum norm solution of +* an undetermined system A**T * X = B. +* +* 4. If TRANS = 'T' and m < n: find the least squares solution of +* an overdetermined system, i.e., solve the least squares problem +* minimize || B - A**T * X ||. +* +* Several right hand side vectors b and solution vectors x can be +* handled in a single call; they are stored as the columns of the +* M-by-NRHS right hand side matrix B and the N-by-NRHS solution +* matrix X. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER*1 +* = 'N': the linear system involves A; +* = 'T': the linear system involves A**T. +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of +* columns of the matrices B and X. NRHS >=0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the M-by-N matrix A. +* On exit, +* if M >= N, A is overwritten by details of its QR +* factorization as returned by DGEQRF; +* if M < N, A is overwritten by details of its LQ +* factorization as returned by DGELQF. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the matrix B of right hand side vectors, stored +* columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS +* if TRANS = 'T'. +* On exit, if INFO = 0, B is overwritten by the solution +* vectors, stored columnwise: +* if TRANS = 'N' and m >= n, rows 1 to n of B contain the least +* squares solution vectors; the residual sum of squares for the +* solution in each column is given by the sum of squares of +* elements N+1 to M in that column; +* if TRANS = 'N' and m < n, rows 1 to N of B contain the +* minimum norm solution vectors; +* if TRANS = 'T' and m >= n, rows 1 to M of B contain the +* minimum norm solution vectors; +* if TRANS = 'T' and m < n, rows 1 to M of B contain the +* least squares solution vectors; the residual sum of squares +* for the solution in each column is given by the sum of +* squares of elements M+1 to N in that column. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= MAX(1,M,N). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* LWORK >= max( 1, MN + max( MN, NRHS ) ). +* For optimal performance, +* LWORK >= max( 1, MN + max( MN, NRHS )*NB ). +* where MN = min(M,N) and NB is the optimum block size. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the i-th diagonal element of the +* triangular factor of A is zero, so that A does not have +* full rank; the least squares solution could not be +* computed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY, TPSD + INTEGER BROW, I, IASCL, IBSCL, J, MN, NB, SCLLEN, WSIZE + DOUBLE PRECISION ANRM, BIGNUM, BNRM, SMLNUM +* .. +* .. Local Arrays .. + DOUBLE PRECISION RWORK( 1 ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + DOUBLE PRECISION DLAMCH, DLANGE + EXTERNAL LSAME, ILAENV, DLABAD, DLAMCH, DLANGE +* .. +* .. External Subroutines .. + EXTERNAL DGELQF, DGEQRF, DLASCL, DLASET, DORMLQ, DORMQR, + $ DTRTRS, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* + INFO = 0 + MN = MIN( M, N ) + LQUERY = ( LWORK.EQ.-1 ) + IF( .NOT.( LSAME( TRANS, 'N' ) .OR. LSAME( TRANS, 'T' ) ) ) THEN + INFO = -1 + ELSE IF( M.LT.0 ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -4 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -6 + ELSE IF( LDB.LT.MAX( 1, M, N ) ) THEN + INFO = -8 + ELSE IF( LWORK.LT.MAX( 1, MN+MAX( MN, NRHS ) ) .AND. .NOT.LQUERY ) + $ THEN + INFO = -10 + END IF +* +* Figure out optimal block size +* + IF( INFO.EQ.0 .OR. INFO.EQ.-10 ) THEN +* + TPSD = .TRUE. + IF( LSAME( TRANS, 'N' ) ) + $ TPSD = .FALSE. +* + IF( M.GE.N ) THEN + NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + IF( TPSD ) THEN + NB = MAX( NB, ILAENV( 1, 'DORMQR', 'LN', M, NRHS, N, + $ -1 ) ) + ELSE + NB = MAX( NB, ILAENV( 1, 'DORMQR', 'LT', M, NRHS, N, + $ -1 ) ) + END IF + ELSE + NB = ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + IF( TPSD ) THEN + NB = MAX( NB, ILAENV( 1, 'DORMLQ', 'LT', N, NRHS, M, + $ -1 ) ) + ELSE + NB = MAX( NB, ILAENV( 1, 'DORMLQ', 'LN', N, NRHS, M, + $ -1 ) ) + END IF + END IF +* + WSIZE = MAX( 1, MN+MAX( MN, NRHS )*NB ) + WORK( 1 ) = DBLE( WSIZE ) +* + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGELS ', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( MIN( M, N, NRHS ).EQ.0 ) THEN + CALL DLASET( 'Full', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB ) + RETURN + END IF +* +* Get machine parameters +* + SMLNUM = DLAMCH( 'S' ) / DLAMCH( 'P' ) + BIGNUM = ONE / SMLNUM + CALL DLABAD( SMLNUM, BIGNUM ) +* +* Scale A, B if max element outside range [SMLNUM,BIGNUM] +* + ANRM = DLANGE( 'M', M, N, A, LDA, RWORK ) + IASCL = 0 + IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN +* +* Scale matrix norm up to SMLNUM +* + CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, INFO ) + IASCL = 1 + ELSE IF( ANRM.GT.BIGNUM ) THEN +* +* Scale matrix norm down to BIGNUM +* + CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, INFO ) + IASCL = 2 + ELSE IF( ANRM.EQ.ZERO ) THEN +* +* Matrix all zero. Return zero solution. +* + CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB ) + GO TO 50 + END IF +* + BROW = M + IF( TPSD ) + $ BROW = N + BNRM = DLANGE( 'M', BROW, NRHS, B, LDB, RWORK ) + IBSCL = 0 + IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN +* +* Scale matrix norm up to SMLNUM +* + CALL DLASCL( 'G', 0, 0, BNRM, SMLNUM, BROW, NRHS, B, LDB, + $ INFO ) + IBSCL = 1 + ELSE IF( BNRM.GT.BIGNUM ) THEN +* +* Scale matrix norm down to BIGNUM +* + CALL DLASCL( 'G', 0, 0, BNRM, BIGNUM, BROW, NRHS, B, LDB, + $ INFO ) + IBSCL = 2 + END IF +* + IF( M.GE.N ) THEN +* +* compute QR factorization of A +* + CALL DGEQRF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN, + $ INFO ) +* +* workspace at least N, optimally N*NB +* + IF( .NOT.TPSD ) THEN +* +* Least-Squares Problem min || A * X - B || +* +* B(1:M,1:NRHS) := Q**T * B(1:M,1:NRHS) +* + CALL DORMQR( 'Left', 'Transpose', M, NRHS, N, A, LDA, + $ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN, + $ INFO ) +* +* workspace at least NRHS, optimally NRHS*NB +* +* B(1:N,1:NRHS) := inv(R) * B(1:N,1:NRHS) +* + CALL DTRTRS( 'Upper', 'No transpose', 'Non-unit', N, NRHS, + $ A, LDA, B, LDB, INFO ) +* + IF( INFO.GT.0 ) THEN + RETURN + END IF +* + SCLLEN = N +* + ELSE +* +* Overdetermined system of equations A**T * X = B +* +* B(1:N,1:NRHS) := inv(R**T) * B(1:N,1:NRHS) +* + CALL DTRTRS( 'Upper', 'Transpose', 'Non-unit', N, NRHS, + $ A, LDA, B, LDB, INFO ) +* + IF( INFO.GT.0 ) THEN + RETURN + END IF +* +* B(N+1:M,1:NRHS) = ZERO +* + DO 20 J = 1, NRHS + DO 10 I = N + 1, M + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE +* +* B(1:M,1:NRHS) := Q(1:N,:) * B(1:N,1:NRHS) +* + CALL DORMQR( 'Left', 'No transpose', M, NRHS, N, A, LDA, + $ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN, + $ INFO ) +* +* workspace at least NRHS, optimally NRHS*NB +* + SCLLEN = M +* + END IF +* + ELSE +* +* Compute LQ factorization of A +* + CALL DGELQF( M, N, A, LDA, WORK( 1 ), WORK( MN+1 ), LWORK-MN, + $ INFO ) +* +* workspace at least M, optimally M*NB. +* + IF( .NOT.TPSD ) THEN +* +* underdetermined system of equations A * X = B +* +* B(1:M,1:NRHS) := inv(L) * B(1:M,1:NRHS) +* + CALL DTRTRS( 'Lower', 'No transpose', 'Non-unit', M, NRHS, + $ A, LDA, B, LDB, INFO ) +* + IF( INFO.GT.0 ) THEN + RETURN + END IF +* +* B(M+1:N,1:NRHS) = 0 +* + DO 40 J = 1, NRHS + DO 30 I = M + 1, N + B( I, J ) = ZERO + 30 CONTINUE + 40 CONTINUE +* +* B(1:N,1:NRHS) := Q(1:N,:)**T * B(1:M,1:NRHS) +* + CALL DORMLQ( 'Left', 'Transpose', N, NRHS, M, A, LDA, + $ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN, + $ INFO ) +* +* workspace at least NRHS, optimally NRHS*NB +* + SCLLEN = N +* + ELSE +* +* overdetermined system min || A**T * X - B || +* +* B(1:N,1:NRHS) := Q * B(1:N,1:NRHS) +* + CALL DORMLQ( 'Left', 'No transpose', N, NRHS, M, A, LDA, + $ WORK( 1 ), B, LDB, WORK( MN+1 ), LWORK-MN, + $ INFO ) +* +* workspace at least NRHS, optimally NRHS*NB +* +* B(1:M,1:NRHS) := inv(L**T) * B(1:M,1:NRHS) +* + CALL DTRTRS( 'Lower', 'Transpose', 'Non-unit', M, NRHS, + $ A, LDA, B, LDB, INFO ) +* + IF( INFO.GT.0 ) THEN + RETURN + END IF +* + SCLLEN = M +* + END IF +* + END IF +* +* Undo scaling +* + IF( IASCL.EQ.1 ) THEN + CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, SCLLEN, NRHS, B, LDB, + $ INFO ) + ELSE IF( IASCL.EQ.2 ) THEN + CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, SCLLEN, NRHS, B, LDB, + $ INFO ) + END IF + IF( IBSCL.EQ.1 ) THEN + CALL DLASCL( 'G', 0, 0, SMLNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) + ELSE IF( IBSCL.EQ.2 ) THEN + CALL DLASCL( 'G', 0, 0, BIGNUM, BNRM, SCLLEN, NRHS, B, LDB, + $ INFO ) + END IF +* + 50 CONTINUE + WORK( 1 ) = DBLE( WSIZE ) +* + RETURN +* +* End of DGELS +* + END diff --git a/dep/lapack/dgeqr2.f b/dep/lapack/dgeqr2.f new file mode 100644 index 00000000..daefb4bc --- /dev/null +++ b/dep/lapack/dgeqr2.f @@ -0,0 +1,122 @@ + SUBROUTINE DGEQR2( M, N, A, LDA, TAU, WORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGEQR2 computes a QR factorization of a real m by n matrix A: +* A = Q * R. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the m by n matrix A. +* On exit, the elements on and above the diagonal of the array +* contain the min(m,n) by n upper trapezoidal matrix R (R is +* upper triangular if m >= n); the elements below the diagonal, +* with the array TAU, represent the orthogonal matrix Q as a +* product of elementary reflectors (see Further Details). +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of elementary reflectors +* +* Q = H(1) H(2) . . . H(k), where k = min(m,n). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v**T +* +* where tau is a real scalar, and v is a real vector with +* v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i), +* and tau in TAU(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, K + DOUBLE PRECISION AII +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DLARFG, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEQR2', -INFO ) + RETURN + END IF +* + K = MIN( M, N ) +* + DO 10 I = 1, K +* +* Generate elementary reflector H(i) to annihilate A(i+1:m,i) +* + CALL DLARFG( M-I+1, A( I, I ), A( MIN( I+1, M ), I ), 1, + $ TAU( I ) ) + IF( I.LT.N ) THEN +* +* Apply H(i) to A(i:m,i+1:n) from the left +* + AII = A( I, I ) + A( I, I ) = ONE + CALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAU( I ), + $ A( I, I+1 ), LDA, WORK ) + A( I, I ) = AII + END IF + 10 CONTINUE + RETURN +* +* End of DGEQR2 +* + END diff --git a/dep/lapack/dgeqrf.f b/dep/lapack/dgeqrf.f new file mode 100644 index 00000000..9608b741 --- /dev/null +++ b/dep/lapack/dgeqrf.f @@ -0,0 +1,197 @@ + SUBROUTINE DGEQRF( M, N, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGEQRF computes a QR factorization of a real M-by-N matrix A: +* A = Q * R. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the M-by-N matrix A. +* On exit, the elements on and above the diagonal of the array +* contain the min(M,N)-by-N upper trapezoidal matrix R (R is +* upper triangular if m >= n); the elements below the diagonal, +* with the array TAU, represent the orthogonal matrix Q as a +* product of min(m,n) elementary reflectors (see Further +* Details). +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,N). +* For optimum performance LWORK >= N*NB, where NB is +* the optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of elementary reflectors +* +* Q = H(1) H(2) . . . H(k), where k = min(m,n). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v**T +* +* where tau is a real scalar, and v is a real vector with +* v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i), +* and tau in TAU(i). +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IB, IINFO, IWS, K, LDWORK, LWKOPT, NB, + $ NBMIN, NX +* .. +* .. External Subroutines .. + EXTERNAL DGEQR2, DLARFB, DLARFT, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + NB = ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + LWKOPT = N*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGEQRF', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + K = MIN( M, N ) + IF( K.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NBMIN = 2 + NX = 0 + IWS = N + IF( NB.GT.1 .AND. NB.LT.K ) THEN +* +* Determine when to cross over from blocked to unblocked code. +* + NX = MAX( 0, ILAENV( 3, 'DGEQRF', ' ', M, N, -1, -1 ) ) + IF( NX.LT.K ) THEN +* +* Determine if workspace is large enough for blocked code. +* + LDWORK = N + IWS = LDWORK*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: reduce NB and +* determine the minimum value of NB. +* + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DGEQRF', ' ', M, N, -1, + $ -1 ) ) + END IF + END IF + END IF +* + IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN +* +* Use blocked code initially +* + DO 10 I = 1, K - NX, NB + IB = MIN( K-I+1, NB ) +* +* Compute the QR factorization of the current block +* A(i:m,i:i+ib-1) +* + CALL DGEQR2( M-I+1, IB, A( I, I ), LDA, TAU( I ), WORK, + $ IINFO ) + IF( I+IB.LE.N ) THEN +* +* Form the triangular factor of the block reflector +* H = H(i) H(i+1) . . . H(i+ib-1) +* + CALL DLARFT( 'Forward', 'Columnwise', M-I+1, IB, + $ A( I, I ), LDA, TAU( I ), WORK, LDWORK ) +* +* Apply H**T to A(i:m,i+ib:n) from the left +* + CALL DLARFB( 'Left', 'Transpose', 'Forward', + $ 'Columnwise', M-I+1, N-I-IB+1, IB, + $ A( I, I ), LDA, WORK, LDWORK, A( I, I+IB ), + $ LDA, WORK( IB+1 ), LDWORK ) + END IF + 10 CONTINUE + ELSE + I = 1 + END IF +* +* Use unblocked code to factor the last or only block. +* + IF( I.LE.K ) + $ CALL DGEQR2( M-I+1, N-I+1, A( I, I ), LDA, TAU( I ), WORK, + $ IINFO ) +* + WORK( 1 ) = IWS + RETURN +* +* End of DGEQRF +* + END diff --git a/dep/lapack/dgesv.f b/dep/lapack/dgesv.f new file mode 100644 index 00000000..0fe73a1f --- /dev/null +++ b/dep/lapack/dgesv.f @@ -0,0 +1,108 @@ + SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) +* +* -- LAPACK driver routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DGESV computes the solution to a real system of linear equations +* A * X = B, +* where A is an N-by-N matrix and X and B are N-by-NRHS matrices. +* +* The LU decomposition with partial pivoting and row interchanges is +* used to factor A as +* A = P * L * U, +* where P is a permutation matrix, L is unit lower triangular, and U is +* upper triangular. The factored form of A is then used to solve the +* system of equations A * X = B. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of linear equations, i.e., the order of the +* matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the N-by-N coefficient matrix A. +* On exit, the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices that define the permutation matrix P; +* row i of the matrix was interchanged with row IPIV(i). +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the N-by-NRHS matrix of right hand side matrix B. +* On exit, if INFO = 0, the N-by-NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, so the solution could not be computed. +* +* ===================================================================== +* +* .. External Subroutines .. + EXTERNAL DGETRF, DGETRS, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGESV ', -INFO ) + RETURN + END IF +* +* Compute the LU factorization of A. +* + CALL DGETRF( N, N, A, LDA, IPIV, INFO ) + IF( INFO.EQ.0 ) THEN +* +* Solve the system A*X = B, overwriting B with X. +* + CALL DGETRS( 'No transpose', N, NRHS, A, LDA, IPIV, B, LDB, + $ INFO ) + END IF + RETURN +* +* End of DGESV +* + END diff --git a/dep/lapack/dgesvd.f b/dep/lapack/dgesvd.f new file mode 100644 index 00000000..9a1c8489 --- /dev/null +++ b/dep/lapack/dgesvd.f @@ -0,0 +1,3405 @@ + SUBROUTINE DGESVD( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, + $ WORK, LWORK, INFO ) +* +* -- LAPACK driver routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER JOBU, JOBVT + INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), + $ VT( LDVT, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGESVD computes the singular value decomposition (SVD) of a real +* M-by-N matrix A, optionally computing the left and/or right singular +* vectors. The SVD is written +* +* A = U * SIGMA * transpose(V) +* +* where SIGMA is an M-by-N matrix which is zero except for its +* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and +* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA +* are the singular values of A; they are real and non-negative, and +* are returned in descending order. The first min(m,n) columns of +* U and V are the left and right singular vectors of A. +* +* Note that the routine returns V**T, not V. +* +* Arguments +* ========= +* +* JOBU (input) CHARACTER*1 +* Specifies options for computing all or part of the matrix U: +* = 'A': all M columns of U are returned in array U: +* = 'S': the first min(m,n) columns of U (the left singular +* vectors) are returned in the array U; +* = 'O': the first min(m,n) columns of U (the left singular +* vectors) are overwritten on the array A; +* = 'N': no columns of U (no left singular vectors) are +* computed. +* +* JOBVT (input) CHARACTER*1 +* Specifies options for computing all or part of the matrix +* V**T: +* = 'A': all N rows of V**T are returned in the array VT; +* = 'S': the first min(m,n) rows of V**T (the right singular +* vectors) are returned in the array VT; +* = 'O': the first min(m,n) rows of V**T (the right singular +* vectors) are overwritten on the array A; +* = 'N': no rows of V**T (no right singular vectors) are +* computed. +* +* JOBVT and JOBU cannot both be 'O'. +* +* M (input) INTEGER +* The number of rows of the input matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the input matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the M-by-N matrix A. +* On exit, +* if JOBU = 'O', A is overwritten with the first min(m,n) +* columns of U (the left singular vectors, +* stored columnwise); +* if JOBVT = 'O', A is overwritten with the first min(m,n) +* rows of V**T (the right singular vectors, +* stored rowwise); +* if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A +* are destroyed. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* S (output) DOUBLE PRECISION array, dimension (min(M,N)) +* The singular values of A, sorted so that S(i) >= S(i+1). +* +* U (output) DOUBLE PRECISION array, dimension (LDU,UCOL) +* (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'. +* If JOBU = 'A', U contains the M-by-M orthogonal matrix U; +* if JOBU = 'S', U contains the first min(m,n) columns of U +* (the left singular vectors, stored columnwise); +* if JOBU = 'N' or 'O', U is not referenced. +* +* LDU (input) INTEGER +* The leading dimension of the array U. LDU >= 1; if +* JOBU = 'S' or 'A', LDU >= M. +* +* VT (output) DOUBLE PRECISION array, dimension (LDVT,N) +* If JOBVT = 'A', VT contains the N-by-N orthogonal matrix +* V**T; +* if JOBVT = 'S', VT contains the first min(m,n) rows of +* V**T (the right singular vectors, stored rowwise); +* if JOBVT = 'N' or 'O', VT is not referenced. +* +* LDVT (input) INTEGER +* The leading dimension of the array VT. LDVT >= 1; if +* JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK; +* if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged +* superdiagonal elements of an upper bidiagonal matrix B +* whose diagonal is in S (not necessarily sorted). B +* satisfies A = U * B * VT, so it has the same singular values +* as A, and singular vectors related by U and VT. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* LWORK >= MAX(1,5*MIN(M,N)) for the paths (see comments inside code): +* - PATH 1 (M much larger than N, JOBU='N') +* - PATH 1t (N much larger than M, JOBVT='N') +* LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)) for the other paths +* For good performance, LWORK should generally be larger. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit. +* < 0: if INFO = -i, the i-th argument had an illegal value. +* > 0: if DBDSQR did not converge, INFO specifies how many +* superdiagonals of an intermediate bidiagonal form B +* did not converge to zero. See the description of WORK +* above for details. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY, WNTUA, WNTUAS, WNTUN, WNTUO, WNTUS, + $ WNTVA, WNTVAS, WNTVN, WNTVO, WNTVS + INTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IR, ISCL, + $ ITAU, ITAUP, ITAUQ, IU, IWORK, LDWRKR, LDWRKU, + $ MAXWRK, MINMN, MINWRK, MNTHR, NCU, NCVT, NRU, + $ NRVT, WRKBL + DOUBLE PRECISION ANRM, BIGNUM, EPS, SMLNUM +* .. +* .. Local Arrays .. + DOUBLE PRECISION DUM( 1 ) +* .. +* .. External Subroutines .. + EXTERNAL DBDSQR, DGEBRD, DGELQF, DGEMM, DGEQRF, DLACPY, + $ DLASCL, DLASET, DORGBR, DORGLQ, DORGQR, DORMBR, + $ XERBLA +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + DOUBLE PRECISION DLAMCH, DLANGE + EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + MINMN = MIN( M, N ) + WNTUA = LSAME( JOBU, 'A' ) + WNTUS = LSAME( JOBU, 'S' ) + WNTUAS = WNTUA .OR. WNTUS + WNTUO = LSAME( JOBU, 'O' ) + WNTUN = LSAME( JOBU, 'N' ) + WNTVA = LSAME( JOBVT, 'A' ) + WNTVS = LSAME( JOBVT, 'S' ) + WNTVAS = WNTVA .OR. WNTVS + WNTVO = LSAME( JOBVT, 'O' ) + WNTVN = LSAME( JOBVT, 'N' ) + LQUERY = ( LWORK.EQ.-1 ) +* + IF( .NOT.( WNTUA .OR. WNTUS .OR. WNTUO .OR. WNTUN ) ) THEN + INFO = -1 + ELSE IF( .NOT.( WNTVA .OR. WNTVS .OR. WNTVO .OR. WNTVN ) .OR. + $ ( WNTVO .AND. WNTUO ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -6 + ELSE IF( LDU.LT.1 .OR. ( WNTUAS .AND. LDU.LT.M ) ) THEN + INFO = -9 + ELSE IF( LDVT.LT.1 .OR. ( WNTVA .AND. LDVT.LT.N ) .OR. + $ ( WNTVS .AND. LDVT.LT.MINMN ) ) THEN + INFO = -11 + END IF +* +* Compute workspace +* (Note: Comments in the code beginning "Workspace:" describe the +* minimal amount of workspace needed at that point in the code, +* as well as the preferred amount for good performance. +* NB refers to the optimal block size for the immediately +* following subroutine, as returned by ILAENV.) +* + IF( INFO.EQ.0 ) THEN + MINWRK = 1 + MAXWRK = 1 + IF( M.GE.N .AND. MINMN.GT.0 ) THEN +* +* Compute space needed for DBDSQR +* + MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 ) + BDSPAC = 5*N + IF( M.GE.MNTHR ) THEN + IF( WNTUN ) THEN +* +* Path 1 (M much larger than N, JOBU='N') +* + MAXWRK = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, + $ -1 ) + MAXWRK = MAX( MAXWRK, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + IF( WNTVO .OR. WNTVAS ) + $ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + MAXWRK = MAX( MAXWRK, BDSPAC ) + MINWRK = MAX( 4*N, BDSPAC ) + ELSE IF( WNTUO .AND. WNTVN ) THEN +* +* Path 2 (M much larger than N, JOBU='O', JOBVT='N') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, + $ N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N ) + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUO .AND. WNTVAS ) THEN +* +* Path 3 (M much larger than N, JOBU='O', JOBVT='S' or +* 'A') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, + $ N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = MAX( N*N+WRKBL, N*N+M*N+N ) + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUS .AND. WNTVN ) THEN +* +* Path 4 (M much larger than N, JOBU='S', JOBVT='N') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, + $ N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = N*N + WRKBL + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUS .AND. WNTVO ) THEN +* +* Path 5 (M much larger than N, JOBU='S', JOBVT='O') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, + $ N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = 2*N*N + WRKBL + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUS .AND. WNTVAS ) THEN +* +* Path 6 (M much larger than N, JOBU='S', JOBVT='S' or +* 'A') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+N*ILAENV( 1, 'DORGQR', ' ', M, + $ N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = N*N + WRKBL + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUA .AND. WNTVN ) THEN +* +* Path 7 (M much larger than N, JOBU='A', JOBVT='N') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M, + $ M, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = N*N + WRKBL + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUA .AND. WNTVO ) THEN +* +* Path 8 (M much larger than N, JOBU='A', JOBVT='O') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M, + $ M, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = 2*N*N + WRKBL + MINWRK = MAX( 3*N+M, BDSPAC ) + ELSE IF( WNTUA .AND. WNTVAS ) THEN +* +* Path 9 (M much larger than N, JOBU='A', JOBVT='S' or +* 'A') +* + WRKBL = N + N*ILAENV( 1, 'DGEQRF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, N+M*ILAENV( 1, 'DORGQR', ' ', M, + $ M, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+2*N* + $ ILAENV( 1, 'DGEBRD', ' ', N, N, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = N*N + WRKBL + MINWRK = MAX( 3*N+M, BDSPAC ) + END IF + ELSE +* +* Path 10 (M at least N, but not much larger) +* + MAXWRK = 3*N + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, + $ -1, -1 ) + IF( WNTUS .OR. WNTUO ) + $ MAXWRK = MAX( MAXWRK, 3*N+N* + $ ILAENV( 1, 'DORGBR', 'Q', M, N, N, -1 ) ) + IF( WNTUA ) + $ MAXWRK = MAX( MAXWRK, 3*N+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, N, -1 ) ) + IF( .NOT.WNTVN ) + $ MAXWRK = MAX( MAXWRK, 3*N+( N-1 )* + $ ILAENV( 1, 'DORGBR', 'P', N, N, N, -1 ) ) + MAXWRK = MAX( MAXWRK, BDSPAC ) + MINWRK = MAX( 3*N+M, BDSPAC ) + END IF + ELSE IF( MINMN.GT.0 ) THEN +* +* Compute space needed for DBDSQR +* + MNTHR = ILAENV( 6, 'DGESVD', JOBU // JOBVT, M, N, 0, 0 ) + BDSPAC = 5*M + IF( N.GE.MNTHR ) THEN + IF( WNTVN ) THEN +* +* Path 1t(N much larger than M, JOBVT='N') +* + MAXWRK = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, + $ -1 ) + MAXWRK = MAX( MAXWRK, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + IF( WNTUO .OR. WNTUAS ) + $ MAXWRK = MAX( MAXWRK, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + MAXWRK = MAX( MAXWRK, BDSPAC ) + MINWRK = MAX( 4*M, BDSPAC ) + ELSE IF( WNTVO .AND. WNTUN ) THEN +* +* Path 2t(N much larger than M, JOBU='N', JOBVT='O') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M ) + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVO .AND. WNTUAS ) THEN +* +* Path 3t(N much larger than M, JOBU='S' or 'A', +* JOBVT='O') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = MAX( M*M+WRKBL, M*M+M*N+M ) + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVS .AND. WNTUN ) THEN +* +* Path 4t(N much larger than M, JOBU='N', JOBVT='S') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = M*M + WRKBL + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVS .AND. WNTUO ) THEN +* +* Path 5t(N much larger than M, JOBU='O', JOBVT='S') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = 2*M*M + WRKBL + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVS .AND. WNTUAS ) THEN +* +* Path 6t(N much larger than M, JOBU='S' or 'A', +* JOBVT='S') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+M*ILAENV( 1, 'DORGLQ', ' ', M, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = M*M + WRKBL + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVA .AND. WNTUN ) THEN +* +* Path 7t(N much larger than M, JOBU='N', JOBVT='A') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = M*M + WRKBL + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVA .AND. WNTUO ) THEN +* +* Path 8t(N much larger than M, JOBU='O', JOBVT='A') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = 2*M*M + WRKBL + MINWRK = MAX( 3*M+N, BDSPAC ) + ELSE IF( WNTVA .AND. WNTUAS ) THEN +* +* Path 9t(N much larger than M, JOBU='S' or 'A', +* JOBVT='A') +* + WRKBL = M + M*ILAENV( 1, 'DGELQF', ' ', M, N, -1, -1 ) + WRKBL = MAX( WRKBL, M+N*ILAENV( 1, 'DORGLQ', ' ', N, + $ N, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+2*M* + $ ILAENV( 1, 'DGEBRD', ' ', M, M, -1, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'P', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + WRKBL = MAX( WRKBL, BDSPAC ) + MAXWRK = M*M + WRKBL + MINWRK = MAX( 3*M+N, BDSPAC ) + END IF + ELSE +* +* Path 10t(N greater than M, but not much larger) +* + MAXWRK = 3*M + ( M+N )*ILAENV( 1, 'DGEBRD', ' ', M, N, + $ -1, -1 ) + IF( WNTVS .OR. WNTVO ) + $ MAXWRK = MAX( MAXWRK, 3*M+M* + $ ILAENV( 1, 'DORGBR', 'P', M, N, M, -1 ) ) + IF( WNTVA ) + $ MAXWRK = MAX( MAXWRK, 3*M+N* + $ ILAENV( 1, 'DORGBR', 'P', N, N, M, -1 ) ) + IF( .NOT.WNTUN ) + $ MAXWRK = MAX( MAXWRK, 3*M+( M-1 )* + $ ILAENV( 1, 'DORGBR', 'Q', M, M, M, -1 ) ) + MAXWRK = MAX( MAXWRK, BDSPAC ) + MINWRK = MAX( 3*M+N, BDSPAC ) + END IF + END IF + MAXWRK = MAX( MAXWRK, MINWRK ) + WORK( 1 ) = MAXWRK +* + IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN + INFO = -13 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGESVD', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) THEN + RETURN + END IF +* +* Get machine constants +* + EPS = DLAMCH( 'P' ) + SMLNUM = SQRT( DLAMCH( 'S' ) ) / EPS + BIGNUM = ONE / SMLNUM +* +* Scale A if max element outside range [SMLNUM,BIGNUM] +* + ANRM = DLANGE( 'M', M, N, A, LDA, DUM ) + ISCL = 0 + IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN + ISCL = 1 + CALL DLASCL( 'G', 0, 0, ANRM, SMLNUM, M, N, A, LDA, IERR ) + ELSE IF( ANRM.GT.BIGNUM ) THEN + ISCL = 1 + CALL DLASCL( 'G', 0, 0, ANRM, BIGNUM, M, N, A, LDA, IERR ) + END IF +* + IF( M.GE.N ) THEN +* +* A has at least as many rows as columns. If A has sufficiently +* more rows than columns, first reduce using the QR +* decomposition (if sufficient workspace available) +* + IF( M.GE.MNTHR ) THEN +* + IF( WNTUN ) THEN +* +* Path 1 (M much larger than N, JOBU='N') +* No left singular vectors to be computed +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Zero out below R +* + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), LDA ) + IE = 1 + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in A +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1, + $ IERR ) + NCVT = 0 + IF( WNTVO .OR. WNTVAS ) THEN +* +* If right singular vectors desired, generate P'. +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + NCVT = N + END IF + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of A in A if desired +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, NCVT, 0, 0, S, WORK( IE ), A, LDA, + $ DUM, 1, DUM, 1, WORK( IWORK ), INFO ) +* +* If right singular vectors desired in VT, copy them there +* + IF( WNTVAS ) + $ CALL DLACPY( 'F', N, N, A, LDA, VT, LDVT ) +* + ELSE IF( WNTUO .AND. WNTVN ) THEN +* +* Path 2 (M much larger than N, JOBU='O', JOBVT='N') +* N left singular vectors to be overwritten on A and +* no right singular vectors to be computed +* + IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN +* +* WORK(IU) is LDA by N, WORK(IR) is LDA by N +* + LDWRKU = LDA + LDWRKR = LDA + ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN +* +* WORK(IU) is LDA by N, WORK(IR) is N by N +* + LDWRKU = LDA + LDWRKR = N + ELSE +* +* WORK(IU) is LDWRKU by N, WORK(IR) is N by N +* + LDWRKU = ( LWORK-N*N-N ) / N + LDWRKR = N + END IF + ITAU = IR + LDWRKR*N + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to WORK(IR) and zero out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), LDWRKR ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, WORK( IR+1 ), + $ LDWRKR ) +* +* Generate Q in A +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate left vectors bidiagonalizing R +* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IR) +* (Workspace: need N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, 1, + $ WORK( IR ), LDWRKR, DUM, 1, + $ WORK( IWORK ), INFO ) + IU = IE + N +* +* Multiply Q in A by left singular vectors of R in +* WORK(IR), storing result in WORK(IU) and copying to A +* (Workspace: need N*N+2*N, prefer N*N+M*N+N) +* + DO 10 I = 1, M, LDWRKU + CHUNK = MIN( M-I+1, LDWRKU ) + CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ), + $ LDA, WORK( IR ), LDWRKR, ZERO, + $ WORK( IU ), LDWRKU ) + CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU, + $ A( I, 1 ), LDA ) + 10 CONTINUE +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + IE = 1 + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize A +* (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB) +* + CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate left vectors bidiagonalizing A +* (Workspace: need 4*N, prefer 3*N+N*NB) +* + CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, 1, + $ A, LDA, DUM, 1, WORK( IWORK ), INFO ) +* + END IF +* + ELSE IF( WNTUO .AND. WNTVAS ) THEN +* +* Path 3 (M much larger than N, JOBU='O', JOBVT='S' or 'A') +* N left singular vectors to be overwritten on A and +* N right singular vectors to be computed in VT +* + IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+LDA*N ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is LDA by N +* + LDWRKU = LDA + LDWRKR = LDA + ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+N )+N*N ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is N by N +* + LDWRKU = LDA + LDWRKR = N + ELSE +* +* WORK(IU) is LDWRKU by N and WORK(IR) is N by N +* + LDWRKU = ( LWORK-N*N-N ) / N + LDWRKR = N + END IF + ITAU = IR + LDWRKR*N + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to VT, zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT ) + IF( N.GT.1 ) + $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ VT( 2, 1 ), LDVT ) +* +* Generate Q in A +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in VT, copying result to WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', N, N, VT, LDVT, WORK( IR ), LDWRKR ) +* +* Generate left vectors bidiagonalizing R in WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right vectors bidiagonalizing R in VT +* (Workspace: need N*N+4*N-1, prefer N*N+3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IR) and computing right +* singular vectors of R in VT +* (Workspace: need N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, LDVT, + $ WORK( IR ), LDWRKR, DUM, 1, + $ WORK( IWORK ), INFO ) + IU = IE + N +* +* Multiply Q in A by left singular vectors of R in +* WORK(IR), storing result in WORK(IU) and copying to A +* (Workspace: need N*N+2*N, prefer N*N+M*N+N) +* + DO 20 I = 1, M, LDWRKU + CHUNK = MIN( M-I+1, LDWRKU ) + CALL DGEMM( 'N', 'N', CHUNK, N, N, ONE, A( I, 1 ), + $ LDA, WORK( IR ), LDWRKR, ZERO, + $ WORK( IU ), LDWRKU ) + CALL DLACPY( 'F', CHUNK, N, WORK( IU ), LDWRKU, + $ A( I, 1 ), LDA ) + 20 CONTINUE +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to VT, zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT ) + IF( N.GT.1 ) + $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ VT( 2, 1 ), LDVT ) +* +* Generate Q in A +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in VT +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in A by left vectors bidiagonalizing R +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT, + $ WORK( ITAUQ ), A, LDA, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right vectors bidiagonalizing R in VT +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in A and computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, LDVT, + $ A, LDA, DUM, 1, WORK( IWORK ), INFO ) +* + END IF +* + ELSE IF( WNTUS ) THEN +* + IF( WNTVN ) THEN +* +* Path 4 (M much larger than N, JOBU='S', JOBVT='N') +* N left singular vectors to be computed in U and +* no right singular vectors to be computed +* + IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.WRKBL+LDA*N ) THEN +* +* WORK(IR) is LDA by N +* + LDWRKR = LDA + ELSE +* +* WORK(IR) is N by N +* + LDWRKR = N + END IF + ITAU = IR + LDWRKR*N + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to WORK(IR), zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), + $ LDWRKR ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ WORK( IR+1 ), LDWRKR ) +* +* Generate Q in A +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left vectors bidiagonalizing R in WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IR) +* (Workspace: need N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, + $ 1, WORK( IR ), LDWRKR, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply Q in A by left singular vectors of R in +* WORK(IR), storing result in U +* (Workspace: need N*N) +* + CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, + $ WORK( IR ), LDWRKR, ZERO, U, LDU ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Zero out below R in A +* + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), + $ LDA ) +* +* Bidiagonalize R in A +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in U by left vectors bidiagonalizing R +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA, + $ WORK( ITAUQ ), U, LDU, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, + $ 1, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTVO ) THEN +* +* Path 5 (M much larger than N, JOBU='S', JOBVT='O') +* N left singular vectors to be computed in U and +* N right singular vectors to be overwritten on A +* + IF( LWORK.GE.2*N*N+MAX( 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+2*LDA*N ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is LDA by N +* + LDWRKU = LDA + IR = IU + LDWRKU*N + LDWRKR = LDA + ELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is N by N +* + LDWRKU = LDA + IR = IU + LDWRKU*N + LDWRKR = N + ELSE +* +* WORK(IU) is N by N and WORK(IR) is N by N +* + LDWRKU = N + IR = IU + LDWRKU*N + LDWRKR = N + END IF + ITAU = IR + LDWRKR*N + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to WORK(IU), zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ WORK( IU+1 ), LDWRKU ) +* +* Generate Q in A +* (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB) +* + CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IU), copying result to +* WORK(IR) +* (Workspace: need 2*N*N+4*N, +* prefer 2*N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, + $ WORK( IR ), LDWRKR ) +* +* Generate left bidiagonalizing vectors in WORK(IU) +* (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in WORK(IR) +* (Workspace: need 2*N*N+4*N-1, +* prefer 2*N*N+3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IU) and computing +* right singular vectors of R in WORK(IR) +* (Workspace: need 2*N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), + $ WORK( IR ), LDWRKR, WORK( IU ), + $ LDWRKU, DUM, 1, WORK( IWORK ), INFO ) +* +* Multiply Q in A by left singular vectors of R in +* WORK(IU), storing result in U +* (Workspace: need N*N) +* + CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, + $ WORK( IU ), LDWRKU, ZERO, U, LDU ) +* +* Copy right singular vectors of R to A +* (Workspace: need N*N) +* + CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A, + $ LDA ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Zero out below R in A +* + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), + $ LDA ) +* +* Bidiagonalize R in A +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in U by left vectors bidiagonalizing R +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA, + $ WORK( ITAUQ ), U, LDU, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right vectors bidiagonalizing R in A +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A, + $ LDA, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTVAS ) THEN +* +* Path 6 (M much larger than N, JOBU='S', JOBVT='S' +* or 'A') +* N left singular vectors to be computed in U and +* N right singular vectors to be computed in VT +* + IF( LWORK.GE.N*N+MAX( 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+LDA*N ) THEN +* +* WORK(IU) is LDA by N +* + LDWRKU = LDA + ELSE +* +* WORK(IU) is N by N +* + LDWRKU = N + END IF + ITAU = IU + LDWRKU*N + IWORK = ITAU + N +* +* Compute A=Q*R +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to WORK(IU), zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ WORK( IU+1 ), LDWRKU ) +* +* Generate Q in A +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DORGQR( M, N, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IU), copying result to VT +* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT, + $ LDVT ) +* +* Generate left bidiagonalizing vectors in WORK(IU) +* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in VT +* (Workspace: need N*N+4*N-1, +* prefer N*N+3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IU) and computing +* right singular vectors of R in VT +* (Workspace: need N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, + $ LDVT, WORK( IU ), LDWRKU, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply Q in A by left singular vectors of R in +* WORK(IU), storing result in U +* (Workspace: need N*N) +* + CALL DGEMM( 'N', 'N', M, N, N, ONE, A, LDA, + $ WORK( IU ), LDWRKU, ZERO, U, LDU ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DORGQR( M, N, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to VT, zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT ) + IF( N.GT.1 ) + $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ VT( 2, 1 ), LDVT ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in VT +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in U by left bidiagonalizing vectors +* in VT +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT, + $ WORK( ITAUQ ), U, LDU, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in VT +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, + $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + END IF +* + ELSE IF( WNTUA ) THEN +* + IF( WNTVN ) THEN +* +* Path 7 (M much larger than N, JOBU='A', JOBVT='N') +* M left singular vectors to be computed in U and +* no right singular vectors to be computed +* + IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.WRKBL+LDA*N ) THEN +* +* WORK(IR) is LDA by N +* + LDWRKR = LDA + ELSE +* +* WORK(IR) is N by N +* + LDWRKR = N + END IF + ITAU = IR + LDWRKR*N + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Copy R to WORK(IR), zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IR ), + $ LDWRKR ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ WORK( IR+1 ), LDWRKR ) +* +* Generate Q in U +* (Workspace: need N*N+N+M, prefer N*N+N+M*NB) +* + CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IR ), LDWRKR, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in WORK(IR) +* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IR ), LDWRKR, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IR) +* (Workspace: need N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, 0, N, 0, S, WORK( IE ), DUM, + $ 1, WORK( IR ), LDWRKR, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply Q in U by left singular vectors of R in +* WORK(IR), storing result in A +* (Workspace: need N*N) +* + CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, + $ WORK( IR ), LDWRKR, ZERO, A, LDA ) +* +* Copy left singular vectors of A from A to U +* + CALL DLACPY( 'F', M, N, A, LDA, U, LDU ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need N+M, prefer N+M*NB) +* + CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Zero out below R in A +* + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), + $ LDA ) +* +* Bidiagonalize R in A +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in U by left bidiagonalizing vectors +* in A +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA, + $ WORK( ITAUQ ), U, LDU, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, 0, M, 0, S, WORK( IE ), DUM, + $ 1, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTVO ) THEN +* +* Path 8 (M much larger than N, JOBU='A', JOBVT='O') +* M left singular vectors to be computed in U and +* N right singular vectors to be overwritten on A +* + IF( LWORK.GE.2*N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+2*LDA*N ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is LDA by N +* + LDWRKU = LDA + IR = IU + LDWRKU*N + LDWRKR = LDA + ELSE IF( LWORK.GE.WRKBL+( LDA+N )*N ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is N by N +* + LDWRKU = LDA + IR = IU + LDWRKU*N + LDWRKR = N + ELSE +* +* WORK(IU) is N by N and WORK(IR) is N by N +* + LDWRKU = N + IR = IU + LDWRKU*N + LDWRKR = N + END IF + ITAU = IR + LDWRKR*N + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N*N+2*N, prefer 2*N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need 2*N*N+N+M, prefer 2*N*N+N+M*NB) +* + CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to WORK(IU), zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ WORK( IU+1 ), LDWRKU ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IU), copying result to +* WORK(IR) +* (Workspace: need 2*N*N+4*N, +* prefer 2*N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, + $ WORK( IR ), LDWRKR ) +* +* Generate left bidiagonalizing vectors in WORK(IU) +* (Workspace: need 2*N*N+4*N, prefer 2*N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in WORK(IR) +* (Workspace: need 2*N*N+4*N-1, +* prefer 2*N*N+3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, WORK( IR ), LDWRKR, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IU) and computing +* right singular vectors of R in WORK(IR) +* (Workspace: need 2*N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), + $ WORK( IR ), LDWRKR, WORK( IU ), + $ LDWRKU, DUM, 1, WORK( IWORK ), INFO ) +* +* Multiply Q in U by left singular vectors of R in +* WORK(IU), storing result in A +* (Workspace: need N*N) +* + CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, + $ WORK( IU ), LDWRKU, ZERO, A, LDA ) +* +* Copy left singular vectors of A from A to U +* + CALL DLACPY( 'F', M, N, A, LDA, U, LDU ) +* +* Copy right singular vectors of R from WORK(IR) to A +* + CALL DLACPY( 'F', N, N, WORK( IR ), LDWRKR, A, + $ LDA ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need N+M, prefer N+M*NB) +* + CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Zero out below R in A +* + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, A( 2, 1 ), + $ LDA ) +* +* Bidiagonalize R in A +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in U by left bidiagonalizing vectors +* in A +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, A, LDA, + $ WORK( ITAUQ ), U, LDU, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in A +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), A, + $ LDA, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTVAS ) THEN +* +* Path 9 (M much larger than N, JOBU='A', JOBVT='S' +* or 'A') +* M left singular vectors to be computed in U and +* N right singular vectors to be computed in VT +* + IF( LWORK.GE.N*N+MAX( N+M, 4*N, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+LDA*N ) THEN +* +* WORK(IU) is LDA by N +* + LDWRKU = LDA + ELSE +* +* WORK(IU) is N by N +* + LDWRKU = N + END IF + ITAU = IU + LDWRKU*N + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need N*N+2*N, prefer N*N+N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need N*N+N+M, prefer N*N+N+M*NB) +* + CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R to WORK(IU), zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ WORK( IU+1 ), LDWRKU ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in WORK(IU), copying result to VT +* (Workspace: need N*N+4*N, prefer N*N+3*N+2*N*NB) +* + CALL DGEBRD( N, N, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', N, N, WORK( IU ), LDWRKU, VT, + $ LDVT ) +* +* Generate left bidiagonalizing vectors in WORK(IU) +* (Workspace: need N*N+4*N, prefer N*N+3*N+N*NB) +* + CALL DORGBR( 'Q', N, N, N, WORK( IU ), LDWRKU, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in VT +* (Workspace: need N*N+4*N-1, +* prefer N*N+3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of R in WORK(IU) and computing +* right singular vectors of R in VT +* (Workspace: need N*N+BDSPAC) +* + CALL DBDSQR( 'U', N, N, N, 0, S, WORK( IE ), VT, + $ LDVT, WORK( IU ), LDWRKU, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply Q in U by left singular vectors of R in +* WORK(IU), storing result in A +* (Workspace: need N*N) +* + CALL DGEMM( 'N', 'N', M, N, N, ONE, U, LDU, + $ WORK( IU ), LDWRKU, ZERO, A, LDA ) +* +* Copy left singular vectors of A from A to U +* + CALL DLACPY( 'F', M, N, A, LDA, U, LDU ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + N +* +* Compute A=Q*R, copying result to U +* (Workspace: need 2*N, prefer N+N*NB) +* + CALL DGEQRF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) +* +* Generate Q in U +* (Workspace: need N+M, prefer N+M*NB) +* + CALL DORGQR( M, M, N, U, LDU, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy R from A to VT, zeroing out below it +* + CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT ) + IF( N.GT.1 ) + $ CALL DLASET( 'L', N-1, N-1, ZERO, ZERO, + $ VT( 2, 1 ), LDVT ) + IE = ITAU + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize R in VT +* (Workspace: need 4*N, prefer 3*N+2*N*NB) +* + CALL DGEBRD( N, N, VT, LDVT, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply Q in U by left bidiagonalizing vectors +* in VT +* (Workspace: need 3*N+M, prefer 3*N+M*NB) +* + CALL DORMBR( 'Q', 'R', 'N', M, N, N, VT, LDVT, + $ WORK( ITAUQ ), U, LDU, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in VT +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + N +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, N, M, 0, S, WORK( IE ), VT, + $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + END IF +* + END IF +* + ELSE +* +* M .LT. MNTHR +* +* Path 10 (M at least N, but not much larger) +* Reduce to bidiagonal form without QR decomposition +* + IE = 1 + ITAUQ = IE + N + ITAUP = ITAUQ + N + IWORK = ITAUP + N +* +* Bidiagonalize A +* (Workspace: need 3*N+M, prefer 3*N+(M+N)*NB) +* + CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1, + $ IERR ) + IF( WNTUAS ) THEN +* +* If left singular vectors desired in U, copy result to U +* and generate left bidiagonalizing vectors in U +* (Workspace: need 3*N+NCU, prefer 3*N+NCU*NB) +* + CALL DLACPY( 'L', M, N, A, LDA, U, LDU ) + IF( WNTUS ) + $ NCU = N + IF( WNTUA ) + $ NCU = M + CALL DORGBR( 'Q', M, NCU, N, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IF( WNTVAS ) THEN +* +* If right singular vectors desired in VT, copy result to +* VT and generate right bidiagonalizing vectors in VT +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DLACPY( 'U', N, N, A, LDA, VT, LDVT ) + CALL DORGBR( 'P', N, N, N, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IF( WNTUO ) THEN +* +* If left singular vectors desired in A, generate left +* bidiagonalizing vectors in A +* (Workspace: need 4*N, prefer 3*N+N*NB) +* + CALL DORGBR( 'Q', M, N, N, A, LDA, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IF( WNTVO ) THEN +* +* If right singular vectors desired in A, generate right +* bidiagonalizing vectors in A +* (Workspace: need 4*N-1, prefer 3*N+(N-1)*NB) +* + CALL DORGBR( 'P', N, N, N, A, LDA, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IWORK = IE + N + IF( WNTUAS .OR. WNTUO ) + $ NRU = M + IF( WNTUN ) + $ NRU = 0 + IF( WNTVAS .OR. WNTVO ) + $ NCVT = N + IF( WNTVN ) + $ NCVT = 0 + IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN +* +* Perform bidiagonal QR iteration, if desired, computing +* left singular vectors in U and computing right singular +* vectors in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT, + $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO ) + ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN +* +* Perform bidiagonal QR iteration, if desired, computing +* left singular vectors in U and computing right singular +* vectors in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), A, LDA, + $ U, LDU, DUM, 1, WORK( IWORK ), INFO ) + ELSE +* +* Perform bidiagonal QR iteration, if desired, computing +* left singular vectors in A and computing right singular +* vectors in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', N, NCVT, NRU, 0, S, WORK( IE ), VT, + $ LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO ) + END IF +* + END IF +* + ELSE +* +* A has more columns than rows. If A has sufficiently more +* columns than rows, first reduce using the LQ decomposition (if +* sufficient workspace available) +* + IF( N.GE.MNTHR ) THEN +* + IF( WNTVN ) THEN +* +* Path 1t(N much larger than M, JOBVT='N') +* No right singular vectors to be computed +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Zero out above L +* + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), LDA ) + IE = 1 + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in A +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1, + $ IERR ) + IF( WNTUO .OR. WNTUAS ) THEN +* +* If left singular vectors desired, generate Q +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IWORK = IE + M + NRU = 0 + IF( WNTUO .OR. WNTUAS ) + $ NRU = M +* +* Perform bidiagonal QR iteration, computing left singular +* vectors of A in A if desired +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, 0, NRU, 0, S, WORK( IE ), DUM, 1, A, + $ LDA, DUM, 1, WORK( IWORK ), INFO ) +* +* If left singular vectors desired in U, copy them there +* + IF( WNTUAS ) + $ CALL DLACPY( 'F', M, M, A, LDA, U, LDU ) +* + ELSE IF( WNTVO .AND. WNTUN ) THEN +* +* Path 2t(N much larger than M, JOBU='N', JOBVT='O') +* M right singular vectors to be overwritten on A and +* no left singular vectors to be computed +* + IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is LDA by M +* + LDWRKU = LDA + CHUNK = N + LDWRKR = LDA + ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is M by M +* + LDWRKU = LDA + CHUNK = N + LDWRKR = M + ELSE +* +* WORK(IU) is M by CHUNK and WORK(IR) is M by M +* + LDWRKU = M + CHUNK = ( LWORK-M*M-M ) / M + LDWRKR = M + END IF + ITAU = IR + LDWRKR*M + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to WORK(IR) and zero out above it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), LDWRKR ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IR+LDWRKR ), LDWRKR ) +* +* Generate Q in A +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IR) +* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate right vectors bidiagonalizing L +* (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of L in WORK(IR) +* (Workspace: need M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ), + $ WORK( IR ), LDWRKR, DUM, 1, DUM, 1, + $ WORK( IWORK ), INFO ) + IU = IE + M +* +* Multiply right singular vectors of L in WORK(IR) by Q +* in A, storing result in WORK(IU) and copying to A +* (Workspace: need M*M+2*M, prefer M*M+M*N+M) +* + DO 30 I = 1, N, CHUNK + BLK = MIN( N-I+1, CHUNK ) + CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ), + $ LDWRKR, A( 1, I ), LDA, ZERO, + $ WORK( IU ), LDWRKU ) + CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU, + $ A( 1, I ), LDA ) + 30 CONTINUE +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + IE = 1 + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize A +* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB) +* + CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate right vectors bidiagonalizing A +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of A in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'L', M, N, 0, 0, S, WORK( IE ), A, LDA, + $ DUM, 1, DUM, 1, WORK( IWORK ), INFO ) +* + END IF +* + ELSE IF( WNTVO .AND. WNTUAS ) THEN +* +* Path 3t(N much larger than M, JOBU='S' or 'A', JOBVT='O') +* M right singular vectors to be overwritten on A and +* M left singular vectors to be computed in U +* + IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+LDA*M ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is LDA by M +* + LDWRKU = LDA + CHUNK = N + LDWRKR = LDA + ELSE IF( LWORK.GE.MAX( WRKBL, LDA*N+M )+M*M ) THEN +* +* WORK(IU) is LDA by N and WORK(IR) is M by M +* + LDWRKU = LDA + CHUNK = N + LDWRKR = M + ELSE +* +* WORK(IU) is M by CHUNK and WORK(IR) is M by M +* + LDWRKU = M + CHUNK = ( LWORK-M*M-M ) / M + LDWRKR = M + END IF + ITAU = IR + LDWRKR*M + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to U, zeroing about above it +* + CALL DLACPY( 'L', M, M, A, LDA, U, LDU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ), + $ LDU ) +* +* Generate Q in A +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in U, copying result to WORK(IR) +* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, U, LDU, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, M, U, LDU, WORK( IR ), LDWRKR ) +* +* Generate right vectors bidiagonalizing L in WORK(IR) +* (Workspace: need M*M+4*M-1, prefer M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left vectors bidiagonalizing L in U +* (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of L in U, and computing right +* singular vectors of L in WORK(IR) +* (Workspace: need M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ), + $ WORK( IR ), LDWRKR, U, LDU, DUM, 1, + $ WORK( IWORK ), INFO ) + IU = IE + M +* +* Multiply right singular vectors of L in WORK(IR) by Q +* in A, storing result in WORK(IU) and copying to A +* (Workspace: need M*M+2*M, prefer M*M+M*N+M)) +* + DO 40 I = 1, N, CHUNK + BLK = MIN( N-I+1, CHUNK ) + CALL DGEMM( 'N', 'N', M, BLK, M, ONE, WORK( IR ), + $ LDWRKR, A( 1, I ), LDA, ZERO, + $ WORK( IU ), LDWRKU ) + CALL DLACPY( 'F', M, BLK, WORK( IU ), LDWRKU, + $ A( 1, I ), LDA ) + 40 CONTINUE +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to U, zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, U, LDU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ), + $ LDU ) +* +* Generate Q in A +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in U +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, U, LDU, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right vectors bidiagonalizing L by Q in A +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU, + $ WORK( ITAUP ), A, LDA, WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left vectors bidiagonalizing L in U +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), A, LDA, + $ U, LDU, DUM, 1, WORK( IWORK ), INFO ) +* + END IF +* + ELSE IF( WNTVS ) THEN +* + IF( WNTUN ) THEN +* +* Path 4t(N much larger than M, JOBU='N', JOBVT='S') +* M right singular vectors to be computed in VT and +* no left singular vectors to be computed +* + IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.WRKBL+LDA*M ) THEN +* +* WORK(IR) is LDA by M +* + LDWRKR = LDA + ELSE +* +* WORK(IR) is M by M +* + LDWRKR = M + END IF + ITAU = IR + LDWRKR*M + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to WORK(IR), zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), + $ LDWRKR ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IR+LDWRKR ), LDWRKR ) +* +* Generate Q in A +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IR) +* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right vectors bidiagonalizing L in +* WORK(IR) +* (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of L in WORK(IR) +* (Workspace: need M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ), + $ WORK( IR ), LDWRKR, DUM, 1, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply right singular vectors of L in WORK(IR) by +* Q in A, storing result in VT +* (Workspace: need M*M) +* + CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ), + $ LDWRKR, A, LDA, ZERO, VT, LDVT ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy result to VT +* + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Zero out above L in A +* + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), + $ LDA ) +* +* Bidiagonalize L in A +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right vectors bidiagonalizing L by Q in VT +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA, + $ WORK( ITAUP ), VT, LDVT, + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT, + $ LDVT, DUM, 1, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTUO ) THEN +* +* Path 5t(N much larger than M, JOBU='O', JOBVT='S') +* M right singular vectors to be computed in VT and +* M left singular vectors to be overwritten on A +* + IF( LWORK.GE.2*M*M+MAX( 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+2*LDA*M ) THEN +* +* WORK(IU) is LDA by M and WORK(IR) is LDA by M +* + LDWRKU = LDA + IR = IU + LDWRKU*M + LDWRKR = LDA + ELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN +* +* WORK(IU) is LDA by M and WORK(IR) is M by M +* + LDWRKU = LDA + IR = IU + LDWRKU*M + LDWRKR = M + ELSE +* +* WORK(IU) is M by M and WORK(IR) is M by M +* + LDWRKU = M + IR = IU + LDWRKU*M + LDWRKR = M + END IF + ITAU = IR + LDWRKR*M + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to WORK(IU), zeroing out below it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IU+LDWRKU ), LDWRKU ) +* +* Generate Q in A +* (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB) +* + CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IU), copying result to +* WORK(IR) +* (Workspace: need 2*M*M+4*M, +* prefer 2*M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, + $ WORK( IR ), LDWRKR ) +* +* Generate right bidiagonalizing vectors in WORK(IU) +* (Workspace: need 2*M*M+4*M-1, +* prefer 2*M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in WORK(IR) +* (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of L in WORK(IR) and computing +* right singular vectors of L in WORK(IU) +* (Workspace: need 2*M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ), + $ WORK( IU ), LDWRKU, WORK( IR ), + $ LDWRKR, DUM, 1, WORK( IWORK ), INFO ) +* +* Multiply right singular vectors of L in WORK(IU) by +* Q in A, storing result in VT +* (Workspace: need M*M) +* + CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ), + $ LDWRKU, A, LDA, ZERO, VT, LDVT ) +* +* Copy left singular vectors of L to A +* (Workspace: need M*M) +* + CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A, + $ LDA ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Zero out above L in A +* + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), + $ LDA ) +* +* Bidiagonalize L in A +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right vectors bidiagonalizing L by Q in VT +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA, + $ WORK( ITAUP ), VT, LDVT, + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors of L in A +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, compute left +* singular vectors of A in A and compute right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT, + $ LDVT, A, LDA, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTUAS ) THEN +* +* Path 6t(N much larger than M, JOBU='S' or 'A', +* JOBVT='S') +* M right singular vectors to be computed in VT and +* M left singular vectors to be computed in U +* + IF( LWORK.GE.M*M+MAX( 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+LDA*M ) THEN +* +* WORK(IU) is LDA by N +* + LDWRKU = LDA + ELSE +* +* WORK(IU) is LDA by M +* + LDWRKU = M + END IF + ITAU = IU + LDWRKU*M + IWORK = ITAU + M +* +* Compute A=L*Q +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to WORK(IU), zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IU+LDWRKU ), LDWRKU ) +* +* Generate Q in A +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DORGLQ( M, N, M, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IU), copying result to U +* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U, + $ LDU ) +* +* Generate right bidiagonalizing vectors in WORK(IU) +* (Workspace: need M*M+4*M-1, +* prefer M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in U +* (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of L in U and computing right +* singular vectors of L in WORK(IU) +* (Workspace: need M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ), + $ WORK( IU ), LDWRKU, U, LDU, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply right singular vectors of L in WORK(IU) by +* Q in A, storing result in VT +* (Workspace: need M*M) +* + CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ), + $ LDWRKU, A, LDA, ZERO, VT, LDVT ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DORGLQ( M, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to U, zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, U, LDU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ), + $ LDU ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in U +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, U, LDU, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right bidiagonalizing vectors in U by Q +* in VT +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU, + $ WORK( ITAUP ), VT, LDVT, + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in U +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT, + $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + END IF +* + ELSE IF( WNTVA ) THEN +* + IF( WNTUN ) THEN +* +* Path 7t(N much larger than M, JOBU='N', JOBVT='A') +* N right singular vectors to be computed in VT and +* no left singular vectors to be computed +* + IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IR = 1 + IF( LWORK.GE.WRKBL+LDA*M ) THEN +* +* WORK(IR) is LDA by M +* + LDWRKR = LDA + ELSE +* +* WORK(IR) is M by M +* + LDWRKR = M + END IF + ITAU = IR + LDWRKR*M + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Copy L to WORK(IR), zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IR ), + $ LDWRKR ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IR+LDWRKR ), LDWRKR ) +* +* Generate Q in VT +* (Workspace: need M*M+M+N, prefer M*M+M+N*NB) +* + CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IR) +* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IR ), LDWRKR, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate right bidiagonalizing vectors in WORK(IR) +* (Workspace: need M*M+4*M-1, +* prefer M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IR ), LDWRKR, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of L in WORK(IR) +* (Workspace: need M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, 0, 0, S, WORK( IE ), + $ WORK( IR ), LDWRKR, DUM, 1, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply right singular vectors of L in WORK(IR) by +* Q in VT, storing result in A +* (Workspace: need M*M) +* + CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IR ), + $ LDWRKR, VT, LDVT, ZERO, A, LDA ) +* +* Copy right singular vectors of A from A to VT +* + CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need M+N, prefer M+N*NB) +* + CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Zero out above L in A +* + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), + $ LDA ) +* +* Bidiagonalize L in A +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right bidiagonalizing vectors in A by Q +* in VT +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA, + $ WORK( ITAUP ), VT, LDVT, + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, 0, 0, S, WORK( IE ), VT, + $ LDVT, DUM, 1, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTUO ) THEN +* +* Path 8t(N much larger than M, JOBU='O', JOBVT='A') +* N right singular vectors to be computed in VT and +* M left singular vectors to be overwritten on A +* + IF( LWORK.GE.2*M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+2*LDA*M ) THEN +* +* WORK(IU) is LDA by M and WORK(IR) is LDA by M +* + LDWRKU = LDA + IR = IU + LDWRKU*M + LDWRKR = LDA + ELSE IF( LWORK.GE.WRKBL+( LDA+M )*M ) THEN +* +* WORK(IU) is LDA by M and WORK(IR) is M by M +* + LDWRKU = LDA + IR = IU + LDWRKU*M + LDWRKR = M + ELSE +* +* WORK(IU) is M by M and WORK(IR) is M by M +* + LDWRKU = M + IR = IU + LDWRKU*M + LDWRKR = M + END IF + ITAU = IR + LDWRKR*M + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need 2*M*M+2*M, prefer 2*M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need 2*M*M+M+N, prefer 2*M*M+M+N*NB) +* + CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to WORK(IU), zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IU+LDWRKU ), LDWRKU ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IU), copying result to +* WORK(IR) +* (Workspace: need 2*M*M+4*M, +* prefer 2*M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, + $ WORK( IR ), LDWRKR ) +* +* Generate right bidiagonalizing vectors in WORK(IU) +* (Workspace: need 2*M*M+4*M-1, +* prefer 2*M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in WORK(IR) +* (Workspace: need 2*M*M+4*M, prefer 2*M*M+3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, WORK( IR ), LDWRKR, + $ WORK( ITAUQ ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of L in WORK(IR) and computing +* right singular vectors of L in WORK(IU) +* (Workspace: need 2*M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ), + $ WORK( IU ), LDWRKU, WORK( IR ), + $ LDWRKR, DUM, 1, WORK( IWORK ), INFO ) +* +* Multiply right singular vectors of L in WORK(IU) by +* Q in VT, storing result in A +* (Workspace: need M*M) +* + CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ), + $ LDWRKU, VT, LDVT, ZERO, A, LDA ) +* +* Copy right singular vectors of A from A to VT +* + CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT ) +* +* Copy left singular vectors of A from WORK(IR) to A +* + CALL DLACPY( 'F', M, M, WORK( IR ), LDWRKR, A, + $ LDA ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need M+N, prefer M+N*NB) +* + CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Zero out above L in A +* + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, A( 1, 2 ), + $ LDA ) +* +* Bidiagonalize L in A +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, A, LDA, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right bidiagonalizing vectors in A by Q +* in VT +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, A, LDA, + $ WORK( ITAUP ), VT, LDVT, + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in A +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, A, LDA, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in A and computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT, + $ LDVT, A, LDA, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + ELSE IF( WNTUAS ) THEN +* +* Path 9t(N much larger than M, JOBU='S' or 'A', +* JOBVT='A') +* N right singular vectors to be computed in VT and +* M left singular vectors to be computed in U +* + IF( LWORK.GE.M*M+MAX( N+M, 4*M, BDSPAC ) ) THEN +* +* Sufficient workspace for a fast algorithm +* + IU = 1 + IF( LWORK.GE.WRKBL+LDA*M ) THEN +* +* WORK(IU) is LDA by M +* + LDWRKU = LDA + ELSE +* +* WORK(IU) is M by M +* + LDWRKU = M + END IF + ITAU = IU + LDWRKU*M + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need M*M+2*M, prefer M*M+M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need M*M+M+N, prefer M*M+M+N*NB) +* + CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to WORK(IU), zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, WORK( IU ), + $ LDWRKU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, + $ WORK( IU+LDWRKU ), LDWRKU ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in WORK(IU), copying result to U +* (Workspace: need M*M+4*M, prefer M*M+3*M+2*M*NB) +* + CALL DGEBRD( M, M, WORK( IU ), LDWRKU, S, + $ WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) + CALL DLACPY( 'L', M, M, WORK( IU ), LDWRKU, U, + $ LDU ) +* +* Generate right bidiagonalizing vectors in WORK(IU) +* (Workspace: need M*M+4*M, prefer M*M+3*M+(M-1)*NB) +* + CALL DORGBR( 'P', M, M, M, WORK( IU ), LDWRKU, + $ WORK( ITAUP ), WORK( IWORK ), + $ LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in U +* (Workspace: need M*M+4*M, prefer M*M+3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of L in U and computing right +* singular vectors of L in WORK(IU) +* (Workspace: need M*M+BDSPAC) +* + CALL DBDSQR( 'U', M, M, M, 0, S, WORK( IE ), + $ WORK( IU ), LDWRKU, U, LDU, DUM, 1, + $ WORK( IWORK ), INFO ) +* +* Multiply right singular vectors of L in WORK(IU) by +* Q in VT, storing result in A +* (Workspace: need M*M) +* + CALL DGEMM( 'N', 'N', M, N, M, ONE, WORK( IU ), + $ LDWRKU, VT, LDVT, ZERO, A, LDA ) +* +* Copy right singular vectors of A from A to VT +* + CALL DLACPY( 'F', M, N, A, LDA, VT, LDVT ) +* + ELSE +* +* Insufficient workspace for a fast algorithm +* + ITAU = 1 + IWORK = ITAU + M +* +* Compute A=L*Q, copying result to VT +* (Workspace: need 2*M, prefer M+M*NB) +* + CALL DGELQF( M, N, A, LDA, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) +* +* Generate Q in VT +* (Workspace: need M+N, prefer M+N*NB) +* + CALL DORGLQ( N, N, M, VT, LDVT, WORK( ITAU ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Copy L to U, zeroing out above it +* + CALL DLACPY( 'L', M, M, A, LDA, U, LDU ) + CALL DLASET( 'U', M-1, M-1, ZERO, ZERO, U( 1, 2 ), + $ LDU ) + IE = ITAU + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize L in U +* (Workspace: need 4*M, prefer 3*M+2*M*NB) +* + CALL DGEBRD( M, M, U, LDU, S, WORK( IE ), + $ WORK( ITAUQ ), WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Multiply right bidiagonalizing vectors in U by Q +* in VT +* (Workspace: need 3*M+N, prefer 3*M+N*NB) +* + CALL DORMBR( 'P', 'L', 'T', M, N, M, U, LDU, + $ WORK( ITAUP ), VT, LDVT, + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) +* +* Generate left bidiagonalizing vectors in U +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'Q', M, M, M, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + IWORK = IE + M +* +* Perform bidiagonal QR iteration, computing left +* singular vectors of A in U and computing right +* singular vectors of A in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'U', M, N, M, 0, S, WORK( IE ), VT, + $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), + $ INFO ) +* + END IF +* + END IF +* + END IF +* + ELSE +* +* N .LT. MNTHR +* +* Path 10t(N greater than M, but not much larger) +* Reduce to bidiagonal form without LQ decomposition +* + IE = 1 + ITAUQ = IE + M + ITAUP = ITAUQ + M + IWORK = ITAUP + M +* +* Bidiagonalize A +* (Workspace: need 3*M+N, prefer 3*M+(M+N)*NB) +* + CALL DGEBRD( M, N, A, LDA, S, WORK( IE ), WORK( ITAUQ ), + $ WORK( ITAUP ), WORK( IWORK ), LWORK-IWORK+1, + $ IERR ) + IF( WNTUAS ) THEN +* +* If left singular vectors desired in U, copy result to U +* and generate left bidiagonalizing vectors in U +* (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB) +* + CALL DLACPY( 'L', M, M, A, LDA, U, LDU ) + CALL DORGBR( 'Q', M, M, N, U, LDU, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IF( WNTVAS ) THEN +* +* If right singular vectors desired in VT, copy result to +* VT and generate right bidiagonalizing vectors in VT +* (Workspace: need 3*M+NRVT, prefer 3*M+NRVT*NB) +* + CALL DLACPY( 'U', M, N, A, LDA, VT, LDVT ) + IF( WNTVA ) + $ NRVT = N + IF( WNTVS ) + $ NRVT = M + CALL DORGBR( 'P', NRVT, N, M, VT, LDVT, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IF( WNTUO ) THEN +* +* If left singular vectors desired in A, generate left +* bidiagonalizing vectors in A +* (Workspace: need 4*M-1, prefer 3*M+(M-1)*NB) +* + CALL DORGBR( 'Q', M, M, N, A, LDA, WORK( ITAUQ ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IF( WNTVO ) THEN +* +* If right singular vectors desired in A, generate right +* bidiagonalizing vectors in A +* (Workspace: need 4*M, prefer 3*M+M*NB) +* + CALL DORGBR( 'P', M, N, M, A, LDA, WORK( ITAUP ), + $ WORK( IWORK ), LWORK-IWORK+1, IERR ) + END IF + IWORK = IE + M + IF( WNTUAS .OR. WNTUO ) + $ NRU = M + IF( WNTUN ) + $ NRU = 0 + IF( WNTVAS .OR. WNTVO ) + $ NCVT = N + IF( WNTVN ) + $ NCVT = 0 + IF( ( .NOT.WNTUO ) .AND. ( .NOT.WNTVO ) ) THEN +* +* Perform bidiagonal QR iteration, if desired, computing +* left singular vectors in U and computing right singular +* vectors in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT, + $ LDVT, U, LDU, DUM, 1, WORK( IWORK ), INFO ) + ELSE IF( ( .NOT.WNTUO ) .AND. WNTVO ) THEN +* +* Perform bidiagonal QR iteration, if desired, computing +* left singular vectors in U and computing right singular +* vectors in A +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), A, LDA, + $ U, LDU, DUM, 1, WORK( IWORK ), INFO ) + ELSE +* +* Perform bidiagonal QR iteration, if desired, computing +* left singular vectors in A and computing right singular +* vectors in VT +* (Workspace: need BDSPAC) +* + CALL DBDSQR( 'L', M, NCVT, NRU, 0, S, WORK( IE ), VT, + $ LDVT, A, LDA, DUM, 1, WORK( IWORK ), INFO ) + END IF +* + END IF +* + END IF +* +* If DBDSQR failed to converge, copy unconverged superdiagonals +* to WORK( 2:MINMN ) +* + IF( INFO.NE.0 ) THEN + IF( IE.GT.2 ) THEN + DO 50 I = 1, MINMN - 1 + WORK( I+1 ) = WORK( I+IE-1 ) + 50 CONTINUE + END IF + IF( IE.LT.2 ) THEN + DO 60 I = MINMN - 1, 1, -1 + WORK( I+1 ) = WORK( I+IE-1 ) + 60 CONTINUE + END IF + END IF +* +* Undo scaling if necessary +* + IF( ISCL.EQ.1 ) THEN + IF( ANRM.GT.BIGNUM ) + $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN, 1, S, MINMN, + $ IERR ) + IF( INFO.NE.0 .AND. ANRM.GT.BIGNUM ) + $ CALL DLASCL( 'G', 0, 0, BIGNUM, ANRM, MINMN-1, 1, WORK( 2 ), + $ MINMN, IERR ) + IF( ANRM.LT.SMLNUM ) + $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN, 1, S, MINMN, + $ IERR ) + IF( INFO.NE.0 .AND. ANRM.LT.SMLNUM ) + $ CALL DLASCL( 'G', 0, 0, SMLNUM, ANRM, MINMN-1, 1, WORK( 2 ), + $ MINMN, IERR ) + END IF +* +* Return optimal workspace in WORK(1) +* + WORK( 1 ) = MAXWRK +* + RETURN +* +* End of DGESVD +* + END diff --git a/dep/lapack/dgetf2.f b/dep/lapack/dgetf2.f new file mode 100644 index 00000000..ee28e8e7 --- /dev/null +++ b/dep/lapack/dgetf2.f @@ -0,0 +1,150 @@ + SUBROUTINE DGETF2( M, N, A, LDA, IPIV, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DGETF2 computes an LU factorization of a general m-by-n matrix A +* using partial pivoting with row interchanges. +* +* The factorization has the form +* A = P * L * U +* where P is a permutation matrix, L is lower triangular with unit +* diagonal elements (lower trapezoidal if m > n), and U is upper +* triangular (upper trapezoidal if m < n). +* +* This is the right-looking Level 2 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the m by n matrix to be factored. +* On exit, the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, U(k,k) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION SFMIN + INTEGER I, J, JP +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + INTEGER IDAMAX + EXTERNAL DLAMCH, IDAMAX +* .. +* .. External Subroutines .. + EXTERNAL DGER, DSCAL, DSWAP, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGETF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Compute machine safe minimum +* + SFMIN = DLAMCH('S') +* + DO 10 J = 1, MIN( M, N ) +* +* Find pivot and test for singularity. +* + JP = J - 1 + IDAMAX( M-J+1, A( J, J ), 1 ) + IPIV( J ) = JP + IF( A( JP, J ).NE.ZERO ) THEN +* +* Apply the interchange to columns 1:N. +* + IF( JP.NE.J ) + $ CALL DSWAP( N, A( J, 1 ), LDA, A( JP, 1 ), LDA ) +* +* Compute elements J+1:M of J-th column. +* + IF( J.LT.M ) THEN + IF( ABS(A( J, J )) .GE. SFMIN ) THEN + CALL DSCAL( M-J, ONE / A( J, J ), A( J+1, J ), 1 ) + ELSE + DO 20 I = 1, M-J + A( J+I, J ) = A( J+I, J ) / A( J, J ) + 20 CONTINUE + END IF + END IF +* + ELSE IF( INFO.EQ.0 ) THEN +* + INFO = J + END IF +* + IF( J.LT.MIN( M, N ) ) THEN +* +* Update trailing submatrix. +* + CALL DGER( M-J, N-J, -ONE, A( J+1, J ), 1, A( J, J+1 ), LDA, + $ A( J+1, J+1 ), LDA ) + END IF + 10 CONTINUE + RETURN +* +* End of DGETF2 +* + END + + + diff --git a/dep/lapack/dgetrf.f b/dep/lapack/dgetrf.f new file mode 100644 index 00000000..3f7aebee --- /dev/null +++ b/dep/lapack/dgetrf.f @@ -0,0 +1,160 @@ + SUBROUTINE DGETRF( M, N, A, LDA, IPIV, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DGETRF computes an LU factorization of a general M-by-N matrix A +* using partial pivoting with row interchanges. +* +* The factorization has the form +* A = P * L * U +* where P is a permutation matrix, L is lower triangular with unit +* diagonal elements (lower trapezoidal if m > n), and U is upper +* triangular (upper trapezoidal if m < n). +* +* This is the right-looking Level 3 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the M-by-N matrix to be factored. +* On exit, the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, IINFO, J, JB, NB +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DGETF2, DLASWP, DTRSM, XERBLA +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGETRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment. +* + NB = ILAENV( 1, 'DGETRF', ' ', M, N, -1, -1 ) + IF( NB.LE.1 .OR. NB.GE.MIN( M, N ) ) THEN +* +* Use unblocked code. +* + CALL DGETF2( M, N, A, LDA, IPIV, INFO ) + ELSE +* +* Use blocked code. +* + DO 20 J = 1, MIN( M, N ), NB + JB = MIN( MIN( M, N )-J+1, NB ) +* +* Factor diagonal and subdiagonal blocks and test for exact +* singularity. +* + CALL DGETF2( M-J+1, JB, A( J, J ), LDA, IPIV( J ), IINFO ) +* +* Adjust INFO and the pivot indices. +* + IF( INFO.EQ.0 .AND. IINFO.GT.0 ) + $ INFO = IINFO + J - 1 + DO 10 I = J, MIN( M, J+JB-1 ) + IPIV( I ) = J - 1 + IPIV( I ) + 10 CONTINUE +* +* Apply interchanges to columns 1:J-1. +* + CALL DLASWP( J-1, A, LDA, J, J+JB-1, IPIV, 1 ) +* + IF( J+JB.LE.N ) THEN +* +* Apply interchanges to columns J+JB:N. +* + CALL DLASWP( N-J-JB+1, A( 1, J+JB ), LDA, J, J+JB-1, + $ IPIV, 1 ) +* +* Compute block row of U. +* + CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Unit', JB, + $ N-J-JB+1, ONE, A( J, J ), LDA, A( J, J+JB ), + $ LDA ) + IF( J+JB.LE.M ) THEN +* +* Update trailing submatrix. +* + CALL DGEMM( 'No transpose', 'No transpose', M-J-JB+1, + $ N-J-JB+1, JB, -ONE, A( J+JB, J ), LDA, + $ A( J, J+JB ), LDA, ONE, A( J+JB, J+JB ), + $ LDA ) + END IF + END IF + 20 CONTINUE + END IF + RETURN +* +* End of DGETRF +* + END diff --git a/dep/lapack/dgetri.f b/dep/lapack/dgetri.f new file mode 100644 index 00000000..9f789018 --- /dev/null +++ b/dep/lapack/dgetri.f @@ -0,0 +1,194 @@ + SUBROUTINE DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LWORK, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION A( LDA, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DGETRI computes the inverse of a matrix using the LU factorization +* computed by DGETRF. +* +* This method inverts U and then computes inv(A) by solving the system +* inv(A)*L = inv(U) for inv(A). +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the factors L and U from the factorization +* A = P*L*U as computed by DGETRF. +* On exit, if INFO = 0, the inverse of the original matrix A. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices from DGETRF; for 1<=i<=N, row i of the +* matrix was interchanged with row IPIV(i). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO=0, then WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,N). +* For optimal performance LWORK >= N*NB, where NB is +* the optimal blocksize returned by ILAENV. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero; the matrix is +* singular and its inverse could not be computed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IWS, J, JB, JJ, JP, LDWORK, LWKOPT, NB, + $ NBMIN, NN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DGEMV, DSWAP, DTRSM, DTRTRI, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NB = ILAENV( 1, 'DGETRI', ' ', N, -1, -1, -1 ) + LWKOPT = N*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -3 + ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGETRI', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Form inv(U). If INFO > 0 from DTRTRI, then U is singular, +* and the inverse is not computed. +* + CALL DTRTRI( 'Upper', 'Non-unit', N, A, LDA, INFO ) + IF( INFO.GT.0 ) + $ RETURN +* + NBMIN = 2 + LDWORK = N + IF( NB.GT.1 .AND. NB.LT.N ) THEN + IWS = MAX( LDWORK*NB, 1 ) + IF( LWORK.LT.IWS ) THEN + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DGETRI', ' ', N, -1, -1, -1 ) ) + END IF + ELSE + IWS = N + END IF +* +* Solve the equation inv(A)*L = inv(U) for inv(A). +* + IF( NB.LT.NBMIN .OR. NB.GE.N ) THEN +* +* Use unblocked code. +* + DO 20 J = N, 1, -1 +* +* Copy current column of L to WORK and replace with zeros. +* + DO 10 I = J + 1, N + WORK( I ) = A( I, J ) + A( I, J ) = ZERO + 10 CONTINUE +* +* Compute current column of inv(A). +* + IF( J.LT.N ) + $ CALL DGEMV( 'No transpose', N, N-J, -ONE, A( 1, J+1 ), + $ LDA, WORK( J+1 ), 1, ONE, A( 1, J ), 1 ) + 20 CONTINUE + ELSE +* +* Use blocked code. +* + NN = ( ( N-1 ) / NB )*NB + 1 + DO 50 J = NN, 1, -NB + JB = MIN( NB, N-J+1 ) +* +* Copy current block column of L to WORK and replace with +* zeros. +* + DO 40 JJ = J, J + JB - 1 + DO 30 I = JJ + 1, N + WORK( I+( JJ-J )*LDWORK ) = A( I, JJ ) + A( I, JJ ) = ZERO + 30 CONTINUE + 40 CONTINUE +* +* Compute current block column of inv(A). +* + IF( J+JB.LE.N ) + $ CALL DGEMM( 'No transpose', 'No transpose', N, JB, + $ N-J-JB+1, -ONE, A( 1, J+JB ), LDA, + $ WORK( J+JB ), LDWORK, ONE, A( 1, J ), LDA ) + CALL DTRSM( 'Right', 'Lower', 'No transpose', 'Unit', N, JB, + $ ONE, WORK( J ), LDWORK, A( 1, J ), LDA ) + 50 CONTINUE + END IF +* +* Apply column interchanges. +* + DO 60 J = N - 1, 1, -1 + JP = IPIV( J ) + IF( JP.NE.J ) + $ CALL DSWAP( N, A( 1, J ), 1, A( 1, JP ), 1 ) + 60 CONTINUE +* + WORK( 1 ) = IWS + RETURN +* +* End of DGETRI +* + END + diff --git a/dep/lapack/dgetrs.f b/dep/lapack/dgetrs.f new file mode 100644 index 00000000..927d25cb --- /dev/null +++ b/dep/lapack/dgetrs.f @@ -0,0 +1,150 @@ + SUBROUTINE DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DGETRS solves a system of linear equations +* A * X = B or A' * X = B +* with a general N-by-N matrix A using the LU factorization computed +* by DGETRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER*1 +* Specifies the form of the system of equations: +* = 'N': A * X = B (No transpose) +* = 'T': A'* X = B (Transpose) +* = 'C': A'* X = B (Conjugate transpose = Transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,N) +* The factors L and U from the factorization A = P*L*U +* as computed by DGETRF. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices from DGETRF; for 1<=i<=N, row i of the +* matrix was interchanged with row IPIV(i). +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOTRAN +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLASWP, DTRSM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGETRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( NOTRAN ) THEN +* +* Solve A * X = B. +* +* Apply row interchanges to the right hand sides. +* + CALL DLASWP( NRHS, B, LDB, 1, N, IPIV, 1 ) +* +* Solve L*X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Unit', N, NRHS, + $ ONE, A, LDA, B, LDB ) +* +* Solve U*X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', N, + $ NRHS, ONE, A, LDA, B, LDB ) + ELSE +* +* Solve A' * X = B. +* +* Solve U'*X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Upper', 'Transpose', 'Non-unit', N, NRHS, + $ ONE, A, LDA, B, LDB ) +* +* Solve L'*X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Lower', 'Transpose', 'Unit', N, NRHS, ONE, + $ A, LDA, B, LDB ) +* +* Apply row interchanges to the solution vectors. +* + CALL DLASWP( NRHS, B, LDB, 1, N, IPIV, -1 ) + END IF +* + RETURN +* +* End of DGETRS +* + END diff --git a/dep/lapack/dgttrf.f b/dep/lapack/dgttrf.f new file mode 100644 index 00000000..01dbbe02 --- /dev/null +++ b/dep/lapack/dgttrf.f @@ -0,0 +1,149 @@ + SUBROUTINE DGTTRF( N, DL, D, DU, DU2, IPIV, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION D( * ), DL( * ), DU( * ), DU2( * ) +* .. +* +* Purpose +* ======= +* +* DGTTRF computes an LU factorization of a real tridiagonal matrix A +* using elimination with partial pivoting and row interchanges. +* +* The factorization has the form +* A = L * U +* where L is a product of permutation and unit lower bidiagonal +* matrices and U is upper triangular with nonzeros in only the main +* diagonal and first two superdiagonals. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* DL (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, DL must contain the (n-1) subdiagonal elements of +* A. +* On exit, DL is overwritten by the (n-1) multipliers that +* define the matrix L from the LU factorization of A. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, D must contain the diagonal elements of A. +* On exit, D is overwritten by the n diagonal elements of the +* upper triangular matrix U from the LU factorization of A. +* +* DU (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, DU must contain the (n-1) superdiagonal elements +* of A. +* On exit, DU is overwritten by the (n-1) elements of the first +* superdiagonal of U. +* +* DU2 (output) DOUBLE PRECISION array, dimension (N-2) +* On exit, DU2 is overwritten by the (n-2) elements of the +* second superdiagonal of U. +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= n, row i of the matrix was +* interchanged with row IPIV(i). IPIV(i) will always be either +* i or i+1; IPIV(i) = i indicates a row interchange was not +* required. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION FACT, TEMP +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DGTTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Initialize IPIV(i) = i +* + DO 10 I = 1, N + IPIV( I ) = I + 10 CONTINUE +* + DO 20 I = 1, N - 1 + IF( DL( I ).EQ.ZERO ) THEN +* +* Subdiagonal is zero, no elimination is required. +* + IF( D( I ).EQ.ZERO .AND. INFO.EQ.0 ) + $ INFO = I + IF( I.LT.N-1 ) + $ DU2( I ) = ZERO + ELSE IF( ABS( D( I ) ).GE.ABS( DL( I ) ) ) THEN +* +* No row interchange required, eliminate DL(I) +* + FACT = DL( I ) / D( I ) + DL( I ) = FACT + D( I+1 ) = D( I+1 ) - FACT*DU( I ) + IF( I.LT.N-1 ) + $ DU2( I ) = ZERO + ELSE +* +* Interchange rows I and I+1, eliminate DL(I) +* + FACT = D( I ) / DL( I ) + D( I ) = DL( I ) + DL( I ) = FACT + TEMP = DU( I ) + DU( I ) = D( I+1 ) + D( I+1 ) = TEMP - FACT*D( I+1 ) + IF( I.LT.N-1 ) THEN + DU2( I ) = DU( I+1 ) + DU( I+1 ) = -FACT*DU( I+1 ) + END IF + IPIV( I ) = IPIV( I ) + 1 + END IF + 20 CONTINUE + IF( D( N ).EQ.ZERO .AND. INFO.EQ.0 ) THEN + INFO = N + RETURN + END IF +* + RETURN +* +* End of DGTTRF +* + END diff --git a/dep/lapack/dgttrs.f b/dep/lapack/dgttrs.f new file mode 100644 index 00000000..e19745e7 --- /dev/null +++ b/dep/lapack/dgttrs.f @@ -0,0 +1,176 @@ + SUBROUTINE DGTTRS( TRANS, N, NRHS, DL, D, DU, DU2, IPIV, B, LDB, + $ INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ), DU2( * ) +* .. +* +* Purpose +* ======= +* +* DGTTRS solves one of the systems of equations +* A*X = B or A'*X = B, +* with a tridiagonal matrix A using the LU factorization computed +* by DGTTRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER +* Specifies the form of the system of equations: +* = 'N': A * X = B (No transpose) +* = 'T': A'* X = B (Transpose) +* = 'C': A'* X = B (Conjugate transpose = Transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* DL (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) multipliers that define the matrix L from the +* LU factorization of A. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the upper triangular matrix U from +* the LU factorization of A. +* +* DU (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) elements of the first superdiagonal of U. +* +* DU2 (input) DOUBLE PRECISION array, dimension (N-2) +* The (n-2) elements of the second superdiagonal of U. +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices; for 1 <= i <= n, row i of the matrix was +* interchanged with row IPIV(i). IPIV(i) will always be either +* i or i+1; IPIV(i) = i indicates a row interchange was not +* required. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, B is overwritten by the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL NOTRAN + INTEGER I, J + DOUBLE PRECISION TEMP +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDB.LT.MAX( N, 1 ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DGTTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( NOTRAN ) THEN +* +* Solve A*X = B using the LU factorization of A, +* overwriting each right hand side vector with its solution. +* + DO 30 J = 1, NRHS +* +* Solve L*x = b. +* + DO 10 I = 1, N - 1 + IF( IPIV( I ).EQ.I ) THEN + B( I+1, J ) = B( I+1, J ) - DL( I )*B( I, J ) + ELSE + TEMP = B( I, J ) + B( I, J ) = B( I+1, J ) + B( I+1, J ) = TEMP - DL( I )*B( I, J ) + END IF + 10 CONTINUE +* +* Solve U*x = b. +* + B( N, J ) = B( N, J ) / D( N ) + IF( N.GT.1 ) + $ B( N-1, J ) = ( B( N-1, J )-DU( N-1 )*B( N, J ) ) / + $ D( N-1 ) + DO 20 I = N - 2, 1, -1 + B( I, J ) = ( B( I, J )-DU( I )*B( I+1, J )-DU2( I )* + $ B( I+2, J ) ) / D( I ) + 20 CONTINUE + 30 CONTINUE + ELSE +* +* Solve A' * X = B. +* + DO 60 J = 1, NRHS +* +* Solve U'*x = b. +* + B( 1, J ) = B( 1, J ) / D( 1 ) + IF( N.GT.1 ) + $ B( 2, J ) = ( B( 2, J )-DU( 1 )*B( 1, J ) ) / D( 2 ) + DO 40 I = 3, N + B( I, J ) = ( B( I, J )-DU( I-1 )*B( I-1, J )-DU2( I-2 )* + $ B( I-2, J ) ) / D( I ) + 40 CONTINUE +* +* Solve L'*x = b. +* + DO 50 I = N - 1, 1, -1 + IF( IPIV( I ).EQ.I ) THEN + B( I, J ) = B( I, J ) - DL( I )*B( I+1, J ) + ELSE + TEMP = B( I+1, J ) + B( I+1, J ) = B( I, J ) - DL( I )*TEMP + B( I, J ) = TEMP + END IF + 50 CONTINUE + 60 CONTINUE + END IF +* +* End of DGTTRS +* + END diff --git a/dep/lapack/dhseqr.f b/dep/lapack/dhseqr.f new file mode 100644 index 00000000..91e792c2 --- /dev/null +++ b/dep/lapack/dhseqr.f @@ -0,0 +1,414 @@ + SUBROUTINE DHSEQR( JOB, COMPZ, N, ILO, IHI, H, LDH, WR, WI, Z, + $ LDZ, WORK, LWORK, INFO ) +* +* -- LAPACK computational routine (version 3.2.2) -- +* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG +* Ltd.. +* June 2010 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, INFO, LDH, LDZ, LWORK, N + CHARACTER COMPZ, JOB +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ), + $ Z( LDZ, * ) +* .. +* Purpose +* ======= +* +* DHSEQR computes the eigenvalues of a Hessenberg matrix H +* and, optionally, the matrices T and Z from the Schur decomposition +* H = Z T Z**T, where T is an upper quasi-triangular matrix (the +* Schur form), and Z is the orthogonal matrix of Schur vectors. +* +* Optionally Z may be postmultiplied into an input orthogonal +* matrix Q so that this routine can give the Schur factorization +* of a matrix A which has been reduced to the Hessenberg form H +* by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. +* +* Arguments +* ========= +* +* JOB (input) CHARACTER*1 +* = 'E': compute eigenvalues only; +* = 'S': compute eigenvalues and the Schur form T. +* +* COMPZ (input) CHARACTER*1 +* = 'N': no Schur vectors are computed; +* = 'I': Z is initialized to the unit matrix and the matrix Z +* of Schur vectors of H is returned; +* = 'V': Z must contain an orthogonal matrix Q on entry, and +* the product Q*Z is returned. +* +* N (input) INTEGER +* The order of the matrix H. N .GE. 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* It is assumed that H is already upper triangular in rows +* and columns 1:ILO-1 and IHI+1:N. ILO and IHI are normally +* set by a previous call to DGEBAL, and then passed to DGEHRD +* when the matrix output by DGEBAL is reduced to Hessenberg +* form. Otherwise ILO and IHI should be set to 1 and N +* respectively. If N.GT.0, then 1.LE.ILO.LE.IHI.LE.N. +* If N = 0, then ILO = 1 and IHI = 0. +* +* H (input/output) DOUBLE PRECISION array, dimension (LDH,N) +* On entry, the upper Hessenberg matrix H. +* On exit, if INFO = 0 and JOB = 'S', then H contains the +* upper quasi-triangular matrix T from the Schur decomposition +* (the Schur form); 2-by-2 diagonal blocks (corresponding to +* complex conjugate pairs of eigenvalues) are returned in +* standard form, with H(i,i) = H(i+1,i+1) and +* H(i+1,i)*H(i,i+1).LT.0. If INFO = 0 and JOB = 'E', the +* contents of H are unspecified on exit. (The output value of +* H when INFO.GT.0 is given under the description of INFO +* below.) +* +* Unlike earlier versions of DHSEQR, this subroutine may +* explicitly H(i,j) = 0 for i.GT.j and j = 1, 2, ... ILO-1 +* or j = IHI+1, IHI+2, ... N. +* +* LDH (input) INTEGER +* The leading dimension of the array H. LDH .GE. max(1,N). +* +* WR (output) DOUBLE PRECISION array, dimension (N) +* WI (output) DOUBLE PRECISION array, dimension (N) +* The real and imaginary parts, respectively, of the computed +* eigenvalues. If two eigenvalues are computed as a complex +* conjugate pair, they are stored in consecutive elements of +* WR and WI, say the i-th and (i+1)th, with WI(i) .GT. 0 and +* WI(i+1) .LT. 0. If JOB = 'S', the eigenvalues are stored in +* the same order as on the diagonal of the Schur form returned +* in H, with WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 +* diagonal block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and +* WI(i+1) = -WI(i). +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N) +* If COMPZ = 'N', Z is not referenced. +* If COMPZ = 'I', on entry Z need not be set and on exit, +* if INFO = 0, Z contains the orthogonal matrix Z of the Schur +* vectors of H. If COMPZ = 'V', on entry Z must contain an +* N-by-N matrix Q, which is assumed to be equal to the unit +* matrix except for the submatrix Z(ILO:IHI,ILO:IHI). On exit, +* if INFO = 0, Z contains Q*Z. +* Normally Q is the orthogonal matrix generated by DORGHR +* after the call to DGEHRD which formed the Hessenberg matrix +* H. (The output value of Z when INFO.GT.0 is given under +* the description of INFO below.) +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. if COMPZ = 'I' or +* COMPZ = 'V', then LDZ.GE.MAX(1,N). Otherwize, LDZ.GE.1. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (LWORK) +* On exit, if INFO = 0, WORK(1) returns an estimate of +* the optimal value for LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK .GE. max(1,N) +* is sufficient and delivers very good and sometimes +* optimal performance. However, LWORK as large as 11*N +* may be required for optimal performance. A workspace +* query is recommended to determine the optimal workspace +* size. +* +* If LWORK = -1, then DHSEQR does a workspace query. +* In this case, DHSEQR checks the input parameters and +* estimates the optimal workspace size for the given +* values of N, ILO and IHI. The estimate is returned +* in WORK(1). No error message related to LWORK is +* issued by XERBLA. Neither H nor Z are accessed. +* +* +* INFO (output) INTEGER +* = 0: successful exit +* .LT. 0: if INFO = -i, the i-th argument had an illegal +* value +* .GT. 0: if INFO = i, DHSEQR failed to compute all of +* the eigenvalues. Elements 1:ilo-1 and i+1:n of WR +* and WI contain those eigenvalues which have been +* successfully computed. (Failures are rare.) +* +* If INFO .GT. 0 and JOB = 'E', then on exit, the +* remaining unconverged eigenvalues are the eigen- +* values of the upper Hessenberg matrix rows and +* columns ILO through INFO of the final, output +* value of H. +* +* If INFO .GT. 0 and JOB = 'S', then on exit +* +* (*) (initial value of H)*U = U*(final value of H) +* +* where U is an orthogonal matrix. The final +* value of H is upper Hessenberg and quasi-triangular +* in rows and columns INFO+1 through IHI. +* +* If INFO .GT. 0 and COMPZ = 'V', then on exit +* +* (final value of Z) = (initial value of Z)*U +* +* where U is the orthogonal matrix in (*) (regard- +* less of the value of JOB.) +* +* If INFO .GT. 0 and COMPZ = 'I', then on exit +* (final value of Z) = U +* where U is the orthogonal matrix in (*) (regard- +* less of the value of JOB.) +* +* If INFO .GT. 0 and COMPZ = 'N', then Z is not +* accessed. +* +* ================================================================ +* Default values supplied by +* ILAENV(ISPEC,'DHSEQR',JOB(:1)//COMPZ(:1),N,ILO,IHI,LWORK). +* It is suggested that these defaults be adjusted in order +* to attain best performance in each particular +* computational environment. +* +* ISPEC=12: The DLAHQR vs DLAQR0 crossover point. +* Default: 75. (Must be at least 11.) +* +* ISPEC=13: Recommended deflation window size. +* This depends on ILO, IHI and NS. NS is the +* number of simultaneous shifts returned +* by ILAENV(ISPEC=15). (See ISPEC=15 below.) +* The default for (IHI-ILO+1).LE.500 is NS. +* The default for (IHI-ILO+1).GT.500 is 3*NS/2. +* +* ISPEC=14: Nibble crossover point. (See IPARMQ for +* details.) Default: 14% of deflation window +* size. +* +* ISPEC=15: Number of simultaneous shifts in a multishift +* QR iteration. +* +* If IHI-ILO+1 is ... +* +* greater than ...but less ... the +* or equal to ... than default is +* +* 1 30 NS = 2(+) +* 30 60 NS = 4(+) +* 60 150 NS = 10(+) +* 150 590 NS = ** +* 590 3000 NS = 64 +* 3000 6000 NS = 128 +* 6000 infinity NS = 256 +* +* (+) By default some or all matrices of this order +* are passed to the implicit double shift routine +* DLAHQR and this parameter is ignored. See +* ISPEC=12 above and comments in IPARMQ for +* details. +* +* (**) The asterisks (**) indicate an ad-hoc +* function of N increasing from 10 to 64. +* +* ISPEC=16: Select structured matrix multiply. +* If the number of simultaneous shifts (specified +* by ISPEC=15) is less than 14, then the default +* for ISPEC=16 is 0. Otherwise the default for +* ISPEC=16 is 2. +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* References: +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 +* Performance, SIAM Journal of Matrix Analysis, volume 23, pages +* 929--947, 2002. +* +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part II: Aggressive Early Deflation, SIAM Journal +* of Matrix Analysis, volume 23, pages 948--973, 2002. +* +* ================================================================ +* .. Parameters .. +* +* ==== Matrices of order NTINY or smaller must be processed by +* . DLAHQR because of insufficient subdiagonal scratch space. +* . (This is a hard limit.) ==== + INTEGER NTINY + PARAMETER ( NTINY = 11 ) +* +* ==== NL allocates some local workspace to help small matrices +* . through a rare DLAHQR failure. NL .GT. NTINY = 11 is +* . required and NL .LE. NMIN = ILAENV(ISPEC=12,...) is recom- +* . mended. (The default value of NMIN is 75.) Using NL = 49 +* . allows up to six simultaneous shifts and a 16-by-16 +* . deflation window. ==== + INTEGER NL + PARAMETER ( NL = 49 ) + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Arrays .. + DOUBLE PRECISION HL( NL, NL ), WORKL( NL ) +* .. +* .. Local Scalars .. + INTEGER I, KBOT, NMIN + LOGICAL INITZ, LQUERY, WANTT, WANTZ +* .. +* .. External Functions .. + INTEGER ILAENV + LOGICAL LSAME + EXTERNAL ILAENV, LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLACPY, DLAHQR, DLAQR0, DLASET, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, MAX, MIN +* .. +* .. Executable Statements .. +* +* ==== Decode and check the input parameters. ==== +* + WANTT = LSAME( JOB, 'S' ) + INITZ = LSAME( COMPZ, 'I' ) + WANTZ = INITZ .OR. LSAME( COMPZ, 'V' ) + WORK( 1 ) = DBLE( MAX( 1, N ) ) + LQUERY = LWORK.EQ.-1 +* + INFO = 0 + IF( .NOT.LSAME( JOB, 'E' ) .AND. .NOT.WANTT ) THEN + INFO = -1 + ELSE IF( .NOT.LSAME( COMPZ, 'N' ) .AND. .NOT.WANTZ ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN + INFO = -5 + ELSE IF( LDH.LT.MAX( 1, N ) ) THEN + INFO = -7 + ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.MAX( 1, N ) ) ) THEN + INFO = -11 + ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -13 + END IF +* + IF( INFO.NE.0 ) THEN +* +* ==== Quick return in case of invalid argument. ==== +* + CALL XERBLA( 'DHSEQR', -INFO ) + RETURN +* + ELSE IF( N.EQ.0 ) THEN +* +* ==== Quick return in case N = 0; nothing to do. ==== +* + RETURN +* + ELSE IF( LQUERY ) THEN +* +* ==== Quick return in case of a workspace query ==== +* + CALL DLAQR0( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, ILO, + $ IHI, Z, LDZ, WORK, LWORK, INFO ) +* ==== Ensure reported workspace size is backward-compatible with +* . previous LAPACK versions. ==== + WORK( 1 ) = MAX( DBLE( MAX( 1, N ) ), WORK( 1 ) ) + RETURN +* + ELSE +* +* ==== copy eigenvalues isolated by DGEBAL ==== +* + DO 10 I = 1, ILO - 1 + WR( I ) = H( I, I ) + WI( I ) = ZERO + 10 CONTINUE + DO 20 I = IHI + 1, N + WR( I ) = H( I, I ) + WI( I ) = ZERO + 20 CONTINUE +* +* ==== Initialize Z, if requested ==== +* + IF( INITZ ) + $ CALL DLASET( 'A', N, N, ZERO, ONE, Z, LDZ ) +* +* ==== Quick return if possible ==== +* + IF( ILO.EQ.IHI ) THEN + WR( ILO ) = H( ILO, ILO ) + WI( ILO ) = ZERO + RETURN + END IF +* +* ==== DLAHQR/DLAQR0 crossover point ==== +* + NMIN = ILAENV( 12, 'DHSEQR', JOB( : 1 ) // COMPZ( : 1 ), N, + $ ILO, IHI, LWORK ) + NMIN = MAX( NTINY, NMIN ) +* +* ==== DLAQR0 for big matrices; DLAHQR for small ones ==== +* + IF( N.GT.NMIN ) THEN + CALL DLAQR0( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, ILO, + $ IHI, Z, LDZ, WORK, LWORK, INFO ) + ELSE +* +* ==== Small matrix ==== +* + CALL DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, ILO, + $ IHI, Z, LDZ, INFO ) +* + IF( INFO.GT.0 ) THEN +* +* ==== A rare DLAHQR failure! DLAQR0 sometimes succeeds +* . when DLAHQR fails. ==== +* + KBOT = INFO +* + IF( N.GE.NL ) THEN +* +* ==== Larger matrices have enough subdiagonal scratch +* . space to call DLAQR0 directly. ==== +* + CALL DLAQR0( WANTT, WANTZ, N, ILO, KBOT, H, LDH, WR, + $ WI, ILO, IHI, Z, LDZ, WORK, LWORK, INFO ) +* + ELSE +* +* ==== Tiny matrices don't have enough subdiagonal +* . scratch space to benefit from DLAQR0. Hence, +* . tiny matrices must be copied into a larger +* . array before calling DLAQR0. ==== +* + CALL DLACPY( 'A', N, N, H, LDH, HL, NL ) + HL( N+1, N ) = ZERO + CALL DLASET( 'A', NL, NL-N, ZERO, ZERO, HL( 1, N+1 ), + $ NL ) + CALL DLAQR0( WANTT, WANTZ, NL, ILO, KBOT, HL, NL, WR, + $ WI, ILO, IHI, Z, LDZ, WORKL, NL, INFO ) + IF( WANTT .OR. INFO.NE.0 ) + $ CALL DLACPY( 'A', N, N, HL, NL, H, LDH ) + END IF + END IF + END IF +* +* ==== Clear out the trash, if necessary. ==== +* + IF( ( WANTT .OR. INFO.NE.0 ) .AND. N.GT.2 ) + $ CALL DLASET( 'L', N-2, N-2, ZERO, ZERO, H( 3, 1 ), LDH ) +* +* ==== Ensure reported workspace size is backward-compatible with +* . previous LAPACK versions. ==== +* + WORK( 1 ) = MAX( DBLE( MAX( 1, N ) ), WORK( 1 ) ) + END IF +* +* ==== End of DHSEQR ==== +* + END + diff --git a/dep/lapack/disnan.f b/dep/lapack/disnan.f new file mode 100644 index 00000000..cbe58abd --- /dev/null +++ b/dep/lapack/disnan.f @@ -0,0 +1,34 @@ + LOGICAL FUNCTION DISNAN( DIN ) +* +* -- LAPACK auxiliary routine (version 3.2.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* June 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN +* .. +* +* Purpose +* ======= +* +* DISNAN returns .TRUE. if its argument is NaN, and .FALSE. +* otherwise. To be replaced by the Fortran 2003 intrinsic in the +* future. +* +* Arguments +* ========= +* +* DIN (input) DOUBLE PRECISION +* Input to test for NaN. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL DLAISNAN + EXTERNAL DLAISNAN +* .. +* .. Executable Statements .. + DISNAN = DLAISNAN(DIN,DIN) + RETURN + END diff --git a/dep/lapack/dlabad.f b/dep/lapack/dlabad.f new file mode 100644 index 00000000..1f453d22 --- /dev/null +++ b/dep/lapack/dlabad.f @@ -0,0 +1,56 @@ + SUBROUTINE DLABAD( SMALL, LARGE ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + DOUBLE PRECISION LARGE, SMALL +* .. +* +* Purpose +* ======= +* +* DLABAD takes as input the values computed by SLAMCH for underflow and +* overflow, and returns the square root of each of these values if the +* log of LARGE is sufficiently large. This subroutine is intended to +* identify machines with a large exponent range, such as the Crays, and +* redefine the underflow and overflow limits to be the square roots of +* the values computed by DLAMCH. This subroutine is needed because +* DLAMCH does not compensate for poor arithmetic in the upper half of +* the exponent range, as is found on a Cray. +* +* Arguments +* ========= +* +* SMALL (input/output) DOUBLE PRECISION +* On entry, the underflow threshold as computed by DLAMCH. +* On exit, if LOG10(LARGE) is sufficiently large, the square +* root of SMALL, otherwise unchanged. +* +* LARGE (input/output) DOUBLE PRECISION +* On entry, the overflow threshold as computed by DLAMCH. +* On exit, if LOG10(LARGE) is sufficiently large, the square +* root of LARGE, otherwise unchanged. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LOG10, SQRT +* .. +* .. Executable Statements .. +* +* If it looks like we're on a Cray, take the square root of +* SMALL and LARGE to avoid overflow and underflow problems. +* + IF( LOG10( LARGE ).GT.2000.D0 ) THEN + SMALL = SQRT( SMALL ) + LARGE = SQRT( LARGE ) + END IF +* + RETURN +* +* End of DLABAD +* + END diff --git a/dep/lapack/dlabrd.f b/dep/lapack/dlabrd.f new file mode 100644 index 00000000..0a153af1 --- /dev/null +++ b/dep/lapack/dlabrd.f @@ -0,0 +1,291 @@ + SUBROUTINE DLABRD( M, N, NB, A, LDA, D, E, TAUQ, TAUP, X, LDX, Y, + $ LDY ) +* +* -- LAPACK auxiliary routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER LDA, LDX, LDY, M, N, NB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAUP( * ), + $ TAUQ( * ), X( LDX, * ), Y( LDY, * ) +* .. +* +* Purpose +* ======= +* +* DLABRD reduces the first NB rows and columns of a real general +* m by n matrix A to upper or lower bidiagonal form by an orthogonal +* transformation Q**T * A * P, and returns the matrices X and Y which +* are needed to apply the transformation to the unreduced part of A. +* +* If m >= n, A is reduced to upper bidiagonal form; if m < n, to lower +* bidiagonal form. +* +* This is an auxiliary routine called by DGEBRD +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows in the matrix A. +* +* N (input) INTEGER +* The number of columns in the matrix A. +* +* NB (input) INTEGER +* The number of leading rows and columns of A to be reduced. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the m by n general matrix to be reduced. +* On exit, the first NB rows and columns of the matrix are +* overwritten; the rest of the array is unchanged. +* If m >= n, elements on and below the diagonal in the first NB +* columns, with the array TAUQ, represent the orthogonal +* matrix Q as a product of elementary reflectors; and +* elements above the diagonal in the first NB rows, with the +* array TAUP, represent the orthogonal matrix P as a product +* of elementary reflectors. +* If m < n, elements below the diagonal in the first NB +* columns, with the array TAUQ, represent the orthogonal +* matrix Q as a product of elementary reflectors, and +* elements on and above the diagonal in the first NB rows, +* with the array TAUP, represent the orthogonal matrix P as +* a product of elementary reflectors. +* See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* D (output) DOUBLE PRECISION array, dimension (NB) +* The diagonal elements of the first NB rows and columns of +* the reduced matrix. D(i) = A(i,i). +* +* E (output) DOUBLE PRECISION array, dimension (NB) +* The off-diagonal elements of the first NB rows and columns of +* the reduced matrix. +* +* TAUQ (output) DOUBLE PRECISION array dimension (NB) +* The scalar factors of the elementary reflectors which +* represent the orthogonal matrix Q. See Further Details. +* +* TAUP (output) DOUBLE PRECISION array, dimension (NB) +* The scalar factors of the elementary reflectors which +* represent the orthogonal matrix P. See Further Details. +* +* X (output) DOUBLE PRECISION array, dimension (LDX,NB) +* The m-by-nb matrix X required to update the unreduced part +* of A. +* +* LDX (input) INTEGER +* The leading dimension of the array X. LDX >= max(1,M). +* +* Y (output) DOUBLE PRECISION array, dimension (LDY,NB) +* The n-by-nb matrix Y required to update the unreduced part +* of A. +* +* LDY (input) INTEGER +* The leading dimension of the array Y. LDY >= max(1,N). +* +* Further Details +* =============== +* +* The matrices Q and P are represented as products of elementary +* reflectors: +* +* Q = H(1) H(2) . . . H(nb) and P = G(1) G(2) . . . G(nb) +* +* Each H(i) and G(i) has the form: +* +* H(i) = I - tauq * v * v**T and G(i) = I - taup * u * u**T +* +* where tauq and taup are real scalars, and v and u are real vectors. +* +* If m >= n, v(1:i-1) = 0, v(i) = 1, and v(i:m) is stored on exit in +* A(i:m,i); u(1:i) = 0, u(i+1) = 1, and u(i+1:n) is stored on exit in +* A(i,i+1:n); tauq is stored in TAUQ(i) and taup in TAUP(i). +* +* If m < n, v(1:i) = 0, v(i+1) = 1, and v(i+1:m) is stored on exit in +* A(i+2:m,i); u(1:i-1) = 0, u(i) = 1, and u(i:n) is stored on exit in +* A(i,i+1:n); tauq is stored in TAUQ(i) and taup in TAUP(i). +* +* The elements of the vectors v and u together form the m-by-nb matrix +* V and the nb-by-n matrix U**T which are needed, with X and Y, to apply +* the transformation to the unreduced part of the matrix, using a block +* update of the form: A := A - V*Y**T - X*U**T. +* +* The contents of A on exit are illustrated by the following examples +* with nb = 2: +* +* m = 6 and n = 5 (m > n): m = 5 and n = 6 (m < n): +* +* ( 1 1 u1 u1 u1 ) ( 1 u1 u1 u1 u1 u1 ) +* ( v1 1 1 u2 u2 ) ( 1 1 u2 u2 u2 u2 ) +* ( v1 v2 a a a ) ( v1 1 a a a a ) +* ( v1 v2 a a a ) ( v1 v2 a a a a ) +* ( v1 v2 a a a ) ( v1 v2 a a a a ) +* ( v1 v2 a a a ) +* +* where a denotes an element of the original matrix which is unchanged, +* vi denotes an element of the vector defining H(i), and ui an element +* of the vector defining G(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DLARFG, DSCAL +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( M.LE.0 .OR. N.LE.0 ) + $ RETURN +* + IF( M.GE.N ) THEN +* +* Reduce to upper bidiagonal form +* + DO 10 I = 1, NB +* +* Update A(i:m,i) +* + CALL DGEMV( 'No transpose', M-I+1, I-1, -ONE, A( I, 1 ), + $ LDA, Y( I, 1 ), LDY, ONE, A( I, I ), 1 ) + CALL DGEMV( 'No transpose', M-I+1, I-1, -ONE, X( I, 1 ), + $ LDX, A( 1, I ), 1, ONE, A( I, I ), 1 ) +* +* Generate reflection Q(i) to annihilate A(i+1:m,i) +* + CALL DLARFG( M-I+1, A( I, I ), A( MIN( I+1, M ), I ), 1, + $ TAUQ( I ) ) + D( I ) = A( I, I ) + IF( I.LT.N ) THEN + A( I, I ) = ONE +* +* Compute Y(i+1:n,i) +* + CALL DGEMV( 'Transpose', M-I+1, N-I, ONE, A( I, I+1 ), + $ LDA, A( I, I ), 1, ZERO, Y( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', M-I+1, I-1, ONE, A( I, 1 ), LDA, + $ A( I, I ), 1, ZERO, Y( 1, I ), 1 ) + CALL DGEMV( 'No transpose', N-I, I-1, -ONE, Y( I+1, 1 ), + $ LDY, Y( 1, I ), 1, ONE, Y( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', M-I+1, I-1, ONE, X( I, 1 ), LDX, + $ A( I, I ), 1, ZERO, Y( 1, I ), 1 ) + CALL DGEMV( 'Transpose', I-1, N-I, -ONE, A( 1, I+1 ), + $ LDA, Y( 1, I ), 1, ONE, Y( I+1, I ), 1 ) + CALL DSCAL( N-I, TAUQ( I ), Y( I+1, I ), 1 ) +* +* Update A(i,i+1:n) +* + CALL DGEMV( 'No transpose', N-I, I, -ONE, Y( I+1, 1 ), + $ LDY, A( I, 1 ), LDA, ONE, A( I, I+1 ), LDA ) + CALL DGEMV( 'Transpose', I-1, N-I, -ONE, A( 1, I+1 ), + $ LDA, X( I, 1 ), LDX, ONE, A( I, I+1 ), LDA ) +* +* Generate reflection P(i) to annihilate A(i,i+2:n) +* + CALL DLARFG( N-I, A( I, I+1 ), A( I, MIN( I+2, N ) ), + $ LDA, TAUP( I ) ) + E( I ) = A( I, I+1 ) + A( I, I+1 ) = ONE +* +* Compute X(i+1:m,i) +* + CALL DGEMV( 'No transpose', M-I, N-I, ONE, A( I+1, I+1 ), + $ LDA, A( I, I+1 ), LDA, ZERO, X( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-I, I, ONE, Y( I+1, 1 ), LDY, + $ A( I, I+1 ), LDA, ZERO, X( 1, I ), 1 ) + CALL DGEMV( 'No transpose', M-I, I, -ONE, A( I+1, 1 ), + $ LDA, X( 1, I ), 1, ONE, X( I+1, I ), 1 ) + CALL DGEMV( 'No transpose', I-1, N-I, ONE, A( 1, I+1 ), + $ LDA, A( I, I+1 ), LDA, ZERO, X( 1, I ), 1 ) + CALL DGEMV( 'No transpose', M-I, I-1, -ONE, X( I+1, 1 ), + $ LDX, X( 1, I ), 1, ONE, X( I+1, I ), 1 ) + CALL DSCAL( M-I, TAUP( I ), X( I+1, I ), 1 ) + END IF + 10 CONTINUE + ELSE +* +* Reduce to lower bidiagonal form +* + DO 20 I = 1, NB +* +* Update A(i,i:n) +* + CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, Y( I, 1 ), + $ LDY, A( I, 1 ), LDA, ONE, A( I, I ), LDA ) + CALL DGEMV( 'Transpose', I-1, N-I+1, -ONE, A( 1, I ), LDA, + $ X( I, 1 ), LDX, ONE, A( I, I ), LDA ) +* +* Generate reflection P(i) to annihilate A(i,i+1:n) +* + CALL DLARFG( N-I+1, A( I, I ), A( I, MIN( I+1, N ) ), LDA, + $ TAUP( I ) ) + D( I ) = A( I, I ) + IF( I.LT.M ) THEN + A( I, I ) = ONE +* +* Compute X(i+1:m,i) +* + CALL DGEMV( 'No transpose', M-I, N-I+1, ONE, A( I+1, I ), + $ LDA, A( I, I ), LDA, ZERO, X( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-I+1, I-1, ONE, Y( I, 1 ), LDY, + $ A( I, I ), LDA, ZERO, X( 1, I ), 1 ) + CALL DGEMV( 'No transpose', M-I, I-1, -ONE, A( I+1, 1 ), + $ LDA, X( 1, I ), 1, ONE, X( I+1, I ), 1 ) + CALL DGEMV( 'No transpose', I-1, N-I+1, ONE, A( 1, I ), + $ LDA, A( I, I ), LDA, ZERO, X( 1, I ), 1 ) + CALL DGEMV( 'No transpose', M-I, I-1, -ONE, X( I+1, 1 ), + $ LDX, X( 1, I ), 1, ONE, X( I+1, I ), 1 ) + CALL DSCAL( M-I, TAUP( I ), X( I+1, I ), 1 ) +* +* Update A(i+1:m,i) +* + CALL DGEMV( 'No transpose', M-I, I-1, -ONE, A( I+1, 1 ), + $ LDA, Y( I, 1 ), LDY, ONE, A( I+1, I ), 1 ) + CALL DGEMV( 'No transpose', M-I, I, -ONE, X( I+1, 1 ), + $ LDX, A( 1, I ), 1, ONE, A( I+1, I ), 1 ) +* +* Generate reflection Q(i) to annihilate A(i+2:m,i) +* + CALL DLARFG( M-I, A( I+1, I ), A( MIN( I+2, M ), I ), 1, + $ TAUQ( I ) ) + E( I ) = A( I+1, I ) + A( I+1, I ) = ONE +* +* Compute Y(i+1:n,i) +* + CALL DGEMV( 'Transpose', M-I, N-I, ONE, A( I+1, I+1 ), + $ LDA, A( I+1, I ), 1, ZERO, Y( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', M-I, I-1, ONE, A( I+1, 1 ), LDA, + $ A( I+1, I ), 1, ZERO, Y( 1, I ), 1 ) + CALL DGEMV( 'No transpose', N-I, I-1, -ONE, Y( I+1, 1 ), + $ LDY, Y( 1, I ), 1, ONE, Y( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', M-I, I, ONE, X( I+1, 1 ), LDX, + $ A( I+1, I ), 1, ZERO, Y( 1, I ), 1 ) + CALL DGEMV( 'Transpose', I, N-I, -ONE, A( 1, I+1 ), LDA, + $ Y( 1, I ), 1, ONE, Y( I+1, I ), 1 ) + CALL DSCAL( N-I, TAUQ( I ), Y( I+1, I ), 1 ) + END IF + 20 CONTINUE + END IF + RETURN +* +* End of DLABRD +* + END diff --git a/dep/lapack/dlacon.f b/dep/lapack/dlacon.f new file mode 100644 index 00000000..f0b1e9e7 --- /dev/null +++ b/dep/lapack/dlacon.f @@ -0,0 +1,204 @@ + SUBROUTINE DLACON( N, V, X, ISGN, EST, KASE ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + INTEGER KASE, N + DOUBLE PRECISION EST +* .. +* .. Array Arguments .. + INTEGER ISGN( * ) + DOUBLE PRECISION V( * ), X( * ) +* .. +* +* Purpose +* ======= +* +* DLACON estimates the 1-norm of a square, real matrix A. +* Reverse communication is used for evaluating matrix-vector products. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix. N >= 1. +* +* V (workspace) DOUBLE PRECISION array, dimension (N) +* On the final return, V = A*W, where EST = norm(V)/norm(W) +* (W is not returned). +* +* X (input/output) DOUBLE PRECISION array, dimension (N) +* On an intermediate return, X should be overwritten by +* A * X, if KASE=1, +* A' * X, if KASE=2, +* and DLACON must be re-called with all the other parameters +* unchanged. +* +* ISGN (workspace) INTEGER array, dimension (N) +* +* EST (output) DOUBLE PRECISION +* An estimate (a lower bound) for norm(A). +* +* KASE (input/output) INTEGER +* On the initial call to DLACON, KASE should be 0. +* On an intermediate return, KASE will be 1 or 2, indicating +* whether X should be overwritten by A * X or A' * X. +* On the final return from DLACON, KASE will again be 0. +* +* Further Details +* ======= ======= +* +* Contributed by Nick Higham, University of Manchester. +* Originally named SONEST, dated March 16, 1988. +* +* Reference: N.J. Higham, "FORTRAN codes for estimating the one-norm of +* a real or complex matrix, with applications to condition estimation", +* ACM Trans. Math. Soft., vol. 14, no. 4, pp. 381-396, December 1988. +* +* ===================================================================== +* +* .. Parameters .. + INTEGER ITMAX + PARAMETER ( ITMAX = 5 ) + DOUBLE PRECISION ZERO, ONE, TWO + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, ITER, J, JLAST, JUMP + DOUBLE PRECISION ALTSGN, ESTOLD, TEMP +* .. +* .. External Functions .. + INTEGER IDAMAX + DOUBLE PRECISION DASUM + EXTERNAL IDAMAX, DASUM +* .. +* .. External Subroutines .. + EXTERNAL DCOPY +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, NINT, SIGN +* .. +* .. Save statement .. + SAVE +* .. +* .. Executable Statements .. +* + IF( KASE.EQ.0 ) THEN + DO 10 I = 1, N + X( I ) = ONE / DBLE( N ) + 10 CONTINUE + KASE = 1 + JUMP = 1 + RETURN + END IF +* + GO TO ( 20, 40, 70, 110, 140 )JUMP +* +* ................ ENTRY (JUMP = 1) +* FIRST ITERATION. X HAS BEEN OVERWRITTEN BY A*X. +* + 20 CONTINUE + IF( N.EQ.1 ) THEN + V( 1 ) = X( 1 ) + EST = ABS( V( 1 ) ) +* ... QUIT + GO TO 150 + END IF + EST = DASUM( N, X, 1 ) +* + DO 30 I = 1, N + X( I ) = SIGN( ONE, X( I ) ) + ISGN( I ) = NINT( X( I ) ) + 30 CONTINUE + KASE = 2 + JUMP = 2 + RETURN +* +* ................ ENTRY (JUMP = 2) +* FIRST ITERATION. X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X. +* + 40 CONTINUE + J = IDAMAX( N, X, 1 ) + ITER = 2 +* +* MAIN LOOP - ITERATIONS 2,3,...,ITMAX. +* + 50 CONTINUE + DO 60 I = 1, N + X( I ) = ZERO + 60 CONTINUE + X( J ) = ONE + KASE = 1 + JUMP = 3 + RETURN +* +* ................ ENTRY (JUMP = 3) +* X HAS BEEN OVERWRITTEN BY A*X. +* + 70 CONTINUE + CALL DCOPY( N, X, 1, V, 1 ) + ESTOLD = EST + EST = DASUM( N, V, 1 ) + DO 80 I = 1, N + IF( NINT( SIGN( ONE, X( I ) ) ).NE.ISGN( I ) ) + $ GO TO 90 + 80 CONTINUE +* REPEATED SIGN VECTOR DETECTED, HENCE ALGORITHM HAS CONVERGED. + GO TO 120 +* + 90 CONTINUE +* TEST FOR CYCLING. + IF( EST.LE.ESTOLD ) + $ GO TO 120 +* + DO 100 I = 1, N + X( I ) = SIGN( ONE, X( I ) ) + ISGN( I ) = NINT( X( I ) ) + 100 CONTINUE + KASE = 2 + JUMP = 4 + RETURN +* +* ................ ENTRY (JUMP = 4) +* X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X. +* + 110 CONTINUE + JLAST = J + J = IDAMAX( N, X, 1 ) + IF( ( X( JLAST ).NE.ABS( X( J ) ) ) .AND. ( ITER.LT.ITMAX ) ) THEN + ITER = ITER + 1 + GO TO 50 + END IF +* +* ITERATION COMPLETE. FINAL STAGE. +* + 120 CONTINUE + ALTSGN = ONE + DO 130 I = 1, N + X( I ) = ALTSGN*( ONE+DBLE( I-1 ) / DBLE( N-1 ) ) + ALTSGN = -ALTSGN + 130 CONTINUE + KASE = 1 + JUMP = 5 + RETURN +* +* ................ ENTRY (JUMP = 5) +* X HAS BEEN OVERWRITTEN BY A*X. +* + 140 CONTINUE + TEMP = TWO*( DASUM( N, X, 1 ) / DBLE( 3*N ) ) + IF( TEMP.GT.EST ) THEN + CALL DCOPY( N, X, 1, V, 1 ) + EST = TEMP + END IF +* + 150 CONTINUE + KASE = 0 + RETURN +* +* End of DLACON +* + END diff --git a/dep/lapack/dlacpy.f b/dep/lapack/dlacpy.f new file mode 100644 index 00000000..94694de5 --- /dev/null +++ b/dep/lapack/dlacpy.f @@ -0,0 +1,88 @@ + SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, LDB, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DLACPY copies all or part of a two-dimensional matrix A to another +* matrix B. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies the part of the matrix A to be copied to B. +* = 'U': Upper triangular part +* = 'L': Lower triangular part +* Otherwise: All of the matrix A +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,N) +* The m by n matrix A. If UPLO = 'U', only the upper triangle +* or trapezoid is accessed; if UPLO = 'L', only the lower +* triangle or trapezoid is accessed. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* B (output) DOUBLE PRECISION array, dimension (LDB,N) +* On exit, B = A in the locations specified by UPLO. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,M). +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( LSAME( UPLO, 'U' ) ) THEN + DO 20 J = 1, N + DO 10 I = 1, MIN( J, M ) + B( I, J ) = A( I, J ) + 10 CONTINUE + 20 CONTINUE + ELSE IF( LSAME( UPLO, 'L' ) ) THEN + DO 40 J = 1, N + DO 30 I = J, M + B( I, J ) = A( I, J ) + 30 CONTINUE + 40 CONTINUE + ELSE + DO 60 J = 1, N + DO 50 I = 1, M + B( I, J ) = A( I, J ) + 50 CONTINUE + 60 CONTINUE + END IF + RETURN +* +* End of DLACPY +* + END diff --git a/dep/lapack/dladiv.f b/dep/lapack/dladiv.f new file mode 100644 index 00000000..9a66d341 --- /dev/null +++ b/dep/lapack/dladiv.f @@ -0,0 +1,63 @@ + SUBROUTINE DLADIV( A, B, C, D, P, Q ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B, C, D, P, Q +* .. +* +* Purpose +* ======= +* +* DLADIV performs complex division in real arithmetic +* +* a + i*b +* p + i*q = --------- +* c + i*d +* +* The algorithm is due to Robert L. Smith and can be found +* in D. Knuth, The art of Computer Programming, Vol.2, p.195 +* +* Arguments +* ========= +* +* A (input) DOUBLE PRECISION +* B (input) DOUBLE PRECISION +* C (input) DOUBLE PRECISION +* D (input) DOUBLE PRECISION +* The scalars a, b, c, and d in the above expression. +* +* P (output) DOUBLE PRECISION +* Q (output) DOUBLE PRECISION +* The scalars p and q in the above expression. +* +* ===================================================================== +* +* .. Local Scalars .. + DOUBLE PRECISION E, F +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. +* + IF( ABS( D ).LT.ABS( C ) ) THEN + E = D / C + F = C + D*E + P = ( A+B*E ) / F + Q = ( B-A*E ) / F + ELSE + E = C / D + F = D + C*E + P = ( B+A*E ) / F + Q = ( -A+B*E ) / F + END IF +* + RETURN +* +* End of DLADIV +* + END diff --git a/dep/lapack/dlae2.f b/dep/lapack/dlae2.f new file mode 100644 index 00000000..8e81c608 --- /dev/null +++ b/dep/lapack/dlae2.f @@ -0,0 +1,123 @@ + SUBROUTINE DLAE2( A, B, C, RT1, RT2 ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B, C, RT1, RT2 +* .. +* +* Purpose +* ======= +* +* DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix +* [ A B ] +* [ B C ]. +* On return, RT1 is the eigenvalue of larger absolute value, and RT2 +* is the eigenvalue of smaller absolute value. +* +* Arguments +* ========= +* +* A (input) DOUBLE PRECISION +* The (1,1) element of the 2-by-2 matrix. +* +* B (input) DOUBLE PRECISION +* The (1,2) and (2,1) elements of the 2-by-2 matrix. +* +* C (input) DOUBLE PRECISION +* The (2,2) element of the 2-by-2 matrix. +* +* RT1 (output) DOUBLE PRECISION +* The eigenvalue of larger absolute value. +* +* RT2 (output) DOUBLE PRECISION +* The eigenvalue of smaller absolute value. +* +* Further Details +* =============== +* +* RT1 is accurate to a few ulps barring over/underflow. +* +* RT2 may be inaccurate if there is massive cancellation in the +* determinant A*C-B*B; higher precision or correctly rounded or +* correctly truncated arithmetic would be needed to compute RT2 +* accurately in all cases. +* +* Overflow is possible only if RT1 is within a factor of 5 of overflow. +* Underflow is harmless if the input data is 0 or exceeds +* underflow_threshold / macheps. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION HALF + PARAMETER ( HALF = 0.5D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AB, ACMN, ACMX, ADF, DF, RT, SM, TB +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +* .. +* .. Executable Statements .. +* +* Compute the eigenvalues +* + SM = A + C + DF = A - C + ADF = ABS( DF ) + TB = B + B + AB = ABS( TB ) + IF( ABS( A ).GT.ABS( C ) ) THEN + ACMX = A + ACMN = C + ELSE + ACMX = C + ACMN = A + END IF + IF( ADF.GT.AB ) THEN + RT = ADF*SQRT( ONE+( AB / ADF )**2 ) + ELSE IF( ADF.LT.AB ) THEN + RT = AB*SQRT( ONE+( ADF / AB )**2 ) + ELSE +* +* Includes case AB=ADF=0 +* + RT = AB*SQRT( TWO ) + END IF + IF( SM.LT.ZERO ) THEN + RT1 = HALF*( SM-RT ) +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE IF( SM.GT.ZERO ) THEN + RT1 = HALF*( SM+RT ) +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE +* +* Includes case RT1 = RT2 = 0 +* + RT1 = HALF*RT + RT2 = -HALF*RT + END IF + RETURN +* +* End of DLAE2 +* + END diff --git a/dep/lapack/dlaebz.f b/dep/lapack/dlaebz.f new file mode 100644 index 00000000..dec0c362 --- /dev/null +++ b/dep/lapack/dlaebz.f @@ -0,0 +1,551 @@ + SUBROUTINE DLAEBZ( IJOB, NITMAX, N, MMAX, MINP, NBMIN, ABSTOL, + $ RELTOL, PIVMIN, D, E, E2, NVAL, AB, C, MOUT, + $ NAB, WORK, IWORK, INFO ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER IJOB, INFO, MINP, MMAX, MOUT, N, NBMIN, NITMAX + DOUBLE PRECISION ABSTOL, PIVMIN, RELTOL +* .. +* .. Array Arguments .. + INTEGER IWORK( * ), NAB( MMAX, * ), NVAL( * ) + DOUBLE PRECISION AB( MMAX, * ), C( * ), D( * ), E( * ), E2( * ), + $ WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLAEBZ contains the iteration loops which compute and use the +* function N(w), which is the count of eigenvalues of a symmetric +* tridiagonal matrix T less than or equal to its argument w. It +* performs a choice of two types of loops: +* +* IJOB=1, followed by +* IJOB=2: It takes as input a list of intervals and returns a list of +* sufficiently small intervals whose union contains the same +* eigenvalues as the union of the original intervals. +* The input intervals are (AB(j,1),AB(j,2)], j=1,...,MINP. +* The output interval (AB(j,1),AB(j,2)] will contain +* eigenvalues NAB(j,1)+1,...,NAB(j,2), where 1 <= j <= MOUT. +* +* IJOB=3: It performs a binary search in each input interval +* (AB(j,1),AB(j,2)] for a point w(j) such that +* N(w(j))=NVAL(j), and uses C(j) as the starting point of +* the search. If such a w(j) is found, then on output +* AB(j,1)=AB(j,2)=w. If no such w(j) is found, then on output +* (AB(j,1),AB(j,2)] will be a small interval containing the +* point where N(w) jumps through NVAL(j), unless that point +* lies outside the initial interval. +* +* Note that the intervals are in all cases half-open intervals, +* i.e., of the form (a,b] , which includes b but not a . +* +* To avoid underflow, the matrix should be scaled so that its largest +* element is no greater than overflow**(1/2) * underflow**(1/4) +* in absolute value. To assure the most accurate computation +* of small eigenvalues, the matrix should be scaled to be +* not much smaller than that, either. +* +* See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal +* Matrix", Report CS41, Computer Science Dept., Stanford +* University, July 21, 1966 +* +* Note: the arguments are, in general, *not* checked for unreasonable +* values. +* +* Arguments +* ========= +* +* IJOB (input) INTEGER +* Specifies what is to be done: +* = 1: Compute NAB for the initial intervals. +* = 2: Perform bisection iteration to find eigenvalues of T. +* = 3: Perform bisection iteration to invert N(w), i.e., +* to find a point which has a specified number of +* eigenvalues of T to its left. +* Other values will cause DLAEBZ to return with INFO=-1. +* +* NITMAX (input) INTEGER +* The maximum number of "levels" of bisection to be +* performed, i.e., an interval of width W will not be made +* smaller than 2^(-NITMAX) * W. If not all intervals +* have converged after NITMAX iterations, then INFO is set +* to the number of non-converged intervals. +* +* N (input) INTEGER +* The dimension n of the tridiagonal matrix T. It must be at +* least 1. +* +* MMAX (input) INTEGER +* The maximum number of intervals. If more than MMAX intervals +* are generated, then DLAEBZ will quit with INFO=MMAX+1. +* +* MINP (input) INTEGER +* The initial number of intervals. It may not be greater than +* MMAX. +* +* NBMIN (input) INTEGER +* The smallest number of intervals that should be processed +* using a vector loop. If zero, then only the scalar loop +* will be used. +* +* ABSTOL (input) DOUBLE PRECISION +* The minimum (absolute) width of an interval. When an +* interval is narrower than ABSTOL, or than RELTOL times the +* larger (in magnitude) endpoint, then it is considered to be +* sufficiently small, i.e., converged. This must be at least +* zero. +* +* RELTOL (input) DOUBLE PRECISION +* The minimum relative width of an interval. When an interval +* is narrower than ABSTOL, or than RELTOL times the larger (in +* magnitude) endpoint, then it is considered to be +* sufficiently small, i.e., converged. Note: this should +* always be at least radix*machine epsilon. +* +* PIVMIN (input) DOUBLE PRECISION +* The minimum absolute value of a "pivot" in the Sturm +* sequence loop. This *must* be at least max |e(j)**2| * +* safe_min and at least safe_min, where safe_min is at least +* the smallest number that can divide one without overflow. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The diagonal elements of the tridiagonal matrix T. +* +* E (input) DOUBLE PRECISION array, dimension (N) +* The offdiagonal elements of the tridiagonal matrix T in +* positions 1 through N-1. E(N) is arbitrary. +* +* E2 (input) DOUBLE PRECISION array, dimension (N) +* The squares of the offdiagonal elements of the tridiagonal +* matrix T. E2(N) is ignored. +* +* NVAL (input/output) INTEGER array, dimension (MINP) +* If IJOB=1 or 2, not referenced. +* If IJOB=3, the desired values of N(w). The elements of NVAL +* will be reordered to correspond with the intervals in AB. +* Thus, NVAL(j) on output will not, in general be the same as +* NVAL(j) on input, but it will correspond with the interval +* (AB(j,1),AB(j,2)] on output. +* +* AB (input/output) DOUBLE PRECISION array, dimension (MMAX,2) +* The endpoints of the intervals. AB(j,1) is a(j), the left +* endpoint of the j-th interval, and AB(j,2) is b(j), the +* right endpoint of the j-th interval. The input intervals +* will, in general, be modified, split, and reordered by the +* calculation. +* +* C (input/output) DOUBLE PRECISION array, dimension (MMAX) +* If IJOB=1, ignored. +* If IJOB=2, workspace. +* If IJOB=3, then on input C(j) should be initialized to the +* first search point in the binary search. +* +* MOUT (output) INTEGER +* If IJOB=1, the number of eigenvalues in the intervals. +* If IJOB=2 or 3, the number of intervals output. +* If IJOB=3, MOUT will equal MINP. +* +* NAB (input/output) INTEGER array, dimension (MMAX,2) +* If IJOB=1, then on output NAB(i,j) will be set to N(AB(i,j)). +* If IJOB=2, then on input, NAB(i,j) should be set. It must +* satisfy the condition: +* N(AB(i,1)) <= NAB(i,1) <= NAB(i,2) <= N(AB(i,2)), +* which means that in interval i only eigenvalues +* NAB(i,1)+1,...,NAB(i,2) will be considered. Usually, +* NAB(i,j)=N(AB(i,j)), from a previous call to DLAEBZ with +* IJOB=1. +* On output, NAB(i,j) will contain +* max(na(k),min(nb(k),N(AB(i,j)))), where k is the index of +* the input interval that the output interval +* (AB(j,1),AB(j,2)] came from, and na(k) and nb(k) are the +* the input values of NAB(k,1) and NAB(k,2). +* If IJOB=3, then on output, NAB(i,j) contains N(AB(i,j)), +* unless N(w) > NVAL(i) for all search points w , in which +* case NAB(i,1) will not be modified, i.e., the output +* value will be the same as the input value (modulo +* reorderings -- see NVAL and AB), or unless N(w) < NVAL(i) +* for all search points w , in which case NAB(i,2) will +* not be modified. Normally, NAB should be set to some +* distinctive value(s) before DLAEBZ is called. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (MMAX) +* Workspace. +* +* IWORK (workspace) INTEGER array, dimension (MMAX) +* Workspace. +* +* INFO (output) INTEGER +* = 0: All intervals converged. +* = 1--MMAX: The last INFO intervals did not converge. +* = MMAX+1: More than MMAX intervals were generated. +* +* Further Details +* =============== +* +* This routine is intended to be called only by other LAPACK +* routines, thus the interface is less user-friendly. It is intended +* for two purposes: +* +* (a) finding eigenvalues. In this case, DLAEBZ should have one or +* more initial intervals set up in AB, and DLAEBZ should be called +* with IJOB=1. This sets up NAB, and also counts the eigenvalues. +* Intervals with no eigenvalues would usually be thrown out at +* this point. Also, if not all the eigenvalues in an interval i +* are desired, NAB(i,1) can be increased or NAB(i,2) decreased. +* For example, set NAB(i,1)=NAB(i,2)-1 to get the largest +* eigenvalue. DLAEBZ is then called with IJOB=2 and MMAX +* no smaller than the value of MOUT returned by the call with +* IJOB=1. After this (IJOB=2) call, eigenvalues NAB(i,1)+1 +* through NAB(i,2) are approximately AB(i,1) (or AB(i,2)) to the +* tolerance specified by ABSTOL and RELTOL. +* +* (b) finding an interval (a',b'] containing eigenvalues w(f),...,w(l). +* In this case, start with a Gershgorin interval (a,b). Set up +* AB to contain 2 search intervals, both initially (a,b). One +* NVAL element should contain f-1 and the other should contain l +* , while C should contain a and b, resp. NAB(i,1) should be -1 +* and NAB(i,2) should be N+1, to flag an error if the desired +* interval does not lie in (a,b). DLAEBZ is then called with +* IJOB=3. On exit, if w(f-1) < w(f), then one of the intervals -- +* j -- will have AB(j,1)=AB(j,2) and NAB(j,1)=NAB(j,2)=f-1, while +* if, to the specified tolerance, w(f-k)=...=w(f+r), k > 0 and r +* >= 0, then the interval will have N(AB(j,1))=NAB(j,1)=f-k and +* N(AB(j,2))=NAB(j,2)=f+r. The cases w(l) < w(l+1) and +* w(l-r)=...=w(l+k) are handled similarly. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, TWO, HALF + PARAMETER ( ZERO = 0.0D0, TWO = 2.0D0, + $ HALF = 1.0D0 / TWO ) +* .. +* .. Local Scalars .. + INTEGER ITMP1, ITMP2, J, JI, JIT, JP, KF, KFNEW, KL, + $ KLNEW + DOUBLE PRECISION TMP1, TMP2 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. Executable Statements .. +* +* Check for Errors +* + INFO = 0 + IF( IJOB.LT.1 .OR. IJOB.GT.3 ) THEN + INFO = -1 + RETURN + END IF +* +* Initialize NAB +* + IF( IJOB.EQ.1 ) THEN +* +* Compute the number of eigenvalues in the initial intervals. +* + MOUT = 0 +*DIR$ NOVECTOR + DO 30 JI = 1, MINP + DO 20 JP = 1, 2 + TMP1 = D( 1 ) - AB( JI, JP ) + IF( ABS( TMP1 ).LT.PIVMIN ) + $ TMP1 = -PIVMIN + NAB( JI, JP ) = 0 + IF( TMP1.LE.ZERO ) + $ NAB( JI, JP ) = 1 +* + DO 10 J = 2, N + TMP1 = D( J ) - E2( J-1 ) / TMP1 - AB( JI, JP ) + IF( ABS( TMP1 ).LT.PIVMIN ) + $ TMP1 = -PIVMIN + IF( TMP1.LE.ZERO ) + $ NAB( JI, JP ) = NAB( JI, JP ) + 1 + 10 CONTINUE + 20 CONTINUE + MOUT = MOUT + NAB( JI, 2 ) - NAB( JI, 1 ) + 30 CONTINUE + RETURN + END IF +* +* Initialize for loop +* +* KF and KL have the following meaning: +* Intervals 1,...,KF-1 have converged. +* Intervals KF,...,KL still need to be refined. +* + KF = 1 + KL = MINP +* +* If IJOB=2, initialize C. +* If IJOB=3, use the user-supplied starting point. +* + IF( IJOB.EQ.2 ) THEN + DO 40 JI = 1, MINP + C( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) ) + 40 CONTINUE + END IF +* +* Iteration loop +* + DO 130 JIT = 1, NITMAX +* +* Loop over intervals +* + IF( KL-KF+1.GE.NBMIN .AND. NBMIN.GT.0 ) THEN +* +* Begin of Parallel Version of the loop +* + DO 60 JI = KF, KL +* +* Compute N(c), the number of eigenvalues less than c +* + WORK( JI ) = D( 1 ) - C( JI ) + IWORK( JI ) = 0 + IF( WORK( JI ).LE.PIVMIN ) THEN + IWORK( JI ) = 1 + WORK( JI ) = MIN( WORK( JI ), -PIVMIN ) + END IF +* + DO 50 J = 2, N + WORK( JI ) = D( J ) - E2( J-1 ) / WORK( JI ) - C( JI ) + IF( WORK( JI ).LE.PIVMIN ) THEN + IWORK( JI ) = IWORK( JI ) + 1 + WORK( JI ) = MIN( WORK( JI ), -PIVMIN ) + END IF + 50 CONTINUE + 60 CONTINUE +* + IF( IJOB.LE.2 ) THEN +* +* IJOB=2: Choose all intervals containing eigenvalues. +* + KLNEW = KL + DO 70 JI = KF, KL +* +* Insure that N(w) is monotone +* + IWORK( JI ) = MIN( NAB( JI, 2 ), + $ MAX( NAB( JI, 1 ), IWORK( JI ) ) ) +* +* Update the Queue -- add intervals if both halves +* contain eigenvalues. +* + IF( IWORK( JI ).EQ.NAB( JI, 2 ) ) THEN +* +* No eigenvalue in the upper interval: +* just use the lower interval. +* + AB( JI, 2 ) = C( JI ) +* + ELSE IF( IWORK( JI ).EQ.NAB( JI, 1 ) ) THEN +* +* No eigenvalue in the lower interval: +* just use the upper interval. +* + AB( JI, 1 ) = C( JI ) + ELSE + KLNEW = KLNEW + 1 + IF( KLNEW.LE.MMAX ) THEN +* +* Eigenvalue in both intervals -- add upper to +* queue. +* + AB( KLNEW, 2 ) = AB( JI, 2 ) + NAB( KLNEW, 2 ) = NAB( JI, 2 ) + AB( KLNEW, 1 ) = C( JI ) + NAB( KLNEW, 1 ) = IWORK( JI ) + AB( JI, 2 ) = C( JI ) + NAB( JI, 2 ) = IWORK( JI ) + ELSE + INFO = MMAX + 1 + END IF + END IF + 70 CONTINUE + IF( INFO.NE.0 ) + $ RETURN + KL = KLNEW + ELSE +* +* IJOB=3: Binary search. Keep only the interval containing +* w s.t. N(w) = NVAL +* + DO 80 JI = KF, KL + IF( IWORK( JI ).LE.NVAL( JI ) ) THEN + AB( JI, 1 ) = C( JI ) + NAB( JI, 1 ) = IWORK( JI ) + END IF + IF( IWORK( JI ).GE.NVAL( JI ) ) THEN + AB( JI, 2 ) = C( JI ) + NAB( JI, 2 ) = IWORK( JI ) + END IF + 80 CONTINUE + END IF +* + ELSE +* +* End of Parallel Version of the loop +* +* Begin of Serial Version of the loop +* + KLNEW = KL + DO 100 JI = KF, KL +* +* Compute N(w), the number of eigenvalues less than w +* + TMP1 = C( JI ) + TMP2 = D( 1 ) - TMP1 + ITMP1 = 0 + IF( TMP2.LE.PIVMIN ) THEN + ITMP1 = 1 + TMP2 = MIN( TMP2, -PIVMIN ) + END IF +* +* A series of compiler directives to defeat vectorization +* for the next loop +* +*$PL$ CMCHAR=' ' +CDIR$ NEXTSCALAR +C$DIR SCALAR +CDIR$ NEXT SCALAR +CVD$L NOVECTOR +CDEC$ NOVECTOR +CVD$ NOVECTOR +*VDIR NOVECTOR +*VOCL LOOP,SCALAR +CIBM PREFER SCALAR +*$PL$ CMCHAR='*' +* + DO 90 J = 2, N + TMP2 = D( J ) - E2( J-1 ) / TMP2 - TMP1 + IF( TMP2.LE.PIVMIN ) THEN + ITMP1 = ITMP1 + 1 + TMP2 = MIN( TMP2, -PIVMIN ) + END IF + 90 CONTINUE +* + IF( IJOB.LE.2 ) THEN +* +* IJOB=2: Choose all intervals containing eigenvalues. +* +* Insure that N(w) is monotone +* + ITMP1 = MIN( NAB( JI, 2 ), + $ MAX( NAB( JI, 1 ), ITMP1 ) ) +* +* Update the Queue -- add intervals if both halves +* contain eigenvalues. +* + IF( ITMP1.EQ.NAB( JI, 2 ) ) THEN +* +* No eigenvalue in the upper interval: +* just use the lower interval. +* + AB( JI, 2 ) = TMP1 +* + ELSE IF( ITMP1.EQ.NAB( JI, 1 ) ) THEN +* +* No eigenvalue in the lower interval: +* just use the upper interval. +* + AB( JI, 1 ) = TMP1 + ELSE IF( KLNEW.LT.MMAX ) THEN +* +* Eigenvalue in both intervals -- add upper to queue. +* + KLNEW = KLNEW + 1 + AB( KLNEW, 2 ) = AB( JI, 2 ) + NAB( KLNEW, 2 ) = NAB( JI, 2 ) + AB( KLNEW, 1 ) = TMP1 + NAB( KLNEW, 1 ) = ITMP1 + AB( JI, 2 ) = TMP1 + NAB( JI, 2 ) = ITMP1 + ELSE + INFO = MMAX + 1 + RETURN + END IF + ELSE +* +* IJOB=3: Binary search. Keep only the interval +* containing w s.t. N(w) = NVAL +* + IF( ITMP1.LE.NVAL( JI ) ) THEN + AB( JI, 1 ) = TMP1 + NAB( JI, 1 ) = ITMP1 + END IF + IF( ITMP1.GE.NVAL( JI ) ) THEN + AB( JI, 2 ) = TMP1 + NAB( JI, 2 ) = ITMP1 + END IF + END IF + 100 CONTINUE + KL = KLNEW +* +* End of Serial Version of the loop +* + END IF +* +* Check for convergence +* + KFNEW = KF + DO 110 JI = KF, KL + TMP1 = ABS( AB( JI, 2 )-AB( JI, 1 ) ) + TMP2 = MAX( ABS( AB( JI, 2 ) ), ABS( AB( JI, 1 ) ) ) + IF( TMP1.LT.MAX( ABSTOL, PIVMIN, RELTOL*TMP2 ) .OR. + $ NAB( JI, 1 ).GE.NAB( JI, 2 ) ) THEN +* +* Converged -- Swap with position KFNEW, +* then increment KFNEW +* + IF( JI.GT.KFNEW ) THEN + TMP1 = AB( JI, 1 ) + TMP2 = AB( JI, 2 ) + ITMP1 = NAB( JI, 1 ) + ITMP2 = NAB( JI, 2 ) + AB( JI, 1 ) = AB( KFNEW, 1 ) + AB( JI, 2 ) = AB( KFNEW, 2 ) + NAB( JI, 1 ) = NAB( KFNEW, 1 ) + NAB( JI, 2 ) = NAB( KFNEW, 2 ) + AB( KFNEW, 1 ) = TMP1 + AB( KFNEW, 2 ) = TMP2 + NAB( KFNEW, 1 ) = ITMP1 + NAB( KFNEW, 2 ) = ITMP2 + IF( IJOB.EQ.3 ) THEN + ITMP1 = NVAL( JI ) + NVAL( JI ) = NVAL( KFNEW ) + NVAL( KFNEW ) = ITMP1 + END IF + END IF + KFNEW = KFNEW + 1 + END IF + 110 CONTINUE + KF = KFNEW +* +* Choose Midpoints +* + DO 120 JI = KF, KL + C( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) ) + 120 CONTINUE +* +* If no more intervals to refine, quit. +* + IF( KF.GT.KL ) + $ GO TO 140 + 130 CONTINUE +* +* Converged +* + 140 CONTINUE + INFO = MAX( KL+1-KF, 0 ) + MOUT = KL +* + RETURN +* +* End of DLAEBZ +* + END diff --git a/dep/lapack/dlaev2.f b/dep/lapack/dlaev2.f new file mode 100644 index 00000000..49402faa --- /dev/null +++ b/dep/lapack/dlaev2.f @@ -0,0 +1,169 @@ + SUBROUTINE DLAEV2( A, B, C, RT1, RT2, CS1, SN1 ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B, C, CS1, RT1, RT2, SN1 +* .. +* +* Purpose +* ======= +* +* DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix +* [ A B ] +* [ B C ]. +* On return, RT1 is the eigenvalue of larger absolute value, RT2 is the +* eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right +* eigenvector for RT1, giving the decomposition +* +* [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ] +* [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ]. +* +* Arguments +* ========= +* +* A (input) DOUBLE PRECISION +* The (1,1) element of the 2-by-2 matrix. +* +* B (input) DOUBLE PRECISION +* The (1,2) element and the conjugate of the (2,1) element of +* the 2-by-2 matrix. +* +* C (input) DOUBLE PRECISION +* The (2,2) element of the 2-by-2 matrix. +* +* RT1 (output) DOUBLE PRECISION +* The eigenvalue of larger absolute value. +* +* RT2 (output) DOUBLE PRECISION +* The eigenvalue of smaller absolute value. +* +* CS1 (output) DOUBLE PRECISION +* SN1 (output) DOUBLE PRECISION +* The vector (CS1, SN1) is a unit right eigenvector for RT1. +* +* Further Details +* =============== +* +* RT1 is accurate to a few ulps barring over/underflow. +* +* RT2 may be inaccurate if there is massive cancellation in the +* determinant A*C-B*B; higher precision or correctly rounded or +* correctly truncated arithmetic would be needed to compute RT2 +* accurately in all cases. +* +* CS1 and SN1 are accurate to a few ulps barring over/underflow. +* +* Overflow is possible only if RT1 is within a factor of 5 of overflow. +* Underflow is harmless if the input data is 0 or exceeds +* underflow_threshold / macheps. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION HALF + PARAMETER ( HALF = 0.5D0 ) +* .. +* .. Local Scalars .. + INTEGER SGN1, SGN2 + DOUBLE PRECISION AB, ACMN, ACMX, ACS, ADF, CS, CT, DF, RT, SM, + $ TB, TN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +* .. +* .. Executable Statements .. +* +* Compute the eigenvalues +* + SM = A + C + DF = A - C + ADF = ABS( DF ) + TB = B + B + AB = ABS( TB ) + IF( ABS( A ).GT.ABS( C ) ) THEN + ACMX = A + ACMN = C + ELSE + ACMX = C + ACMN = A + END IF + IF( ADF.GT.AB ) THEN + RT = ADF*SQRT( ONE+( AB / ADF )**2 ) + ELSE IF( ADF.LT.AB ) THEN + RT = AB*SQRT( ONE+( ADF / AB )**2 ) + ELSE +* +* Includes case AB=ADF=0 +* + RT = AB*SQRT( TWO ) + END IF + IF( SM.LT.ZERO ) THEN + RT1 = HALF*( SM-RT ) + SGN1 = -1 +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE IF( SM.GT.ZERO ) THEN + RT1 = HALF*( SM+RT ) + SGN1 = 1 +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE +* +* Includes case RT1 = RT2 = 0 +* + RT1 = HALF*RT + RT2 = -HALF*RT + SGN1 = 1 + END IF +* +* Compute the eigenvector +* + IF( DF.GE.ZERO ) THEN + CS = DF + RT + SGN2 = 1 + ELSE + CS = DF - RT + SGN2 = -1 + END IF + ACS = ABS( CS ) + IF( ACS.GT.AB ) THEN + CT = -TB / CS + SN1 = ONE / SQRT( ONE+CT*CT ) + CS1 = CT*SN1 + ELSE + IF( AB.EQ.ZERO ) THEN + CS1 = ONE + SN1 = ZERO + ELSE + TN = -CS / TB + CS1 = ONE / SQRT( ONE+TN*TN ) + SN1 = TN*CS1 + END IF + END IF + IF( SGN1.EQ.SGN2 ) THEN + TN = CS1 + CS1 = -SN1 + SN1 = TN + END IF + RETURN +* +* End of DLAEV2 +* + END diff --git a/dep/lapack/dlaexc.f b/dep/lapack/dlaexc.f new file mode 100644 index 00000000..18bc67ad --- /dev/null +++ b/dep/lapack/dlaexc.f @@ -0,0 +1,355 @@ + SUBROUTINE DLAEXC( WANTQ, N, T, LDT, Q, LDQ, J1, N1, N2, WORK, + $ INFO ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + LOGICAL WANTQ + INTEGER INFO, J1, LDQ, LDT, N, N1, N2 +* .. +* .. Array Arguments .. + DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLAEXC swaps adjacent diagonal blocks T11 and T22 of order 1 or 2 in +* an upper quasi-triangular matrix T by an orthogonal similarity +* transformation. +* +* T must be in Schur canonical form, that is, block upper triangular +* with 1-by-1 and 2-by-2 diagonal blocks; each 2-by-2 diagonal block +* has its diagonal elemnts equal and its off-diagonal elements of +* opposite sign. +* +* Arguments +* ========= +* +* WANTQ (input) LOGICAL +* = .TRUE. : accumulate the transformation in the matrix Q; +* = .FALSE.: do not accumulate the transformation. +* +* N (input) INTEGER +* The order of the matrix T. N >= 0. +* +* T (input/output) DOUBLE PRECISION array, dimension (LDT,N) +* On entry, the upper quasi-triangular matrix T, in Schur +* canonical form. +* On exit, the updated matrix T, again in Schur canonical form. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= max(1,N). +* +* Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N) +* On entry, if WANTQ is .TRUE., the orthogonal matrix Q. +* On exit, if WANTQ is .TRUE., the updated matrix Q. +* If WANTQ is .FALSE., Q is not referenced. +* +* LDQ (input) INTEGER +* The leading dimension of the array Q. +* LDQ >= 1; and if WANTQ is .TRUE., LDQ >= N. +* +* J1 (input) INTEGER +* The index of the first row of the first block T11. +* +* N1 (input) INTEGER +* The order of the first block T11. N1 = 0, 1 or 2. +* +* N2 (input) INTEGER +* The order of the second block T22. N2 = 0, 1 or 2. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* = 1: the transformed matrix T would be too far from Schur +* form; the blocks are not swapped and T and Q are +* unchanged. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) + DOUBLE PRECISION TEN + PARAMETER ( TEN = 1.0D+1 ) + INTEGER LDD, LDX + PARAMETER ( LDD = 4, LDX = 2 ) +* .. +* .. Local Scalars .. + INTEGER IERR, J2, J3, J4, K, ND + DOUBLE PRECISION CS, DNORM, EPS, SCALE, SMLNUM, SN, T11, T22, + $ T33, TAU, TAU1, TAU2, TEMP, THRESH, WI1, WI2, + $ WR1, WR2, XNORM +* .. +* .. Local Arrays .. + DOUBLE PRECISION D( LDD, 4 ), U( 3 ), U1( 3 ), U2( 3 ), + $ X( LDX, 2 ) +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLANGE + EXTERNAL DLAMCH, DLANGE +* .. +* .. External Subroutines .. + EXTERNAL DLACPY, DLANV2, DLARFG, DLARFX, DLARTG, DLASY2, + $ DROT +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. +* .. Executable Statements .. +* + INFO = 0 +* +* Quick return if possible +* + IF( N.EQ.0 .OR. N1.EQ.0 .OR. N2.EQ.0 ) + $ RETURN + IF( J1+N1.GT.N ) + $ RETURN +* + J2 = J1 + 1 + J3 = J1 + 2 + J4 = J1 + 3 +* + IF( N1.EQ.1 .AND. N2.EQ.1 ) THEN +* +* Swap two 1-by-1 blocks. +* + T11 = T( J1, J1 ) + T22 = T( J2, J2 ) +* +* Determine the transformation to perform the interchange. +* + CALL DLARTG( T( J1, J2 ), T22-T11, CS, SN, TEMP ) +* +* Apply transformation to the matrix T. +* + IF( J3.LE.N ) + $ CALL DROT( N-J1-1, T( J1, J3 ), LDT, T( J2, J3 ), LDT, CS, + $ SN ) + CALL DROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN ) +* + T( J1, J1 ) = T22 + T( J2, J2 ) = T11 +* + IF( WANTQ ) THEN +* +* Accumulate transformation in the matrix Q. +* + CALL DROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN ) + END IF +* + ELSE +* +* Swapping involves at least one 2-by-2 block. +* +* Copy the diagonal block of order N1+N2 to the local array D +* and compute its norm. +* + ND = N1 + N2 + CALL DLACPY( 'Full', ND, ND, T( J1, J1 ), LDT, D, LDD ) + DNORM = DLANGE( 'Max', ND, ND, D, LDD, WORK ) +* +* Compute machine-dependent threshold for test for accepting +* swap. +* + EPS = DLAMCH( 'P' ) + SMLNUM = DLAMCH( 'S' ) / EPS + THRESH = MAX( TEN*EPS*DNORM, SMLNUM ) +* +* Solve T11*X - X*T22 = scale*T12 for X. +* + CALL DLASY2( .FALSE., .FALSE., -1, N1, N2, D, LDD, + $ D( N1+1, N1+1 ), LDD, D( 1, N1+1 ), LDD, SCALE, X, + $ LDX, XNORM, IERR ) +* +* Swap the adjacent diagonal blocks. +* + K = N1 + N1 + N2 - 3 + GO TO ( 10, 20, 30 )K +* + 10 CONTINUE +* +* N1 = 1, N2 = 2: generate elementary reflector H so that: +* +* ( scale, X11, X12 ) H = ( 0, 0, * ) +* + U( 1 ) = SCALE + U( 2 ) = X( 1, 1 ) + U( 3 ) = X( 1, 2 ) + CALL DLARFG( 3, U( 3 ), U, 1, TAU ) + U( 3 ) = ONE + T11 = T( J1, J1 ) +* +* Perform swap provisionally on diagonal block in D. +* + CALL DLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK ) + CALL DLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK ) +* +* Test whether to reject swap. +* + IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 3, + $ 3 )-T11 ) ).GT.THRESH )GO TO 50 +* +* Accept swap: apply transformation to the entire matrix T. +* + CALL DLARFX( 'L', 3, N-J1+1, U, TAU, T( J1, J1 ), LDT, WORK ) + CALL DLARFX( 'R', J2, 3, U, TAU, T( 1, J1 ), LDT, WORK ) +* + T( J3, J1 ) = ZERO + T( J3, J2 ) = ZERO + T( J3, J3 ) = T11 +* + IF( WANTQ ) THEN +* +* Accumulate transformation in the matrix Q. +* + CALL DLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK ) + END IF + GO TO 40 +* + 20 CONTINUE +* +* N1 = 2, N2 = 1: generate elementary reflector H so that: +* +* H ( -X11 ) = ( * ) +* ( -X21 ) = ( 0 ) +* ( scale ) = ( 0 ) +* + U( 1 ) = -X( 1, 1 ) + U( 2 ) = -X( 2, 1 ) + U( 3 ) = SCALE + CALL DLARFG( 3, U( 1 ), U( 2 ), 1, TAU ) + U( 1 ) = ONE + T33 = T( J3, J3 ) +* +* Perform swap provisionally on diagonal block in D. +* + CALL DLARFX( 'L', 3, 3, U, TAU, D, LDD, WORK ) + CALL DLARFX( 'R', 3, 3, U, TAU, D, LDD, WORK ) +* +* Test whether to reject swap. +* + IF( MAX( ABS( D( 2, 1 ) ), ABS( D( 3, 1 ) ), ABS( D( 1, + $ 1 )-T33 ) ).GT.THRESH )GO TO 50 +* +* Accept swap: apply transformation to the entire matrix T. +* + CALL DLARFX( 'R', J3, 3, U, TAU, T( 1, J1 ), LDT, WORK ) + CALL DLARFX( 'L', 3, N-J1, U, TAU, T( J1, J2 ), LDT, WORK ) +* + T( J1, J1 ) = T33 + T( J2, J1 ) = ZERO + T( J3, J1 ) = ZERO +* + IF( WANTQ ) THEN +* +* Accumulate transformation in the matrix Q. +* + CALL DLARFX( 'R', N, 3, U, TAU, Q( 1, J1 ), LDQ, WORK ) + END IF + GO TO 40 +* + 30 CONTINUE +* +* N1 = 2, N2 = 2: generate elementary reflectors H(1) and H(2) so +* that: +* +* H(2) H(1) ( -X11 -X12 ) = ( * * ) +* ( -X21 -X22 ) ( 0 * ) +* ( scale 0 ) ( 0 0 ) +* ( 0 scale ) ( 0 0 ) +* + U1( 1 ) = -X( 1, 1 ) + U1( 2 ) = -X( 2, 1 ) + U1( 3 ) = SCALE + CALL DLARFG( 3, U1( 1 ), U1( 2 ), 1, TAU1 ) + U1( 1 ) = ONE +* + TEMP = -TAU1*( X( 1, 2 )+U1( 2 )*X( 2, 2 ) ) + U2( 1 ) = -TEMP*U1( 2 ) - X( 2, 2 ) + U2( 2 ) = -TEMP*U1( 3 ) + U2( 3 ) = SCALE + CALL DLARFG( 3, U2( 1 ), U2( 2 ), 1, TAU2 ) + U2( 1 ) = ONE +* +* Perform swap provisionally on diagonal block in D. +* + CALL DLARFX( 'L', 3, 4, U1, TAU1, D, LDD, WORK ) + CALL DLARFX( 'R', 4, 3, U1, TAU1, D, LDD, WORK ) + CALL DLARFX( 'L', 3, 4, U2, TAU2, D( 2, 1 ), LDD, WORK ) + CALL DLARFX( 'R', 4, 3, U2, TAU2, D( 1, 2 ), LDD, WORK ) +* +* Test whether to reject swap. +* + IF( MAX( ABS( D( 3, 1 ) ), ABS( D( 3, 2 ) ), ABS( D( 4, 1 ) ), + $ ABS( D( 4, 2 ) ) ).GT.THRESH )GO TO 50 +* +* Accept swap: apply transformation to the entire matrix T. +* + CALL DLARFX( 'L', 3, N-J1+1, U1, TAU1, T( J1, J1 ), LDT, WORK ) + CALL DLARFX( 'R', J4, 3, U1, TAU1, T( 1, J1 ), LDT, WORK ) + CALL DLARFX( 'L', 3, N-J1+1, U2, TAU2, T( J2, J1 ), LDT, WORK ) + CALL DLARFX( 'R', J4, 3, U2, TAU2, T( 1, J2 ), LDT, WORK ) +* + T( J3, J1 ) = ZERO + T( J3, J2 ) = ZERO + T( J4, J1 ) = ZERO + T( J4, J2 ) = ZERO +* + IF( WANTQ ) THEN +* +* Accumulate transformation in the matrix Q. +* + CALL DLARFX( 'R', N, 3, U1, TAU1, Q( 1, J1 ), LDQ, WORK ) + CALL DLARFX( 'R', N, 3, U2, TAU2, Q( 1, J2 ), LDQ, WORK ) + END IF +* + 40 CONTINUE +* + IF( N2.EQ.2 ) THEN +* +* Standardize new 2-by-2 block T11 +* + CALL DLANV2( T( J1, J1 ), T( J1, J2 ), T( J2, J1 ), + $ T( J2, J2 ), WR1, WI1, WR2, WI2, CS, SN ) + CALL DROT( N-J1-1, T( J1, J1+2 ), LDT, T( J2, J1+2 ), LDT, + $ CS, SN ) + CALL DROT( J1-1, T( 1, J1 ), 1, T( 1, J2 ), 1, CS, SN ) + IF( WANTQ ) + $ CALL DROT( N, Q( 1, J1 ), 1, Q( 1, J2 ), 1, CS, SN ) + END IF +* + IF( N1.EQ.2 ) THEN +* +* Standardize new 2-by-2 block T22 +* + J3 = J1 + N2 + J4 = J3 + 1 + CALL DLANV2( T( J3, J3 ), T( J3, J4 ), T( J4, J3 ), + $ T( J4, J4 ), WR1, WI1, WR2, WI2, CS, SN ) + IF( J3+2.LE.N ) + $ CALL DROT( N-J3-1, T( J3, J3+2 ), LDT, T( J4, J3+2 ), + $ LDT, CS, SN ) + CALL DROT( J3-1, T( 1, J3 ), 1, T( 1, J4 ), 1, CS, SN ) + IF( WANTQ ) + $ CALL DROT( N, Q( 1, J3 ), 1, Q( 1, J4 ), 1, CS, SN ) + END IF +* + END IF + RETURN +* +* Exit with INFO = 1 if swap was rejected. +* + 50 CONTINUE + INFO = 1 + RETURN +* +* End of DLAEXC +* + END diff --git a/dep/lapack/dlagtf.f b/dep/lapack/dlagtf.f new file mode 100644 index 00000000..e91357bf --- /dev/null +++ b/dep/lapack/dlagtf.f @@ -0,0 +1,190 @@ + SUBROUTINE DLAGTF( N, A, LAMBDA, B, C, TOL, D, IN, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, N + DOUBLE PRECISION LAMBDA, TOL +* .. +* .. Array Arguments .. + INTEGER IN( * ) + DOUBLE PRECISION A( * ), B( * ), C( * ), D( * ) +* .. +* +* Purpose +* ======= +* +* DLAGTF factorizes the matrix (T - lambda*I), where T is an n by n +* tridiagonal matrix and lambda is a scalar, as +* +* T - lambda*I = PLU, +* +* where P is a permutation matrix, L is a unit lower tridiagonal matrix +* with at most one non-zero sub-diagonal elements per column and U is +* an upper triangular matrix with at most two non-zero super-diagonal +* elements per column. +* +* The factorization is obtained by Gaussian elimination with partial +* pivoting and implicit row scaling. +* +* The parameter LAMBDA is included in the routine so that DLAGTF may +* be used, in conjunction with DLAGTS, to obtain eigenvectors of T by +* inverse iteration. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix T. +* +* A (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, A must contain the diagonal elements of T. +* +* On exit, A is overwritten by the n diagonal elements of the +* upper triangular matrix U of the factorization of T. +* +* LAMBDA (input) DOUBLE PRECISION +* On entry, the scalar lambda. +* +* B (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, B must contain the (n-1) super-diagonal elements of +* T. +* +* On exit, B is overwritten by the (n-1) super-diagonal +* elements of the matrix U of the factorization of T. +* +* C (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, C must contain the (n-1) sub-diagonal elements of +* T. +* +* On exit, C is overwritten by the (n-1) sub-diagonal elements +* of the matrix L of the factorization of T. +* +* TOL (input) DOUBLE PRECISION +* On entry, a relative tolerance used to indicate whether or +* not the matrix (T - lambda*I) is nearly singular. TOL should +* normally be chose as approximately the largest relative error +* in the elements of T. For example, if the elements of T are +* correct to about 4 significant figures, then TOL should be +* set to about 5*10**(-4). If TOL is supplied as less than eps, +* where eps is the relative machine precision, then the value +* eps is used in place of TOL. +* +* D (output) DOUBLE PRECISION array, dimension (N-2) +* On exit, D is overwritten by the (n-2) second super-diagonal +* elements of the matrix U of the factorization of T. +* +* IN (output) INTEGER array, dimension (N) +* On exit, IN contains details of the permutation matrix P. If +* an interchange occurred at the kth step of the elimination, +* then IN(k) = 1, otherwise IN(k) = 0. The element IN(n) +* returns the smallest positive integer j such that +* +* abs( u(j,j) ).le. norm( (T - lambda*I)(j) )*TOL, +* +* where norm( A(j) ) denotes the sum of the absolute values of +* the jth row of the matrix A. If no such j exists then IN(n) +* is returned as zero. If IN(n) is returned as positive, then a +* diagonal element of U is small, indicating that +* (T - lambda*I) is singular or nearly singular, +* +* INFO (output) INTEGER +* = 0 : successful exit +* .lt. 0: if INFO = -k, the kth argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER K + DOUBLE PRECISION EPS, MULT, PIV1, PIV2, SCALE1, SCALE2, TEMP, TL +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DLAGTF', -INFO ) + RETURN + END IF +* + IF( N.EQ.0 ) + $ RETURN +* + A( 1 ) = A( 1 ) - LAMBDA + IN( N ) = 0 + IF( N.EQ.1 ) THEN + IF( A( 1 ).EQ.ZERO ) + $ IN( 1 ) = 1 + RETURN + END IF +* + EPS = DLAMCH( 'Epsilon' ) +* + TL = MAX( TOL, EPS ) + SCALE1 = ABS( A( 1 ) ) + ABS( B( 1 ) ) + DO 10 K = 1, N - 1 + A( K+1 ) = A( K+1 ) - LAMBDA + SCALE2 = ABS( C( K ) ) + ABS( A( K+1 ) ) + IF( K.LT.( N-1 ) ) + $ SCALE2 = SCALE2 + ABS( B( K+1 ) ) + IF( A( K ).EQ.ZERO ) THEN + PIV1 = ZERO + ELSE + PIV1 = ABS( A( K ) ) / SCALE1 + END IF + IF( C( K ).EQ.ZERO ) THEN + IN( K ) = 0 + PIV2 = ZERO + SCALE1 = SCALE2 + IF( K.LT.( N-1 ) ) + $ D( K ) = ZERO + ELSE + PIV2 = ABS( C( K ) ) / SCALE2 + IF( PIV2.LE.PIV1 ) THEN + IN( K ) = 0 + SCALE1 = SCALE2 + C( K ) = C( K ) / A( K ) + A( K+1 ) = A( K+1 ) - C( K )*B( K ) + IF( K.LT.( N-1 ) ) + $ D( K ) = ZERO + ELSE + IN( K ) = 1 + MULT = A( K ) / C( K ) + A( K ) = C( K ) + TEMP = A( K+1 ) + A( K+1 ) = B( K ) - MULT*TEMP + IF( K.LT.( N-1 ) ) THEN + D( K ) = B( K+1 ) + B( K+1 ) = -MULT*D( K ) + END IF + B( K ) = TEMP + C( K ) = MULT + END IF + END IF + IF( ( MAX( PIV1, PIV2 ).LE.TL ) .AND. ( IN( N ).EQ.0 ) ) + $ IN( N ) = K + 10 CONTINUE + IF( ( ABS( A( N ) ).LE.SCALE1*TL ) .AND. ( IN( N ).EQ.0 ) ) + $ IN( N ) = N +* + RETURN +* +* End of DLAGTF +* + END diff --git a/dep/lapack/dlagtm.f b/dep/lapack/dlagtm.f new file mode 100644 index 00000000..dfe7cb45 --- /dev/null +++ b/dep/lapack/dlagtm.f @@ -0,0 +1,191 @@ + SUBROUTINE DLAGTM( TRANS, N, NRHS, ALPHA, DL, D, DU, X, LDX, BETA, + $ B, LDB ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER LDB, LDX, N, NRHS + DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), DL( * ), DU( * ), + $ X( LDX, * ) +* .. +* +* Purpose +* ======= +* +* DLAGTM performs a matrix-vector product of the form +* +* B := alpha * A * X + beta * B +* +* where A is a tridiagonal matrix of order N, B and X are N by NRHS +* matrices, and alpha and beta are real scalars, each of which may be +* 0., 1., or -1. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER +* Specifies the operation applied to A. +* = 'N': No transpose, B := alpha * A * X + beta * B +* = 'T': Transpose, B := alpha * A'* X + beta * B +* = 'C': Conjugate transpose = Transpose +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrices X and B. +* +* ALPHA (input) DOUBLE PRECISION +* The scalar alpha. ALPHA must be 0., 1., or -1.; otherwise, +* it is assumed to be 0. +* +* DL (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) sub-diagonal elements of T. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The diagonal elements of T. +* +* DU (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) super-diagonal elements of T. +* +* X (input) DOUBLE PRECISION array, dimension (LDX,NRHS) +* The N by NRHS matrix X. +* LDX (input) INTEGER +* The leading dimension of the array X. LDX >= max(N,1). +* +* BETA (input) DOUBLE PRECISION +* The scalar beta. BETA must be 0., 1., or -1.; otherwise, +* it is assumed to be 1. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the N by NRHS matrix B. +* On exit, B is overwritten by the matrix expression +* B := alpha * A * X + beta * B. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(N,1). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Executable Statements .. +* + IF( N.EQ.0 ) + $ RETURN +* +* Multiply B by BETA if BETA.NE.1. +* + IF( BETA.EQ.ZERO ) THEN + DO 20 J = 1, NRHS + DO 10 I = 1, N + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE IF( BETA.EQ.-ONE ) THEN + DO 40 J = 1, NRHS + DO 30 I = 1, N + B( I, J ) = -B( I, J ) + 30 CONTINUE + 40 CONTINUE + END IF +* + IF( ALPHA.EQ.ONE ) THEN + IF( LSAME( TRANS, 'N' ) ) THEN +* +* Compute B := B + A*X +* + DO 60 J = 1, NRHS + IF( N.EQ.1 ) THEN + B( 1, J ) = B( 1, J ) + D( 1 )*X( 1, J ) + ELSE + B( 1, J ) = B( 1, J ) + D( 1 )*X( 1, J ) + + $ DU( 1 )*X( 2, J ) + B( N, J ) = B( N, J ) + DL( N-1 )*X( N-1, J ) + + $ D( N )*X( N, J ) + DO 50 I = 2, N - 1 + B( I, J ) = B( I, J ) + DL( I-1 )*X( I-1, J ) + + $ D( I )*X( I, J ) + DU( I )*X( I+1, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE +* +* Compute B := B + A'*X +* + DO 80 J = 1, NRHS + IF( N.EQ.1 ) THEN + B( 1, J ) = B( 1, J ) + D( 1 )*X( 1, J ) + ELSE + B( 1, J ) = B( 1, J ) + D( 1 )*X( 1, J ) + + $ DL( 1 )*X( 2, J ) + B( N, J ) = B( N, J ) + DU( N-1 )*X( N-1, J ) + + $ D( N )*X( N, J ) + DO 70 I = 2, N - 1 + B( I, J ) = B( I, J ) + DU( I-1 )*X( I-1, J ) + + $ D( I )*X( I, J ) + DL( I )*X( I+1, J ) + 70 CONTINUE + END IF + 80 CONTINUE + END IF + ELSE IF( ALPHA.EQ.-ONE ) THEN + IF( LSAME( TRANS, 'N' ) ) THEN +* +* Compute B := B - A*X +* + DO 100 J = 1, NRHS + IF( N.EQ.1 ) THEN + B( 1, J ) = B( 1, J ) - D( 1 )*X( 1, J ) + ELSE + B( 1, J ) = B( 1, J ) - D( 1 )*X( 1, J ) - + $ DU( 1 )*X( 2, J ) + B( N, J ) = B( N, J ) - DL( N-1 )*X( N-1, J ) - + $ D( N )*X( N, J ) + DO 90 I = 2, N - 1 + B( I, J ) = B( I, J ) - DL( I-1 )*X( I-1, J ) - + $ D( I )*X( I, J ) - DU( I )*X( I+1, J ) + 90 CONTINUE + END IF + 100 CONTINUE + ELSE +* +* Compute B := B - A'*X +* + DO 120 J = 1, NRHS + IF( N.EQ.1 ) THEN + B( 1, J ) = B( 1, J ) - D( 1 )*X( 1, J ) + ELSE + B( 1, J ) = B( 1, J ) - D( 1 )*X( 1, J ) - + $ DL( 1 )*X( 2, J ) + B( N, J ) = B( N, J ) - DU( N-1 )*X( N-1, J ) - + $ D( N )*X( N, J ) + DO 110 I = 2, N - 1 + B( I, J ) = B( I, J ) - DU( I-1 )*X( I-1, J ) - + $ D( I )*X( I, J ) - DL( I )*X( I+1, J ) + 110 CONTINUE + END IF + 120 CONTINUE + END IF + END IF + RETURN +* +* End of DLAGTM +* + END diff --git a/dep/lapack/dlagts.f b/dep/lapack/dlagts.f new file mode 100644 index 00000000..2606e23a --- /dev/null +++ b/dep/lapack/dlagts.f @@ -0,0 +1,304 @@ + SUBROUTINE DLAGTS( JOB, N, A, B, C, D, IN, Y, TOL, INFO ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, JOB, N + DOUBLE PRECISION TOL +* .. +* .. Array Arguments .. + INTEGER IN( * ) + DOUBLE PRECISION A( * ), B( * ), C( * ), D( * ), Y( * ) +* .. +* +* Purpose +* ======= +* +* DLAGTS may be used to solve one of the systems of equations +* +* (T - lambda*I)*x = y or (T - lambda*I)'*x = y, +* +* where T is an n by n tridiagonal matrix, for x, following the +* factorization of (T - lambda*I) as +* +* (T - lambda*I) = P*L*U , +* +* by routine DLAGTF. The choice of equation to be solved is +* controlled by the argument JOB, and in each case there is an option +* to perturb zero or very small diagonal elements of U, this option +* being intended for use in applications such as inverse iteration. +* +* Arguments +* ========= +* +* JOB (input) INTEGER +* Specifies the job to be performed by DLAGTS as follows: +* = 1: The equations (T - lambda*I)x = y are to be solved, +* but diagonal elements of U are not to be perturbed. +* = -1: The equations (T - lambda*I)x = y are to be solved +* and, if overflow would otherwise occur, the diagonal +* elements of U are to be perturbed. See argument TOL +* below. +* = 2: The equations (T - lambda*I)'x = y are to be solved, +* but diagonal elements of U are not to be perturbed. +* = -2: The equations (T - lambda*I)'x = y are to be solved +* and, if overflow would otherwise occur, the diagonal +* elements of U are to be perturbed. See argument TOL +* below. +* +* N (input) INTEGER +* The order of the matrix T. +* +* A (input) DOUBLE PRECISION array, dimension (N) +* On entry, A must contain the diagonal elements of U as +* returned from DLAGTF. +* +* B (input) DOUBLE PRECISION array, dimension (N-1) +* On entry, B must contain the first super-diagonal elements of +* U as returned from DLAGTF. +* +* C (input) DOUBLE PRECISION array, dimension (N-1) +* On entry, C must contain the sub-diagonal elements of L as +* returned from DLAGTF. +* +* D (input) DOUBLE PRECISION array, dimension (N-2) +* On entry, D must contain the second super-diagonal elements +* of U as returned from DLAGTF. +* +* IN (input) INTEGER array, dimension (N) +* On entry, IN must contain details of the matrix P as returned +* from DLAGTF. +* +* Y (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the right hand side vector y. +* On exit, Y is overwritten by the solution vector x. +* +* TOL (input/output) DOUBLE PRECISION +* On entry, with JOB .lt. 0, TOL should be the minimum +* perturbation to be made to very small diagonal elements of U. +* TOL should normally be chosen as about eps*norm(U), where eps +* is the relative machine precision, but if TOL is supplied as +* non-positive, then it is reset to eps*max( abs( u(i,j) ) ). +* If JOB .gt. 0 then TOL is not referenced. +* +* On exit, TOL is changed as described above, only if TOL is +* non-positive on entry. Otherwise TOL is unchanged. +* +* INFO (output) INTEGER +* = 0 : successful exit +* .lt. 0: if INFO = -i, the i-th argument had an illegal value +* .gt. 0: overflow would occur when computing the INFO(th) +* element of the solution vector x. This can only occur +* when JOB is supplied as positive and either means +* that a diagonal element of U is very small, or that +* the elements of the right-hand side vector y are very +* large. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER K + DOUBLE PRECISION ABSAK, AK, BIGNUM, EPS, PERT, SFMIN, TEMP +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SIGN +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( ( ABS( JOB ).GT.2 ) .OR. ( JOB.EQ.0 ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLAGTS', -INFO ) + RETURN + END IF +* + IF( N.EQ.0 ) + $ RETURN +* + EPS = DLAMCH( 'Epsilon' ) + SFMIN = DLAMCH( 'Safe minimum' ) + BIGNUM = ONE / SFMIN +* + IF( JOB.LT.0 ) THEN + IF( TOL.LE.ZERO ) THEN + TOL = ABS( A( 1 ) ) + IF( N.GT.1 ) + $ TOL = MAX( TOL, ABS( A( 2 ) ), ABS( B( 1 ) ) ) + DO 10 K = 3, N + TOL = MAX( TOL, ABS( A( K ) ), ABS( B( K-1 ) ), + $ ABS( D( K-2 ) ) ) + 10 CONTINUE + TOL = TOL*EPS + IF( TOL.EQ.ZERO ) + $ TOL = EPS + END IF + END IF +* + IF( ABS( JOB ).EQ.1 ) THEN + DO 20 K = 2, N + IF( IN( K-1 ).EQ.0 ) THEN + Y( K ) = Y( K ) - C( K-1 )*Y( K-1 ) + ELSE + TEMP = Y( K-1 ) + Y( K-1 ) = Y( K ) + Y( K ) = TEMP - C( K-1 )*Y( K ) + END IF + 20 CONTINUE + IF( JOB.EQ.1 ) THEN + DO 30 K = N, 1, -1 + IF( K.LE.N-2 ) THEN + TEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 ) + ELSE IF( K.EQ.N-1 ) THEN + TEMP = Y( K ) - B( K )*Y( K+1 ) + ELSE + TEMP = Y( K ) + END IF + AK = A( K ) + ABSAK = ABS( AK ) + IF( ABSAK.LT.ONE ) THEN + IF( ABSAK.LT.SFMIN ) THEN + IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK ) + $ THEN + INFO = K + RETURN + ELSE + TEMP = TEMP*BIGNUM + AK = AK*BIGNUM + END IF + ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN + INFO = K + RETURN + END IF + END IF + Y( K ) = TEMP / AK + 30 CONTINUE + ELSE + DO 50 K = N, 1, -1 + IF( K.LE.N-2 ) THEN + TEMP = Y( K ) - B( K )*Y( K+1 ) - D( K )*Y( K+2 ) + ELSE IF( K.EQ.N-1 ) THEN + TEMP = Y( K ) - B( K )*Y( K+1 ) + ELSE + TEMP = Y( K ) + END IF + AK = A( K ) + PERT = SIGN( TOL, AK ) + 40 CONTINUE + ABSAK = ABS( AK ) + IF( ABSAK.LT.ONE ) THEN + IF( ABSAK.LT.SFMIN ) THEN + IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK ) + $ THEN + AK = AK + PERT + PERT = 2*PERT + GO TO 40 + ELSE + TEMP = TEMP*BIGNUM + AK = AK*BIGNUM + END IF + ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN + AK = AK + PERT + PERT = 2*PERT + GO TO 40 + END IF + END IF + Y( K ) = TEMP / AK + 50 CONTINUE + END IF + ELSE +* +* Come to here if JOB = 2 or -2 +* + IF( JOB.EQ.2 ) THEN + DO 60 K = 1, N + IF( K.GE.3 ) THEN + TEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 ) + ELSE IF( K.EQ.2 ) THEN + TEMP = Y( K ) - B( K-1 )*Y( K-1 ) + ELSE + TEMP = Y( K ) + END IF + AK = A( K ) + ABSAK = ABS( AK ) + IF( ABSAK.LT.ONE ) THEN + IF( ABSAK.LT.SFMIN ) THEN + IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK ) + $ THEN + INFO = K + RETURN + ELSE + TEMP = TEMP*BIGNUM + AK = AK*BIGNUM + END IF + ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN + INFO = K + RETURN + END IF + END IF + Y( K ) = TEMP / AK + 60 CONTINUE + ELSE + DO 80 K = 1, N + IF( K.GE.3 ) THEN + TEMP = Y( K ) - B( K-1 )*Y( K-1 ) - D( K-2 )*Y( K-2 ) + ELSE IF( K.EQ.2 ) THEN + TEMP = Y( K ) - B( K-1 )*Y( K-1 ) + ELSE + TEMP = Y( K ) + END IF + AK = A( K ) + PERT = SIGN( TOL, AK ) + 70 CONTINUE + ABSAK = ABS( AK ) + IF( ABSAK.LT.ONE ) THEN + IF( ABSAK.LT.SFMIN ) THEN + IF( ABSAK.EQ.ZERO .OR. ABS( TEMP )*SFMIN.GT.ABSAK ) + $ THEN + AK = AK + PERT + PERT = 2*PERT + GO TO 70 + ELSE + TEMP = TEMP*BIGNUM + AK = AK*BIGNUM + END IF + ELSE IF( ABS( TEMP ).GT.ABSAK*BIGNUM ) THEN + AK = AK + PERT + PERT = 2*PERT + GO TO 70 + END IF + END IF + Y( K ) = TEMP / AK + 80 CONTINUE + END IF +* + DO 90 K = N, 2, -1 + IF( IN( K-1 ).EQ.0 ) THEN + Y( K-1 ) = Y( K-1 ) - C( K-1 )*Y( K ) + ELSE + TEMP = Y( K-1 ) + Y( K-1 ) = Y( K ) + Y( K ) = TEMP - C( K-1 )*Y( K ) + END IF + 90 CONTINUE + END IF +* +* End of DLAGTS +* + END diff --git a/dep/lapack/dlahqr.f b/dep/lapack/dlahqr.f new file mode 100644 index 00000000..68332719 --- /dev/null +++ b/dep/lapack/dlahqr.f @@ -0,0 +1,410 @@ + SUBROUTINE DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, + $ ILOZ, IHIZ, Z, LDZ, INFO ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + LOGICAL WANTT, WANTZ + INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), WI( * ), WR( * ), Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DLAHQR is an auxiliary routine called by DHSEQR to update the +* eigenvalues and Schur decomposition already computed by DHSEQR, by +* dealing with the Hessenberg submatrix in rows and columns ILO to IHI. +* +* Arguments +* ========= +* +* WANTT (input) LOGICAL +* = .TRUE. : the full Schur form T is required; +* = .FALSE.: only eigenvalues are required. +* +* WANTZ (input) LOGICAL +* = .TRUE. : the matrix of Schur vectors Z is required; +* = .FALSE.: Schur vectors are not required. +* +* N (input) INTEGER +* The order of the matrix H. N >= 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* It is assumed that H is already upper quasi-triangular in +* rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless +* ILO = 1). DLAHQR works primarily with the Hessenberg +* submatrix in rows and columns ILO to IHI, but applies +* transformations to all of H if WANTT is .TRUE.. +* 1 <= ILO <= max(1,IHI); IHI <= N. +* +* H (input/output) DOUBLE PRECISION array, dimension (LDH,N) +* On entry, the upper Hessenberg matrix H. +* On exit, if WANTT is .TRUE., H is upper quasi-triangular in +* rows and columns ILO:IHI, with any 2-by-2 diagonal blocks in +* standard form. If WANTT is .FALSE., the contents of H are +* unspecified on exit. +* +* LDH (input) INTEGER +* The leading dimension of the array H. LDH >= max(1,N). +* +* WR (output) DOUBLE PRECISION array, dimension (N) +* WI (output) DOUBLE PRECISION array, dimension (N) +* The real and imaginary parts, respectively, of the computed +* eigenvalues ILO to IHI are stored in the corresponding +* elements of WR and WI. If two eigenvalues are computed as a +* complex conjugate pair, they are stored in consecutive +* elements of WR and WI, say the i-th and (i+1)th, with +* WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the +* eigenvalues are stored in the same order as on the diagonal +* of the Schur form returned in H, with WR(i) = H(i,i), and, if +* H(i:i+1,i:i+1) is a 2-by-2 diagonal block, +* WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i). +* +* ILOZ (input) INTEGER +* IHIZ (input) INTEGER +* Specify the rows of Z to which transformations must be +* applied if WANTZ is .TRUE.. +* 1 <= ILOZ <= ILO; IHI <= IHIZ <= N. +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N) +* If WANTZ is .TRUE., on entry Z must contain the current +* matrix Z of transformations accumulated by DHSEQR, and on +* exit Z has been updated; transformations are applied only to +* the submatrix Z(ILOZ:IHIZ,ILO:IHI). +* If WANTZ is .FALSE., Z is not referenced. +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. LDZ >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* > 0: DLAHQR failed to compute all the eigenvalues ILO to IHI +* in a total of 30*(IHI-ILO+1) iterations; if INFO = i, +* elements i+1:ihi of WR and WI contain those eigenvalues +* which have been successfully computed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) + DOUBLE PRECISION DAT1, DAT2 + PARAMETER ( DAT1 = 0.75D+0, DAT2 = -0.4375D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, I1, I2, ITN, ITS, J, K, L, M, NH, NR, NZ + DOUBLE PRECISION CS, H00, H10, H11, H12, H21, H22, H33, H33S, + $ H43H34, H44, H44S, OVFL, S, SMLNUM, SN, SUM, + $ T1, T2, T3, TST1, ULP, UNFL, V1, V2, V3 +* .. +* .. Local Arrays .. + DOUBLE PRECISION V( 3 ), WORK( 1 ) +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLANHS + EXTERNAL DLAMCH, DLANHS +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DLABAD, DLANV2, DLARFG, DROT +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. Executable Statements .. +* + INFO = 0 +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN + IF( ILO.EQ.IHI ) THEN + WR( ILO ) = H( ILO, ILO ) + WI( ILO ) = ZERO + RETURN + END IF +* + NH = IHI - ILO + 1 + NZ = IHIZ - ILOZ + 1 +* +* Set machine-dependent constants for the stopping criterion. +* If norm(H) <= sqrt(OVFL), overflow should not occur. +* + UNFL = DLAMCH( 'Safe minimum' ) + OVFL = ONE / UNFL + CALL DLABAD( UNFL, OVFL ) + ULP = DLAMCH( 'Precision' ) + SMLNUM = UNFL*( NH / ULP ) +* +* I1 and I2 are the indices of the first row and last column of H +* to which transformations must be applied. If eigenvalues only are +* being computed, I1 and I2 are set inside the main loop. +* + IF( WANTT ) THEN + I1 = 1 + I2 = N + END IF +* +* ITN is the total number of QR iterations allowed. +* + ITN = 30*NH +* +* The main loop begins here. I is the loop index and decreases from +* IHI to ILO in steps of 1 or 2. Each iteration of the loop works +* with the active submatrix in rows and columns L to I. +* Eigenvalues I+1 to IHI have already converged. Either L = ILO or +* H(L,L-1) is negligible so that the matrix splits. +* + I = IHI + 10 CONTINUE + L = ILO + IF( I.LT.ILO ) + $ GO TO 150 +* +* Perform QR iterations on rows and columns ILO to I until a +* submatrix of order 1 or 2 splits off at the bottom because a +* subdiagonal element has become negligible. +* + DO 130 ITS = 0, ITN +* +* Look for a single small subdiagonal element. +* + DO 20 K = I, L + 1, -1 + TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) ) + IF( TST1.EQ.ZERO ) + $ TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK ) + IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) ) + $ GO TO 30 + 20 CONTINUE + 30 CONTINUE + L = K + IF( L.GT.ILO ) THEN +* +* H(L,L-1) is negligible +* + H( L, L-1 ) = ZERO + END IF +* +* Exit from loop if a submatrix of order 1 or 2 has split off. +* + IF( L.GE.I-1 ) + $ GO TO 140 +* +* Now the active submatrix is in rows and columns L to I. If +* eigenvalues only are being computed, only the active submatrix +* need be transformed. +* + IF( .NOT.WANTT ) THEN + I1 = L + I2 = I + END IF +* + IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN +* +* Exceptional shift. +* + S = ABS( H( I, I-1 ) ) + ABS( H( I-1, I-2 ) ) + H44 = DAT1*S + H33 = H44 + H43H34 = DAT2*S*S + ELSE +* +* Prepare to use Wilkinson's double shift +* + H44 = H( I, I ) + H33 = H( I-1, I-1 ) + H43H34 = H( I, I-1 )*H( I-1, I ) + END IF +* +* Look for two consecutive small subdiagonal elements. +* + DO 40 M = I - 2, L, -1 +* +* Determine the effect of starting the double-shift QR +* iteration at row M, and see if this would make H(M,M-1) +* negligible. +* + H11 = H( M, M ) + H22 = H( M+1, M+1 ) + H21 = H( M+1, M ) + H12 = H( M, M+1 ) + H44S = H44 - H11 + H33S = H33 - H11 + V1 = ( H33S*H44S-H43H34 ) / H21 + H12 + V2 = H22 - H11 - H33S - H44S + V3 = H( M+2, M+1 ) + S = ABS( V1 ) + ABS( V2 ) + ABS( V3 ) + V1 = V1 / S + V2 = V2 / S + V3 = V3 / S + V( 1 ) = V1 + V( 2 ) = V2 + V( 3 ) = V3 + IF( M.EQ.L ) + $ GO TO 50 + H00 = H( M-1, M-1 ) + H10 = H( M, M-1 ) + TST1 = ABS( V1 )*( ABS( H00 )+ABS( H11 )+ABS( H22 ) ) + IF( ABS( H10 )*( ABS( V2 )+ABS( V3 ) ).LE.ULP*TST1 ) + $ GO TO 50 + 40 CONTINUE + 50 CONTINUE +* +* Double-shift QR step +* + DO 120 K = M, I - 1 +* +* The first iteration of this loop determines a reflection G +* from the vector V and applies it from left and right to H, +* thus creating a nonzero bulge below the subdiagonal. +* +* Each subsequent iteration determines a reflection G to +* restore the Hessenberg form in the (K-1)th column, and thus +* chases the bulge one step toward the bottom of the active +* submatrix. NR is the order of G. +* + NR = MIN( 3, I-K+1 ) + IF( K.GT.M ) + $ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 ) + CALL DLARFG( NR, V( 1 ), V( 2 ), 1, T1 ) + IF( K.GT.M ) THEN + H( K, K-1 ) = V( 1 ) + H( K+1, K-1 ) = ZERO + IF( K.LT.I-1 ) + $ H( K+2, K-1 ) = ZERO + ELSE IF( M.GT.L ) THEN + H( K, K-1 ) = -H( K, K-1 ) + END IF + V2 = V( 2 ) + T2 = T1*V2 + IF( NR.EQ.3 ) THEN + V3 = V( 3 ) + T3 = T1*V3 +* +* Apply G from the left to transform the rows of the matrix +* in columns K to I2. +* + DO 60 J = K, I2 + SUM = H( K, J ) + V2*H( K+1, J ) + V3*H( K+2, J ) + H( K, J ) = H( K, J ) - SUM*T1 + H( K+1, J ) = H( K+1, J ) - SUM*T2 + H( K+2, J ) = H( K+2, J ) - SUM*T3 + 60 CONTINUE +* +* Apply G from the right to transform the columns of the +* matrix in rows I1 to min(K+3,I). +* + DO 70 J = I1, MIN( K+3, I ) + SUM = H( J, K ) + V2*H( J, K+1 ) + V3*H( J, K+2 ) + H( J, K ) = H( J, K ) - SUM*T1 + H( J, K+1 ) = H( J, K+1 ) - SUM*T2 + H( J, K+2 ) = H( J, K+2 ) - SUM*T3 + 70 CONTINUE +* + IF( WANTZ ) THEN +* +* Accumulate transformations in the matrix Z +* + DO 80 J = ILOZ, IHIZ + SUM = Z( J, K ) + V2*Z( J, K+1 ) + V3*Z( J, K+2 ) + Z( J, K ) = Z( J, K ) - SUM*T1 + Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2 + Z( J, K+2 ) = Z( J, K+2 ) - SUM*T3 + 80 CONTINUE + END IF + ELSE IF( NR.EQ.2 ) THEN +* +* Apply G from the left to transform the rows of the matrix +* in columns K to I2. +* + DO 90 J = K, I2 + SUM = H( K, J ) + V2*H( K+1, J ) + H( K, J ) = H( K, J ) - SUM*T1 + H( K+1, J ) = H( K+1, J ) - SUM*T2 + 90 CONTINUE +* +* Apply G from the right to transform the columns of the +* matrix in rows I1 to min(K+3,I). +* + DO 100 J = I1, I + SUM = H( J, K ) + V2*H( J, K+1 ) + H( J, K ) = H( J, K ) - SUM*T1 + H( J, K+1 ) = H( J, K+1 ) - SUM*T2 + 100 CONTINUE +* + IF( WANTZ ) THEN +* +* Accumulate transformations in the matrix Z +* + DO 110 J = ILOZ, IHIZ + SUM = Z( J, K ) + V2*Z( J, K+1 ) + Z( J, K ) = Z( J, K ) - SUM*T1 + Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2 + 110 CONTINUE + END IF + END IF + 120 CONTINUE +* + 130 CONTINUE +* +* Failure to converge in remaining number of iterations +* + INFO = I + RETURN +* + 140 CONTINUE +* + IF( L.EQ.I ) THEN +* +* H(I,I-1) is negligible: one eigenvalue has converged. +* + WR( I ) = H( I, I ) + WI( I ) = ZERO + ELSE IF( L.EQ.I-1 ) THEN +* +* H(I-1,I-2) is negligible: a pair of eigenvalues have converged. +* +* Transform the 2-by-2 submatrix to standard Schur form, +* and compute and store the eigenvalues. +* + CALL DLANV2( H( I-1, I-1 ), H( I-1, I ), H( I, I-1 ), + $ H( I, I ), WR( I-1 ), WI( I-1 ), WR( I ), WI( I ), + $ CS, SN ) +* + IF( WANTT ) THEN +* +* Apply the transformation to the rest of H. +* + IF( I2.GT.I ) + $ CALL DROT( I2-I, H( I-1, I+1 ), LDH, H( I, I+1 ), LDH, + $ CS, SN ) + CALL DROT( I-I1-1, H( I1, I-1 ), 1, H( I1, I ), 1, CS, SN ) + END IF + IF( WANTZ ) THEN +* +* Apply the transformation to Z. +* + CALL DROT( NZ, Z( ILOZ, I-1 ), 1, Z( ILOZ, I ), 1, CS, SN ) + END IF + END IF +* +* Decrement number of remaining iterations, and return to start of +* the main loop with new value of I. +* + ITN = ITN - ITS + I = L - 1 + GO TO 10 +* + 150 CONTINUE + RETURN +* +* End of DLAHQR +* + END diff --git a/dep/lapack/dlahr2.f b/dep/lapack/dlahr2.f new file mode 100644 index 00000000..8d588503 --- /dev/null +++ b/dep/lapack/dlahr2.f @@ -0,0 +1,246 @@ + SUBROUTINE DLAHR2( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY ) +* +* -- LAPACK auxiliary routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2009 -- +* +* .. Scalar Arguments .. + INTEGER K, LDA, LDT, LDY, N, NB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ), + $ Y( LDY, NB ) +* .. +* +* Purpose +* ======= +* +* DLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1) +* matrix A so that elements below the k-th subdiagonal are zero. The +* reduction is performed by an orthogonal similarity transformation +* Q**T * A * Q. The routine returns the matrices V and T which determine +* Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T. +* +* This is an auxiliary routine called by DGEHRD. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. +* +* K (input) INTEGER +* The offset for the reduction. Elements below the k-th +* subdiagonal in the first NB columns are reduced to zero. +* K < N. +* +* NB (input) INTEGER +* The number of columns to be reduced. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N-K+1) +* On entry, the n-by-(n-k+1) general matrix A. +* On exit, the elements on and above the k-th subdiagonal in +* the first NB columns are overwritten with the corresponding +* elements of the reduced matrix; the elements below the k-th +* subdiagonal, with the array TAU, represent the matrix Q as a +* product of elementary reflectors. The other columns of A are +* unchanged. See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* TAU (output) DOUBLE PRECISION array, dimension (NB) +* The scalar factors of the elementary reflectors. See Further +* Details. +* +* T (output) DOUBLE PRECISION array, dimension (LDT,NB) +* The upper triangular matrix T. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= NB. +* +* Y (output) DOUBLE PRECISION array, dimension (LDY,NB) +* The n-by-nb matrix Y. +* +* LDY (input) INTEGER +* The leading dimension of the array Y. LDY >= N. +* +* Further Details +* =============== +* +* The matrix Q is represented as a product of nb elementary reflectors +* +* Q = H(1) H(2) . . . H(nb). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v**T +* +* where tau is a real scalar, and v is a real vector with +* v(1:i+k-1) = 0, v(i+k) = 1; v(i+k+1:n) is stored on exit in +* A(i+k+1:n,i), and tau in TAU(i). +* +* The elements of the vectors v together form the (n-k+1)-by-nb matrix +* V which is needed, with T and Y, to apply the transformation to the +* unreduced part of the matrix, using an update of the form: +* A := (I - V*T*V**T) * (A - Y*V**T). +* +* The contents of A on exit are illustrated by the following example +* with n = 7, k = 3 and nb = 2: +* +* ( a a a a a ) +* ( a a a a a ) +* ( a a a a a ) +* ( h h a a a ) +* ( v1 h a a a ) +* ( v1 v2 a a a ) +* ( v1 v2 a a a ) +* +* where a denotes an element of the original matrix A, h denotes a +* modified element of the upper Hessenberg matrix H, and vi denotes an +* element of the vector defining H(i). +* +* This subroutine is a slight modification of LAPACK-3.0's DLAHRD +* incorporating improvements proposed by Quintana-Orti and Van de +* Gejin. Note that the entries of A(1:K,2:NB) differ from those +* returned by the original LAPACK-3.0's DLAHRD routine. (This +* subroutine is not backward compatible with LAPACK-3.0's DLAHRD.) +* +* References +* ========== +* +* Gregorio Quintana-Orti and Robert van de Geijn, "Improving the +* performance of reduction to Hessenberg form," ACM Transactions on +* Mathematical Software, 32(2):180-194, June 2006. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, + $ ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION EI +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DGEMM, DGEMV, DLACPY, + $ DLARFG, DSCAL, DTRMM, DTRMV +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + DO 10 I = 1, NB + IF( I.GT.1 ) THEN +* +* Update A(K+1:N,I) +* +* Update I-th column of A - Y * V**T +* + CALL DGEMV( 'NO TRANSPOSE', N-K, I-1, -ONE, Y(K+1,1), LDY, + $ A( K+I-1, 1 ), LDA, ONE, A( K+1, I ), 1 ) +* +* Apply I - V * T**T * V**T to this column (call it b) from the +* left, using the last column of T as workspace +* +* Let V = ( V1 ) and b = ( b1 ) (first I-1 rows) +* ( V2 ) ( b2 ) +* +* where V1 is unit lower triangular +* +* w := V1**T * b1 +* + CALL DCOPY( I-1, A( K+1, I ), 1, T( 1, NB ), 1 ) + CALL DTRMV( 'Lower', 'Transpose', 'UNIT', + $ I-1, A( K+1, 1 ), + $ LDA, T( 1, NB ), 1 ) +* +* w := w + V2**T * b2 +* + CALL DGEMV( 'Transpose', N-K-I+1, I-1, + $ ONE, A( K+I, 1 ), + $ LDA, A( K+I, I ), 1, ONE, T( 1, NB ), 1 ) +* +* w := T**T * w +* + CALL DTRMV( 'Upper', 'Transpose', 'NON-UNIT', + $ I-1, T, LDT, + $ T( 1, NB ), 1 ) +* +* b2 := b2 - V2*w +* + CALL DGEMV( 'NO TRANSPOSE', N-K-I+1, I-1, -ONE, + $ A( K+I, 1 ), + $ LDA, T( 1, NB ), 1, ONE, A( K+I, I ), 1 ) +* +* b1 := b1 - V1*w +* + CALL DTRMV( 'Lower', 'NO TRANSPOSE', + $ 'UNIT', I-1, + $ A( K+1, 1 ), LDA, T( 1, NB ), 1 ) + CALL DAXPY( I-1, -ONE, T( 1, NB ), 1, A( K+1, I ), 1 ) +* + A( K+I-1, I-1 ) = EI + END IF +* +* Generate the elementary reflector H(I) to annihilate +* A(K+I+1:N,I) +* + CALL DLARFG( N-K-I+1, A( K+I, I ), A( MIN( K+I+1, N ), I ), 1, + $ TAU( I ) ) + EI = A( K+I, I ) + A( K+I, I ) = ONE +* +* Compute Y(K+1:N,I) +* + CALL DGEMV( 'NO TRANSPOSE', N-K, N-K-I+1, + $ ONE, A( K+1, I+1 ), + $ LDA, A( K+I, I ), 1, ZERO, Y( K+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-K-I+1, I-1, + $ ONE, A( K+I, 1 ), LDA, + $ A( K+I, I ), 1, ZERO, T( 1, I ), 1 ) + CALL DGEMV( 'NO TRANSPOSE', N-K, I-1, -ONE, + $ Y( K+1, 1 ), LDY, + $ T( 1, I ), 1, ONE, Y( K+1, I ), 1 ) + CALL DSCAL( N-K, TAU( I ), Y( K+1, I ), 1 ) +* +* Compute T(1:I,I) +* + CALL DSCAL( I-1, -TAU( I ), T( 1, I ), 1 ) + CALL DTRMV( 'Upper', 'No Transpose', 'NON-UNIT', + $ I-1, T, LDT, + $ T( 1, I ), 1 ) + T( I, I ) = TAU( I ) +* + 10 CONTINUE + A( K+NB, NB ) = EI +* +* Compute Y(1:K,1:NB) +* + CALL DLACPY( 'ALL', K, NB, A( 1, 2 ), LDA, Y, LDY ) + CALL DTRMM( 'RIGHT', 'Lower', 'NO TRANSPOSE', + $ 'UNIT', K, NB, + $ ONE, A( K+1, 1 ), LDA, Y, LDY ) + IF( N.GT.K+NB ) + $ CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', K, + $ NB, N-K-NB, ONE, + $ A( 1, 2+NB ), LDA, A( K+1+NB, 1 ), LDA, ONE, Y, + $ LDY ) + CALL DTRMM( 'RIGHT', 'Upper', 'NO TRANSPOSE', + $ 'NON-UNIT', K, NB, + $ ONE, T, LDT, Y, LDY ) +* + RETURN +* +* End of DLAHR2 +* + END diff --git a/dep/lapack/dlaic1.f b/dep/lapack/dlaic1.f new file mode 100644 index 00000000..36a68b74 --- /dev/null +++ b/dep/lapack/dlaic1.f @@ -0,0 +1,291 @@ + SUBROUTINE DLAIC1( JOB, J, X, SEST, W, GAMMA, SESTPR, S, C ) +* +* -- LAPACK auxiliary routine (version 1.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + INTEGER J, JOB + DOUBLE PRECISION C, GAMMA, S, SEST, SESTPR +* .. +* .. Array Arguments .. + DOUBLE PRECISION W( J ), X( J ) +* .. +* +* Purpose +* ======= +* +* DLAIC1 applies one step of incremental condition estimation in +* its simplest version: +* +* Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j +* lower triangular matrix L, such that +* twonorm(L*x) = sest +* Then DLAIC1 computes sestpr, s, c such that +* the vector +* [ s*x ] +* xhat = [ c ] +* is an approximate singular vector of +* [ L 0 ] +* Lhat = [ w' gamma ] +* in the sense that +* twonorm(Lhat*xhat) = sestpr. +* +* Depending on JOB, an estimate for the largest or smallest singular +* value is computed. +* +* Note that [s c]' and sestpr**2 is an eigenpair of the system +* +* diag(sest*sest, 0) + [alpha gamma] * [ alpha ] +* [ gamma ] +* +* where alpha = x'*w. +* +* Arguments +* ========= +* +* JOB (input) INTEGER +* = 1: an estimate for the largest singular value is computed. +* = 2: an estimate for the smallest singular value is computed. +* +* J (input) INTEGER +* Length of X and W +* +* X (input) DOUBLE PRECISION array, dimension (J) +* The j-vector x. +* +* SEST (input) DOUBLE PRECISION +* Estimated singular value of j by j matrix L +* +* W (input) DOUBLE PRECISION array, dimension (J) +* The j-vector w. +* +* GAMMA (input) DOUBLE PRECISION +* The diagonal element gamma. +* +* SESTPR (output) DOUBLE PRECISION +* Estimated singular value of (j+1) by (j+1) matrix Lhat. +* +* S (output) DOUBLE PRECISION +* Sine needed in forming xhat. +* +* C (output) DOUBLE PRECISION +* Cosine needed in forming xhat. +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0 ) + DOUBLE PRECISION HALF, FOUR + PARAMETER ( HALF = 0.5D0, FOUR = 4.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION ABSALP, ABSEST, ABSGAM, ALPHA, B, COSINE, EPS, + $ NORMA, S1, S2, SINE, T, TEST, TMP, ZETA1, ZETA2 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SIGN, SQRT +* .. +* .. External Functions .. + DOUBLE PRECISION DDOT, DLAMCH + EXTERNAL DDOT, DLAMCH +* .. +* .. Executable Statements .. +* + EPS = DLAMCH( 'Epsilon' ) + ALPHA = DDOT( J, X, 1, W, 1 ) +* + ABSALP = ABS( ALPHA ) + ABSGAM = ABS( GAMMA ) + ABSEST = ABS( SEST ) +* + IF( JOB.EQ.1 ) THEN +* +* Estimating largest singular value +* +* special cases +* + IF( SEST.EQ.ZERO ) THEN + S1 = MAX( ABSGAM, ABSALP ) + IF( S1.EQ.ZERO ) THEN + S = ZERO + C = ONE + SESTPR = ZERO + ELSE + S = ALPHA / S1 + C = GAMMA / S1 + TMP = SQRT( S*S+C*C ) + S = S / TMP + C = C / TMP + SESTPR = S1*TMP + END IF + RETURN + ELSE IF( ABSGAM.LE.EPS*ABSEST ) THEN + S = ONE + C = ZERO + TMP = MAX( ABSEST, ABSALP ) + S1 = ABSEST / TMP + S2 = ABSALP / TMP + SESTPR = TMP*SQRT( S1*S1+S2*S2 ) + RETURN + ELSE IF( ABSALP.LE.EPS*ABSEST ) THEN + S1 = ABSGAM + S2 = ABSEST + IF( S1.LE.S2 ) THEN + S = ONE + C = ZERO + SESTPR = S2 + ELSE + S = ZERO + C = ONE + SESTPR = S1 + END IF + RETURN + ELSE IF( ABSEST.LE.EPS*ABSALP .OR. ABSEST.LE.EPS*ABSGAM ) THEN + S1 = ABSGAM + S2 = ABSALP + IF( S1.LE.S2 ) THEN + TMP = S1 / S2 + S = SQRT( ONE+TMP*TMP ) + SESTPR = S2*S + C = ( GAMMA / S2 ) / S + S = SIGN( ONE, ALPHA ) / S + ELSE + TMP = S2 / S1 + C = SQRT( ONE+TMP*TMP ) + SESTPR = S1*C + S = ( ALPHA / S1 ) / C + C = SIGN( ONE, GAMMA ) / C + END IF + RETURN + ELSE +* +* normal case +* + ZETA1 = ALPHA / ABSEST + ZETA2 = GAMMA / ABSEST +* + B = ( ONE-ZETA1*ZETA1-ZETA2*ZETA2 )*HALF + C = ZETA1*ZETA1 + IF( B.GT.ZERO ) THEN + T = C / ( B+SQRT( B*B+C ) ) + ELSE + T = SQRT( B*B+C ) - B + END IF +* + SINE = -ZETA1 / T + COSINE = -ZETA2 / ( ONE+T ) + TMP = SQRT( SINE*SINE+COSINE*COSINE ) + S = SINE / TMP + C = COSINE / TMP + SESTPR = SQRT( T+ONE )*ABSEST + RETURN + END IF +* + ELSE IF( JOB.EQ.2 ) THEN +* +* Estimating smallest singular value +* +* special cases +* + IF( SEST.EQ.ZERO ) THEN + SESTPR = ZERO + IF( MAX( ABSGAM, ABSALP ).EQ.ZERO ) THEN + SINE = ONE + COSINE = ZERO + ELSE + SINE = -GAMMA + COSINE = ALPHA + END IF + S1 = MAX( ABS( SINE ), ABS( COSINE ) ) + S = SINE / S1 + C = COSINE / S1 + TMP = SQRT( S*S+C*C ) + S = S / TMP + C = C / TMP + RETURN + ELSE IF( ABSGAM.LE.EPS*ABSEST ) THEN + S = ZERO + C = ONE + SESTPR = ABSGAM + RETURN + ELSE IF( ABSALP.LE.EPS*ABSEST ) THEN + S1 = ABSGAM + S2 = ABSEST + IF( S1.LE.S2 ) THEN + S = ZERO + C = ONE + SESTPR = S1 + ELSE + S = ONE + C = ZERO + SESTPR = S2 + END IF + RETURN + ELSE IF( ABSEST.LE.EPS*ABSALP .OR. ABSEST.LE.EPS*ABSGAM ) THEN + S1 = ABSGAM + S2 = ABSALP + IF( S1.LE.S2 ) THEN + TMP = S1 / S2 + C = SQRT( ONE+TMP*TMP ) + SESTPR = ABSEST*( TMP / C ) + S = -( GAMMA / S2 ) / C + C = SIGN( ONE, ALPHA ) / C + ELSE + TMP = S2 / S1 + S = SQRT( ONE+TMP*TMP ) + SESTPR = ABSEST / S + C = ( ALPHA / S1 ) / S + S = -SIGN( ONE, GAMMA ) / S + END IF + RETURN + ELSE +* +* normal case +* + ZETA1 = ALPHA / ABSEST + ZETA2 = GAMMA / ABSEST +* + NORMA = MAX( ONE+ZETA1*ZETA1+ABS( ZETA1*ZETA2 ), + $ ABS( ZETA1*ZETA2 )+ZETA2*ZETA2 ) +* +* See if root is closer to zero or to ONE +* + TEST = ONE + TWO*( ZETA1-ZETA2 )*( ZETA1+ZETA2 ) + IF( TEST.GE.ZERO ) THEN +* +* root is close to zero, compute directly +* + B = ( ZETA1*ZETA1+ZETA2*ZETA2+ONE )*HALF + C = ZETA2*ZETA2 + T = C / ( B+SQRT( ABS( B*B-C ) ) ) + SINE = ZETA1 / ( ONE-T ) + COSINE = -ZETA2 / T + SESTPR = SQRT( T+FOUR*EPS*EPS*NORMA )*ABSEST + ELSE +* +* root is closer to ONE, shift by that amount +* + B = ( ZETA2*ZETA2+ZETA1*ZETA1-ONE )*HALF + C = ZETA1*ZETA1 + IF( B.GE.ZERO ) THEN + T = -C / ( B+SQRT( B*B+C ) ) + ELSE + T = B - SQRT( B*B+C ) + END IF + SINE = -ZETA1 / T + COSINE = -ZETA2 / ( ONE+T ) + SESTPR = SQRT( ONE+T+FOUR*EPS*EPS*NORMA )*ABSEST + END IF + TMP = SQRT( SINE*SINE+COSINE*COSINE ) + S = SINE / TMP + C = COSINE / TMP + RETURN +* + END IF + END IF + RETURN +* +* End of DLAIC1 +* + END diff --git a/dep/lapack/dlaisnan.f b/dep/lapack/dlaisnan.f new file mode 100644 index 00000000..6c358b96 --- /dev/null +++ b/dep/lapack/dlaisnan.f @@ -0,0 +1,42 @@ + LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* -- LAPACK auxiliary routine (version 3.2.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* June 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN1, DIN2 +* .. +* +* Purpose +* ======= +* +* This routine is not for general use. It exists solely to avoid +* over-optimization in DISNAN. +* +* DLAISNAN checks for NaNs by comparing its two arguments for +* inequality. NaN is the only floating-point value where NaN != NaN +* returns .TRUE. To check for NaNs, pass the same variable as both +* arguments. +* +* A compiler must assume that the two arguments are +* not the same variable, and the test will not be optimized away. +* Interprocedural or whole-program optimization may delete this +* test. The ISNAN functions will be replaced by the correct +* Fortran 03 intrinsic once the intrinsic is widely available. +* +* Arguments +* ========= +* +* DIN1 (input) DOUBLE PRECISION +* +* DIN2 (input) DOUBLE PRECISION +* Two numbers to compare for inequality. +* +* ===================================================================== +* +* .. Executable Statements .. + DLAISNAN = (DIN1.NE.DIN2) + RETURN + END diff --git a/dep/lapack/dlaln2.f b/dep/lapack/dlaln2.f new file mode 100644 index 00000000..18bd8e99 --- /dev/null +++ b/dep/lapack/dlaln2.f @@ -0,0 +1,508 @@ + SUBROUTINE DLALN2( LTRANS, NA, NW, SMIN, CA, A, LDA, D1, D2, B, + $ LDB, WR, WI, X, LDX, SCALE, XNORM, INFO ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + LOGICAL LTRANS + INTEGER INFO, LDA, LDB, LDX, NA, NW + DOUBLE PRECISION CA, D1, D2, SCALE, SMIN, WI, WR, XNORM +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ), X( LDX, * ) +* .. +* +* Purpose +* ======= +* +* DLALN2 solves a system of the form (ca A - w D ) X = s B +* or (ca A' - w D) X = s B with possible scaling ("s") and +* perturbation of A. (A' means A-transpose.) +* +* A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA +* real diagonal matrix, w is a real or complex value, and X and B are +* NA x 1 matrices -- real if w is real, complex if w is complex. NA +* may be 1 or 2. +* +* If w is complex, X and B are represented as NA x 2 matrices, +* the first column of each being the real part and the second +* being the imaginary part. +* +* "s" is a scaling factor (.LE. 1), computed by DLALN2, which is +* so chosen that X can be computed without overflow. X is further +* scaled if necessary to assure that norm(ca A - w D)*norm(X) is less +* than overflow. +* +* If both singular values of (ca A - w D) are less than SMIN, +* SMIN*identity will be used instead of (ca A - w D). If only one +* singular value is less than SMIN, one element of (ca A - w D) will be +* perturbed enough to make the smallest singular value roughly SMIN. +* If both singular values are at least SMIN, (ca A - w D) will not be +* perturbed. In any case, the perturbation will be at most some small +* multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values +* are computed by infinity-norm approximations, and thus will only be +* correct to a factor of 2 or so. +* +* Note: all input quantities are assumed to be smaller than overflow +* by a reasonable factor. (See BIGNUM.) +* +* Arguments +* ========== +* +* LTRANS (input) LOGICAL +* =.TRUE.: A-transpose will be used. +* =.FALSE.: A will be used (not transposed.) +* +* NA (input) INTEGER +* The size of the matrix A. It may (only) be 1 or 2. +* +* NW (input) INTEGER +* 1 if "w" is real, 2 if "w" is complex. It may only be 1 +* or 2. +* +* SMIN (input) DOUBLE PRECISION +* The desired lower bound on the singular values of A. This +* should be a safe distance away from underflow or overflow, +* say, between (underflow/machine precision) and (machine +* precision * overflow ). (See BIGNUM and ULP.) +* +* CA (input) DOUBLE PRECISION +* The coefficient c, which A is multiplied by. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,NA) +* The NA x NA matrix A. +* +* LDA (input) INTEGER +* The leading dimension of A. It must be at least NA. +* +* D1 (input) DOUBLE PRECISION +* The 1,1 element in the diagonal matrix D. +* +* D2 (input) DOUBLE PRECISION +* The 2,2 element in the diagonal matrix D. Not used if NW=1. +* +* B (input) DOUBLE PRECISION array, dimension (LDB,NW) +* The NA x NW matrix B (right-hand side). If NW=2 ("w" is +* complex), column 1 contains the real part of B and column 2 +* contains the imaginary part. +* +* LDB (input) INTEGER +* The leading dimension of B. It must be at least NA. +* +* WR (input) DOUBLE PRECISION +* The real part of the scalar "w". +* +* WI (input) DOUBLE PRECISION +* The imaginary part of the scalar "w". Not used if NW=1. +* +* X (output) DOUBLE PRECISION array, dimension (LDX,NW) +* The NA x NW matrix X (unknowns), as computed by DLALN2. +* If NW=2 ("w" is complex), on exit, column 1 will contain +* the real part of X and column 2 will contain the imaginary +* part. +* +* LDX (input) INTEGER +* The leading dimension of X. It must be at least NA. +* +* SCALE (output) DOUBLE PRECISION +* The scale factor that B must be multiplied by to insure +* that overflow does not occur when computing X. Thus, +* (ca A - w D) X will be SCALE*B, not B (ignoring +* perturbations of A.) It will be at most 1. +* +* XNORM (output) DOUBLE PRECISION +* The infinity-norm of X, when X is regarded as an NA x NW +* real matrix. +* +* INFO (output) INTEGER +* An error flag. It will be set to zero if no error occurs, +* a negative number if an argument is in error, or a positive +* number if ca A - w D had to be perturbed. +* The possible values are: +* = 0: No error occurred, and (ca A - w D) did not have to be +* perturbed. +* = 1: (ca A - w D) had to be perturbed to make its smallest +* (or only) singular value greater than SMIN. +* NOTE: In the interests of speed, this routine does not +* check the inputs for errors. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) +* .. +* .. Local Scalars .. + INTEGER ICMAX, J + DOUBLE PRECISION BBND, BI1, BI2, BIGNUM, BNORM, BR1, BR2, CI21, + $ CI22, CMAX, CNORM, CR21, CR22, CSI, CSR, LI21, + $ LR21, SMINI, SMLNUM, TEMP, U22ABS, UI11, UI11R, + $ UI12, UI12S, UI22, UR11, UR11R, UR12, UR12S, + $ UR22, XI1, XI2, XR1, XR2 +* .. +* .. Local Arrays .. + LOGICAL RSWAP( 4 ), ZSWAP( 4 ) + INTEGER IPIVOT( 4, 4 ) + DOUBLE PRECISION CI( 2, 2 ), CIV( 4 ), CR( 2, 2 ), CRV( 4 ) +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DLADIV +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. +* .. Equivalences .. + EQUIVALENCE ( CI( 1, 1 ), CIV( 1 ) ), + $ ( CR( 1, 1 ), CRV( 1 ) ) +* .. +* .. Data statements .. + DATA ZSWAP / .FALSE., .FALSE., .TRUE., .TRUE. / + DATA RSWAP / .FALSE., .TRUE., .FALSE., .TRUE. / + DATA IPIVOT / 1, 2, 3, 4, 2, 1, 4, 3, 3, 4, 1, 2, 4, + $ 3, 2, 1 / +* .. +* .. Executable Statements .. +* +* Compute BIGNUM +* + SMLNUM = TWO*DLAMCH( 'Safe minimum' ) + BIGNUM = ONE / SMLNUM + SMINI = MAX( SMIN, SMLNUM ) +* +* Don't check for input errors +* + INFO = 0 +* +* Standard Initializations +* + SCALE = ONE +* + IF( NA.EQ.1 ) THEN +* +* 1 x 1 (i.e., scalar) system C X = B +* + IF( NW.EQ.1 ) THEN +* +* Real 1x1 system. +* +* C = ca A - w D +* + CSR = CA*A( 1, 1 ) - WR*D1 + CNORM = ABS( CSR ) +* +* If | C | < SMINI, use C = SMINI +* + IF( CNORM.LT.SMINI ) THEN + CSR = SMINI + CNORM = SMINI + INFO = 1 + END IF +* +* Check scaling for X = B / C +* + BNORM = ABS( B( 1, 1 ) ) + IF( CNORM.LT.ONE .AND. BNORM.GT.ONE ) THEN + IF( BNORM.GT.BIGNUM*CNORM ) + $ SCALE = ONE / BNORM + END IF +* +* Compute X +* + X( 1, 1 ) = ( B( 1, 1 )*SCALE ) / CSR + XNORM = ABS( X( 1, 1 ) ) + ELSE +* +* Complex 1x1 system (w is complex) +* +* C = ca A - w D +* + CSR = CA*A( 1, 1 ) - WR*D1 + CSI = -WI*D1 + CNORM = ABS( CSR ) + ABS( CSI ) +* +* If | C | < SMINI, use C = SMINI +* + IF( CNORM.LT.SMINI ) THEN + CSR = SMINI + CSI = ZERO + CNORM = SMINI + INFO = 1 + END IF +* +* Check scaling for X = B / C +* + BNORM = ABS( B( 1, 1 ) ) + ABS( B( 1, 2 ) ) + IF( CNORM.LT.ONE .AND. BNORM.GT.ONE ) THEN + IF( BNORM.GT.BIGNUM*CNORM ) + $ SCALE = ONE / BNORM + END IF +* +* Compute X +* + CALL DLADIV( SCALE*B( 1, 1 ), SCALE*B( 1, 2 ), CSR, CSI, + $ X( 1, 1 ), X( 1, 2 ) ) + XNORM = ABS( X( 1, 1 ) ) + ABS( X( 1, 2 ) ) + END IF +* + ELSE +* +* 2x2 System +* +* Compute the real part of C = ca A - w D (or ca A' - w D ) +* + CR( 1, 1 ) = CA*A( 1, 1 ) - WR*D1 + CR( 2, 2 ) = CA*A( 2, 2 ) - WR*D2 + IF( LTRANS ) THEN + CR( 1, 2 ) = CA*A( 2, 1 ) + CR( 2, 1 ) = CA*A( 1, 2 ) + ELSE + CR( 2, 1 ) = CA*A( 2, 1 ) + CR( 1, 2 ) = CA*A( 1, 2 ) + END IF +* + IF( NW.EQ.1 ) THEN +* +* Real 2x2 system (w is real) +* +* Find the largest element in C +* + CMAX = ZERO + ICMAX = 0 +* + DO 10 J = 1, 4 + IF( ABS( CRV( J ) ).GT.CMAX ) THEN + CMAX = ABS( CRV( J ) ) + ICMAX = J + END IF + 10 CONTINUE +* +* If norm(C) < SMINI, use SMINI*identity. +* + IF( CMAX.LT.SMINI ) THEN + BNORM = MAX( ABS( B( 1, 1 ) ), ABS( B( 2, 1 ) ) ) + IF( SMINI.LT.ONE .AND. BNORM.GT.ONE ) THEN + IF( BNORM.GT.BIGNUM*SMINI ) + $ SCALE = ONE / BNORM + END IF + TEMP = SCALE / SMINI + X( 1, 1 ) = TEMP*B( 1, 1 ) + X( 2, 1 ) = TEMP*B( 2, 1 ) + XNORM = TEMP*BNORM + INFO = 1 + RETURN + END IF +* +* Gaussian elimination with complete pivoting. +* + UR11 = CRV( ICMAX ) + CR21 = CRV( IPIVOT( 2, ICMAX ) ) + UR12 = CRV( IPIVOT( 3, ICMAX ) ) + CR22 = CRV( IPIVOT( 4, ICMAX ) ) + UR11R = ONE / UR11 + LR21 = UR11R*CR21 + UR22 = CR22 - UR12*LR21 +* +* If smaller pivot < SMINI, use SMINI +* + IF( ABS( UR22 ).LT.SMINI ) THEN + UR22 = SMINI + INFO = 1 + END IF + IF( RSWAP( ICMAX ) ) THEN + BR1 = B( 2, 1 ) + BR2 = B( 1, 1 ) + ELSE + BR1 = B( 1, 1 ) + BR2 = B( 2, 1 ) + END IF + BR2 = BR2 - LR21*BR1 + BBND = MAX( ABS( BR1*( UR22*UR11R ) ), ABS( BR2 ) ) + IF( BBND.GT.ONE .AND. ABS( UR22 ).LT.ONE ) THEN + IF( BBND.GE.BIGNUM*ABS( UR22 ) ) + $ SCALE = ONE / BBND + END IF +* + XR2 = ( BR2*SCALE ) / UR22 + XR1 = ( SCALE*BR1 )*UR11R - XR2*( UR11R*UR12 ) + IF( ZSWAP( ICMAX ) ) THEN + X( 1, 1 ) = XR2 + X( 2, 1 ) = XR1 + ELSE + X( 1, 1 ) = XR1 + X( 2, 1 ) = XR2 + END IF + XNORM = MAX( ABS( XR1 ), ABS( XR2 ) ) +* +* Further scaling if norm(A) norm(X) > overflow +* + IF( XNORM.GT.ONE .AND. CMAX.GT.ONE ) THEN + IF( XNORM.GT.BIGNUM / CMAX ) THEN + TEMP = CMAX / BIGNUM + X( 1, 1 ) = TEMP*X( 1, 1 ) + X( 2, 1 ) = TEMP*X( 2, 1 ) + XNORM = TEMP*XNORM + SCALE = TEMP*SCALE + END IF + END IF + ELSE +* +* Complex 2x2 system (w is complex) +* +* Find the largest element in C +* + CI( 1, 1 ) = -WI*D1 + CI( 2, 1 ) = ZERO + CI( 1, 2 ) = ZERO + CI( 2, 2 ) = -WI*D2 + CMAX = ZERO + ICMAX = 0 +* + DO 20 J = 1, 4 + IF( ABS( CRV( J ) )+ABS( CIV( J ) ).GT.CMAX ) THEN + CMAX = ABS( CRV( J ) ) + ABS( CIV( J ) ) + ICMAX = J + END IF + 20 CONTINUE +* +* If norm(C) < SMINI, use SMINI*identity. +* + IF( CMAX.LT.SMINI ) THEN + BNORM = MAX( ABS( B( 1, 1 ) )+ABS( B( 1, 2 ) ), + $ ABS( B( 2, 1 ) )+ABS( B( 2, 2 ) ) ) + IF( SMINI.LT.ONE .AND. BNORM.GT.ONE ) THEN + IF( BNORM.GT.BIGNUM*SMINI ) + $ SCALE = ONE / BNORM + END IF + TEMP = SCALE / SMINI + X( 1, 1 ) = TEMP*B( 1, 1 ) + X( 2, 1 ) = TEMP*B( 2, 1 ) + X( 1, 2 ) = TEMP*B( 1, 2 ) + X( 2, 2 ) = TEMP*B( 2, 2 ) + XNORM = TEMP*BNORM + INFO = 1 + RETURN + END IF +* +* Gaussian elimination with complete pivoting. +* + UR11 = CRV( ICMAX ) + UI11 = CIV( ICMAX ) + CR21 = CRV( IPIVOT( 2, ICMAX ) ) + CI21 = CIV( IPIVOT( 2, ICMAX ) ) + UR12 = CRV( IPIVOT( 3, ICMAX ) ) + UI12 = CIV( IPIVOT( 3, ICMAX ) ) + CR22 = CRV( IPIVOT( 4, ICMAX ) ) + CI22 = CIV( IPIVOT( 4, ICMAX ) ) + IF( ICMAX.EQ.1 .OR. ICMAX.EQ.4 ) THEN +* +* Code when off-diagonals of pivoted C are real +* + IF( ABS( UR11 ).GT.ABS( UI11 ) ) THEN + TEMP = UI11 / UR11 + UR11R = ONE / ( UR11*( ONE+TEMP**2 ) ) + UI11R = -TEMP*UR11R + ELSE + TEMP = UR11 / UI11 + UI11R = -ONE / ( UI11*( ONE+TEMP**2 ) ) + UR11R = -TEMP*UI11R + END IF + LR21 = CR21*UR11R + LI21 = CR21*UI11R + UR12S = UR12*UR11R + UI12S = UR12*UI11R + UR22 = CR22 - UR12*LR21 + UI22 = CI22 - UR12*LI21 + ELSE +* +* Code when diagonals of pivoted C are real +* + UR11R = ONE / UR11 + UI11R = ZERO + LR21 = CR21*UR11R + LI21 = CI21*UR11R + UR12S = UR12*UR11R + UI12S = UI12*UR11R + UR22 = CR22 - UR12*LR21 + UI12*LI21 + UI22 = -UR12*LI21 - UI12*LR21 + END IF + U22ABS = ABS( UR22 ) + ABS( UI22 ) +* +* If smaller pivot < SMINI, use SMINI +* + IF( U22ABS.LT.SMINI ) THEN + UR22 = SMINI + UI22 = ZERO + INFO = 1 + END IF + IF( RSWAP( ICMAX ) ) THEN + BR2 = B( 1, 1 ) + BR1 = B( 2, 1 ) + BI2 = B( 1, 2 ) + BI1 = B( 2, 2 ) + ELSE + BR1 = B( 1, 1 ) + BR2 = B( 2, 1 ) + BI1 = B( 1, 2 ) + BI2 = B( 2, 2 ) + END IF + BR2 = BR2 - LR21*BR1 + LI21*BI1 + BI2 = BI2 - LI21*BR1 - LR21*BI1 + BBND = MAX( ( ABS( BR1 )+ABS( BI1 ) )* + $ ( U22ABS*( ABS( UR11R )+ABS( UI11R ) ) ), + $ ABS( BR2 )+ABS( BI2 ) ) + IF( BBND.GT.ONE .AND. U22ABS.LT.ONE ) THEN + IF( BBND.GE.BIGNUM*U22ABS ) THEN + SCALE = ONE / BBND + BR1 = SCALE*BR1 + BI1 = SCALE*BI1 + BR2 = SCALE*BR2 + BI2 = SCALE*BI2 + END IF + END IF +* + CALL DLADIV( BR2, BI2, UR22, UI22, XR2, XI2 ) + XR1 = UR11R*BR1 - UI11R*BI1 - UR12S*XR2 + UI12S*XI2 + XI1 = UI11R*BR1 + UR11R*BI1 - UI12S*XR2 - UR12S*XI2 + IF( ZSWAP( ICMAX ) ) THEN + X( 1, 1 ) = XR2 + X( 2, 1 ) = XR1 + X( 1, 2 ) = XI2 + X( 2, 2 ) = XI1 + ELSE + X( 1, 1 ) = XR1 + X( 2, 1 ) = XR2 + X( 1, 2 ) = XI1 + X( 2, 2 ) = XI2 + END IF + XNORM = MAX( ABS( XR1 )+ABS( XI1 ), ABS( XR2 )+ABS( XI2 ) ) +* +* Further scaling if norm(A) norm(X) > overflow +* + IF( XNORM.GT.ONE .AND. CMAX.GT.ONE ) THEN + IF( XNORM.GT.BIGNUM / CMAX ) THEN + TEMP = CMAX / BIGNUM + X( 1, 1 ) = TEMP*X( 1, 1 ) + X( 2, 1 ) = TEMP*X( 2, 1 ) + X( 1, 2 ) = TEMP*X( 1, 2 ) + X( 2, 2 ) = TEMP*X( 2, 2 ) + XNORM = TEMP*XNORM + SCALE = TEMP*SCALE + END IF + END IF + END IF + END IF +* + RETURN +* +* End of DLALN2 +* + END diff --git a/dep/lapack/dlamch.f b/dep/lapack/dlamch.f new file mode 100644 index 00000000..25c2c8e6 --- /dev/null +++ b/dep/lapack/dlamch.f @@ -0,0 +1,193 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2011 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/dep/lapack/dlange.f b/dep/lapack/dlange.f new file mode 100644 index 00000000..471c2371 --- /dev/null +++ b/dep/lapack/dlange.f @@ -0,0 +1,145 @@ + DOUBLE PRECISION FUNCTION DLANGE( NORM, M, N, A, LDA, WORK ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLANGE returns the value of the one norm, or the Frobenius norm, or +* the infinity norm, or the element of largest absolute value of a +* real matrix A. +* +* Description +* =========== +* +* DLANGE returns the value +* +* DLANGE = ( max(abs(A(i,j))), NORM = 'M' or 'm' +* ( +* ( norm1(A), NORM = '1', 'O' or 'o' +* ( +* ( normI(A), NORM = 'I' or 'i' +* ( +* ( normF(A), NORM = 'F', 'f', 'E' or 'e' +* +* where norm1 denotes the one norm of a matrix (maximum column sum), +* normI denotes the infinity norm of a matrix (maximum row sum) and +* normF denotes the Frobenius norm of a matrix (square root of sum of +* squares). Note that max(abs(A(i,j))) is not a consistent matrix norm. +* +* Arguments +* ========= +* +* NORM (input) CHARACTER*1 +* Specifies the value to be returned in DLANGE as described +* above. +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. When M = 0, +* DLANGE is set to zero. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. When N = 0, +* DLANGE is set to zero. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,N) +* The m by n matrix A. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(M,1). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)), +* where LWORK >= M when NORM = 'I'; otherwise, WORK is not +* referenced. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J + DOUBLE PRECISION SCALE, SUM, VALUE +* .. +* .. External Subroutines .. + EXTERNAL DLASSQ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + IF( MIN( M, N ).EQ.0 ) THEN + VALUE = ZERO + ELSE IF( LSAME( NORM, 'M' ) ) THEN +* +* Find max(abs(A(i,j))). +* + VALUE = ZERO + DO 20 J = 1, N + DO 10 I = 1, M + VALUE = MAX( VALUE, ABS( A( I, J ) ) ) + 10 CONTINUE + 20 CONTINUE + ELSE IF( ( LSAME( NORM, 'O' ) ) .OR. ( NORM.EQ.'1' ) ) THEN +* +* Find norm1(A). +* + VALUE = ZERO + DO 40 J = 1, N + SUM = ZERO + DO 30 I = 1, M + SUM = SUM + ABS( A( I, J ) ) + 30 CONTINUE + VALUE = MAX( VALUE, SUM ) + 40 CONTINUE + ELSE IF( LSAME( NORM, 'I' ) ) THEN +* +* Find normI(A). +* + DO 50 I = 1, M + WORK( I ) = ZERO + 50 CONTINUE + DO 70 J = 1, N + DO 60 I = 1, M + WORK( I ) = WORK( I ) + ABS( A( I, J ) ) + 60 CONTINUE + 70 CONTINUE + VALUE = ZERO + DO 80 I = 1, M + VALUE = MAX( VALUE, WORK( I ) ) + 80 CONTINUE + ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN +* +* Find normF(A). +* + SCALE = ZERO + SUM = ONE + DO 90 J = 1, N + CALL DLASSQ( M, A( 1, J ), 1, SCALE, SUM ) + 90 CONTINUE + VALUE = SCALE*SQRT( SUM ) + END IF +* + DLANGE = VALUE + RETURN +* +* End of DLANGE +* + END diff --git a/dep/lapack/dlanhs.f b/dep/lapack/dlanhs.f new file mode 100644 index 00000000..55ca1493 --- /dev/null +++ b/dep/lapack/dlanhs.f @@ -0,0 +1,142 @@ + DOUBLE PRECISION FUNCTION DLANHS( NORM, N, A, LDA, WORK ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLANHS returns the value of the one norm, or the Frobenius norm, or +* the infinity norm, or the element of largest absolute value of a +* Hessenberg matrix A. +* +* Description +* =========== +* +* DLANHS returns the value +* +* DLANHS = ( max(abs(A(i,j))), NORM = 'M' or 'm' +* ( +* ( norm1(A), NORM = '1', 'O' or 'o' +* ( +* ( normI(A), NORM = 'I' or 'i' +* ( +* ( normF(A), NORM = 'F', 'f', 'E' or 'e' +* +* where norm1 denotes the one norm of a matrix (maximum column sum), +* normI denotes the infinity norm of a matrix (maximum row sum) and +* normF denotes the Frobenius norm of a matrix (square root of sum of +* squares). Note that max(abs(A(i,j))) is not a matrix norm. +* +* Arguments +* ========= +* +* NORM (input) CHARACTER*1 +* Specifies the value to be returned in DLANHS as described +* above. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. When N = 0, DLANHS is +* set to zero. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,N) +* The n by n upper Hessenberg matrix A; the part of A below the +* first sub-diagonal is not referenced. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(N,1). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (LWORK), +* where LWORK >= N when NORM = 'I'; otherwise, WORK is not +* referenced. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J + DOUBLE PRECISION SCALE, SUM, VALUE +* .. +* .. External Subroutines .. + EXTERNAL DLASSQ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + IF( N.EQ.0 ) THEN + VALUE = ZERO + ELSE IF( LSAME( NORM, 'M' ) ) THEN +* +* Find max(abs(A(i,j))). +* + VALUE = ZERO + DO 20 J = 1, N + DO 10 I = 1, MIN( N, J+1 ) + VALUE = MAX( VALUE, ABS( A( I, J ) ) ) + 10 CONTINUE + 20 CONTINUE + ELSE IF( ( LSAME( NORM, 'O' ) ) .OR. ( NORM.EQ.'1' ) ) THEN +* +* Find norm1(A). +* + VALUE = ZERO + DO 40 J = 1, N + SUM = ZERO + DO 30 I = 1, MIN( N, J+1 ) + SUM = SUM + ABS( A( I, J ) ) + 30 CONTINUE + VALUE = MAX( VALUE, SUM ) + 40 CONTINUE + ELSE IF( LSAME( NORM, 'I' ) ) THEN +* +* Find normI(A). +* + DO 50 I = 1, N + WORK( I ) = ZERO + 50 CONTINUE + DO 70 J = 1, N + DO 60 I = 1, MIN( N, J+1 ) + WORK( I ) = WORK( I ) + ABS( A( I, J ) ) + 60 CONTINUE + 70 CONTINUE + VALUE = ZERO + DO 80 I = 1, N + VALUE = MAX( VALUE, WORK( I ) ) + 80 CONTINUE + ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN +* +* Find normF(A). +* + SCALE = ZERO + SUM = ONE + DO 90 J = 1, N + CALL DLASSQ( MIN( N, J+1 ), A( 1, J ), 1, SCALE, SUM ) + 90 CONTINUE + VALUE = SCALE*SQRT( SUM ) + END IF +* + DLANHS = VALUE + RETURN +* +* End of DLANHS +* + END diff --git a/dep/lapack/dlanst.f b/dep/lapack/dlanst.f new file mode 100644 index 00000000..2b12091a --- /dev/null +++ b/dep/lapack/dlanst.f @@ -0,0 +1,124 @@ + DOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DLANST returns the value of the one norm, or the Frobenius norm, or +* the infinity norm, or the element of largest absolute value of a +* real symmetric tridiagonal matrix A. +* +* Description +* =========== +* +* DLANST returns the value +* +* DLANST = ( max(abs(A(i,j))), NORM = 'M' or 'm' +* ( +* ( norm1(A), NORM = '1', 'O' or 'o' +* ( +* ( normI(A), NORM = 'I' or 'i' +* ( +* ( normF(A), NORM = 'F', 'f', 'E' or 'e' +* +* where norm1 denotes the one norm of a matrix (maximum column sum), +* normI denotes the infinity norm of a matrix (maximum row sum) and +* normF denotes the Frobenius norm of a matrix (square root of sum of +* squares). Note that max(abs(A(i,j))) is not a consistent matrix norm. +* +* Arguments +* ========= +* +* NORM (input) CHARACTER*1 +* Specifies the value to be returned in DLANST as described +* above. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. When N = 0, DLANST is +* set to zero. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The diagonal elements of A. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) sub-diagonal or super-diagonal elements of A. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION ANORM, SCALE, SUM +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLASSQ +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* + IF( N.LE.0 ) THEN + ANORM = ZERO + ELSE IF( LSAME( NORM, 'M' ) ) THEN +* +* Find max(abs(A(i,j))). +* + ANORM = ABS( D( N ) ) + DO 10 I = 1, N - 1 + ANORM = MAX( ANORM, ABS( D( I ) ) ) + ANORM = MAX( ANORM, ABS( E( I ) ) ) + 10 CONTINUE + ELSE IF( LSAME( NORM, 'O' ) .OR. NORM.EQ.'1' .OR. + $ LSAME( NORM, 'I' ) ) THEN +* +* Find norm1(A). +* + IF( N.EQ.1 ) THEN + ANORM = ABS( D( 1 ) ) + ELSE + ANORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ), + $ ABS( E( N-1 ) )+ABS( D( N ) ) ) + DO 20 I = 2, N - 1 + ANORM = MAX( ANORM, ABS( D( I ) )+ABS( E( I ) )+ + $ ABS( E( I-1 ) ) ) + 20 CONTINUE + END IF + ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN +* +* Find normF(A). +* + SCALE = ZERO + SUM = ONE + IF( N.GT.1 ) THEN + CALL DLASSQ( N-1, E, 1, SCALE, SUM ) + SUM = 2*SUM + END IF + CALL DLASSQ( N, D, 1, SCALE, SUM ) + ANORM = SCALE*SQRT( SUM ) + END IF +* + DLANST = ANORM + RETURN +* +* End of DLANST +* + END diff --git a/dep/lapack/dlansy.f b/dep/lapack/dlansy.f new file mode 100644 index 00000000..b6c727c0 --- /dev/null +++ b/dep/lapack/dlansy.f @@ -0,0 +1,173 @@ + DOUBLE PRECISION FUNCTION DLANSY( NORM, UPLO, N, A, LDA, WORK ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER NORM, UPLO + INTEGER LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLANSY returns the value of the one norm, or the Frobenius norm, or +* the infinity norm, or the element of largest absolute value of a +* real symmetric matrix A. +* +* Description +* =========== +* +* DLANSY returns the value +* +* DLANSY = ( max(abs(A(i,j))), NORM = 'M' or 'm' +* ( +* ( norm1(A), NORM = '1', 'O' or 'o' +* ( +* ( normI(A), NORM = 'I' or 'i' +* ( +* ( normF(A), NORM = 'F', 'f', 'E' or 'e' +* +* where norm1 denotes the one norm of a matrix (maximum column sum), +* normI denotes the infinity norm of a matrix (maximum row sum) and +* normF denotes the Frobenius norm of a matrix (square root of sum of +* squares). Note that max(abs(A(i,j))) is not a consistent matrix norm. +* +* Arguments +* ========= +* +* NORM (input) CHARACTER*1 +* Specifies the value to be returned in DLANSY as described +* above. +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* symmetric matrix A is to be referenced. +* = 'U': Upper triangular part of A is referenced +* = 'L': Lower triangular part of A is referenced +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. When N = 0, DLANSY is +* set to zero. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,N) +* The symmetric matrix A. If UPLO = 'U', the leading n by n +* upper triangular part of A contains the upper triangular part +* of the matrix A, and the strictly lower triangular part of A +* is not referenced. If UPLO = 'L', the leading n by n lower +* triangular part of A contains the lower triangular part of +* the matrix A, and the strictly upper triangular part of A is +* not referenced. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(N,1). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)), +* where LWORK >= N when NORM = 'I' or '1' or 'O'; otherwise, +* WORK is not referenced. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J + DOUBLE PRECISION ABSA, SCALE, SUM, VALUE +* .. +* .. External Subroutines .. + EXTERNAL DLASSQ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* + IF( N.EQ.0 ) THEN + VALUE = ZERO + ELSE IF( LSAME( NORM, 'M' ) ) THEN +* +* Find max(abs(A(i,j))). +* + VALUE = ZERO + IF( LSAME( UPLO, 'U' ) ) THEN + DO 20 J = 1, N + DO 10 I = 1, J + VALUE = MAX( VALUE, ABS( A( I, J ) ) ) + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40 J = 1, N + DO 30 I = J, N + VALUE = MAX( VALUE, ABS( A( I, J ) ) ) + 30 CONTINUE + 40 CONTINUE + END IF + ELSE IF( ( LSAME( NORM, 'I' ) ) .OR. ( LSAME( NORM, 'O' ) ) .OR. + $ ( NORM.EQ.'1' ) ) THEN +* +* Find normI(A) ( = norm1(A), since A is symmetric). +* + VALUE = ZERO + IF( LSAME( UPLO, 'U' ) ) THEN + DO 60 J = 1, N + SUM = ZERO + DO 50 I = 1, J - 1 + ABSA = ABS( A( I, J ) ) + SUM = SUM + ABSA + WORK( I ) = WORK( I ) + ABSA + 50 CONTINUE + WORK( J ) = SUM + ABS( A( J, J ) ) + 60 CONTINUE + DO 70 I = 1, N + VALUE = MAX( VALUE, WORK( I ) ) + 70 CONTINUE + ELSE + DO 80 I = 1, N + WORK( I ) = ZERO + 80 CONTINUE + DO 100 J = 1, N + SUM = WORK( J ) + ABS( A( J, J ) ) + DO 90 I = J + 1, N + ABSA = ABS( A( I, J ) ) + SUM = SUM + ABSA + WORK( I ) = WORK( I ) + ABSA + 90 CONTINUE + VALUE = MAX( VALUE, SUM ) + 100 CONTINUE + END IF + ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN +* +* Find normF(A). +* + SCALE = ZERO + SUM = ONE + IF( LSAME( UPLO, 'U' ) ) THEN + DO 110 J = 2, N + CALL DLASSQ( J-1, A( 1, J ), 1, SCALE, SUM ) + 110 CONTINUE + ELSE + DO 120 J = 1, N - 1 + CALL DLASSQ( N-J, A( J+1, J ), 1, SCALE, SUM ) + 120 CONTINUE + END IF + SUM = 2*SUM + CALL DLASSQ( N, A, LDA+1, SCALE, SUM ) + VALUE = SCALE*SQRT( SUM ) + END IF +* + DLANSY = VALUE + RETURN +* +* End of DLANSY +* + END diff --git a/dep/lapack/dlanv2.f b/dep/lapack/dlanv2.f new file mode 100644 index 00000000..121dd7e3 --- /dev/null +++ b/dep/lapack/dlanv2.f @@ -0,0 +1,175 @@ + SUBROUTINE DLANV2( A, B, C, D, RT1R, RT1I, RT2R, RT2I, CS, SN ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B, C, CS, D, RT1I, RT1R, RT2I, RT2R, SN +* .. +* +* Purpose +* ======= +* +* DLANV2 computes the Schur factorization of a real 2-by-2 nonsymmetric +* matrix in standard form: +* +* [ A B ] = [ CS -SN ] [ AA BB ] [ CS SN ] +* [ C D ] [ SN CS ] [ CC DD ] [-SN CS ] +* +* where either +* 1) CC = 0 so that AA and DD are real eigenvalues of the matrix, or +* 2) AA = DD and BB*CC < 0, so that AA + or - sqrt(BB*CC) are complex +* conjugate eigenvalues. +* +* Arguments +* ========= +* +* A (input/output) DOUBLE PRECISION +* B (input/output) DOUBLE PRECISION +* C (input/output) DOUBLE PRECISION +* D (input/output) DOUBLE PRECISION +* On entry, the elements of the input matrix. +* On exit, they are overwritten by the elements of the +* standardised Schur form. +* +* RT1R (output) DOUBLE PRECISION +* RT1I (output) DOUBLE PRECISION +* RT2R (output) DOUBLE PRECISION +* RT2I (output) DOUBLE PRECISION +* The real and imaginary parts of the eigenvalues. If the +* eigenvalues are both real, abs(RT1R) >= abs(RT2R); if the +* eigenvalues are a complex conjugate pair, RT1I > 0. +* +* CS (output) DOUBLE PRECISION +* SN (output) DOUBLE PRECISION +* Parameters of the rotation matrix. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, HALF, ONE + PARAMETER ( ZERO = 0.0D+0, HALF = 0.5D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AA, BB, CC, CS1, DD, P, SAB, SAC, SIGMA, SN1, + $ TAU, TEMP +* .. +* .. External Functions .. + DOUBLE PRECISION DLAPY2 + EXTERNAL DLAPY2 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN, SQRT +* .. +* .. Executable Statements .. +* +* Initialize CS and SN +* + CS = ONE + SN = ZERO +* + IF( C.EQ.ZERO ) THEN + GO TO 10 +* + ELSE IF( B.EQ.ZERO ) THEN +* +* Swap rows and columns +* + CS = ZERO + SN = ONE + TEMP = D + D = A + A = TEMP + B = -C + C = ZERO + GO TO 10 + ELSE IF( (A-D).EQ.ZERO .AND. SIGN( ONE, B ).NE. + $ SIGN( ONE, C ) ) THEN + GO TO 10 + ELSE +* +* Make diagonal elements equal +* + TEMP = A - D + P = HALF*TEMP + SIGMA = B + C + TAU = DLAPY2( SIGMA, TEMP ) + CS1 = SQRT( HALF*( ONE+ABS( SIGMA ) / TAU ) ) + SN1 = -( P / ( TAU*CS1 ) )*SIGN( ONE, SIGMA ) +* +* Compute [ AA BB ] = [ A B ] [ CS1 -SN1 ] +* [ CC DD ] [ C D ] [ SN1 CS1 ] +* + AA = A*CS1 + B*SN1 + BB = -A*SN1 + B*CS1 + CC = C*CS1 + D*SN1 + DD = -C*SN1 + D*CS1 +* +* Compute [ A B ] = [ CS1 SN1 ] [ AA BB ] +* [ C D ] [-SN1 CS1 ] [ CC DD ] +* + A = AA*CS1 + CC*SN1 + B = BB*CS1 + DD*SN1 + C = -AA*SN1 + CC*CS1 + D = -BB*SN1 + DD*CS1 +* +* Accumulate transformation +* + TEMP = CS*CS1 - SN*SN1 + SN = CS*SN1 + SN*CS1 + CS = TEMP +* + TEMP = HALF*( A+D ) + A = TEMP + D = TEMP +* + IF( C.NE.ZERO ) THEN + IF( B.NE.ZERO ) THEN + IF( SIGN( ONE, B ).EQ.SIGN( ONE, C ) ) THEN +* +* Real eigenvalues: reduce to upper triangular form +* + SAB = SQRT( ABS( B ) ) + SAC = SQRT( ABS( C ) ) + P = SIGN( SAB*SAC, C ) + TAU = ONE / SQRT( ABS( B+C ) ) + A = TEMP + P + D = TEMP - P + B = B - C + C = ZERO + CS1 = SAB*TAU + SN1 = SAC*TAU + TEMP = CS*CS1 - SN*SN1 + SN = CS*SN1 + SN*CS1 + CS = TEMP + END IF + ELSE + B = -C + C = ZERO + TEMP = CS + CS = -SN + SN = TEMP + END IF + END IF + END IF +* + 10 CONTINUE +* +* Store eigenvalues in (RT1R,RT1I) and (RT2R,RT2I). +* + RT1R = A + RT2R = D + IF( C.EQ.ZERO ) THEN + RT1I = ZERO + RT2I = ZERO + ELSE + RT1I = SQRT( ABS( B ) )*SQRT( ABS( C ) ) + RT2I = -RT1I + END IF + RETURN +* +* End of DLANV2 +* + END diff --git a/dep/lapack/dlaptm.f b/dep/lapack/dlaptm.f new file mode 100644 index 00000000..e1e23a6f --- /dev/null +++ b/dep/lapack/dlaptm.f @@ -0,0 +1,136 @@ + SUBROUTINE DLAPTM( N, NRHS, ALPHA, D, E, X, LDX, BETA, B, LDB ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + INTEGER LDB, LDX, N, NRHS + DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), E( * ), X( LDX, * ) +* .. +* +* Purpose +* ======= +* +* DLAPTM multiplies an N by NRHS matrix X by a symmetric tridiagonal +* matrix A and stores the result in a matrix B. The operation has the +* form +* +* B := alpha * A * X + beta * B +* +* where alpha may be either 1. or -1. and beta may be 0., 1., or -1. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrices X and B. +* +* ALPHA (input) DOUBLE PRECISION +* The scalar alpha. ALPHA must be 1. or -1.; otherwise, +* it is assumed to be 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the tridiagonal matrix A. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) subdiagonal or superdiagonal elements of A. +* +* X (input) DOUBLE PRECISION array, dimension (LDX,NRHS) +* The N by NRHS matrix X. +* +* LDX (input) INTEGER +* The leading dimension of the array X. LDX >= max(N,1). +* +* BETA (input) DOUBLE PRECISION +* The scalar beta. BETA must be 0., 1., or -1.; otherwise, +* it is assumed to be 1. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the N by NRHS matrix B. +* On exit, B is overwritten by the matrix expression +* B := alpha * A * X + beta * B. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(N,1). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J +* .. +* .. Executable Statements .. +* + IF( N.EQ.0 ) + $ RETURN +* +* Multiply B by BETA if BETA.NE.1. +* + IF( BETA.EQ.ZERO ) THEN + DO 20 J = 1, NRHS + DO 10 I = 1, N + B( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE IF( BETA.EQ.-ONE ) THEN + DO 40 J = 1, NRHS + DO 30 I = 1, N + B( I, J ) = -B( I, J ) + 30 CONTINUE + 40 CONTINUE + END IF +* + IF( ALPHA.EQ.ONE ) THEN +* +* Compute B := B + A*X +* + DO 60 J = 1, NRHS + IF( N.EQ.1 ) THEN + B( 1, J ) = B( 1, J ) + D( 1 )*X( 1, J ) + ELSE + B( 1, J ) = B( 1, J ) + D( 1 )*X( 1, J ) + + $ E( 1 )*X( 2, J ) + B( N, J ) = B( N, J ) + E( N-1 )*X( N-1, J ) + + $ D( N )*X( N, J ) + DO 50 I = 2, N - 1 + B( I, J ) = B( I, J ) + E( I-1 )*X( I-1, J ) + + $ D( I )*X( I, J ) + E( I )*X( I+1, J ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE IF( ALPHA.EQ.-ONE ) THEN +* +* Compute B := B - A*X +* + DO 80 J = 1, NRHS + IF( N.EQ.1 ) THEN + B( 1, J ) = B( 1, J ) - D( 1 )*X( 1, J ) + ELSE + B( 1, J ) = B( 1, J ) - D( 1 )*X( 1, J ) - + $ E( 1 )*X( 2, J ) + B( N, J ) = B( N, J ) - E( N-1 )*X( N-1, J ) - + $ D( N )*X( N, J ) + DO 70 I = 2, N - 1 + B( I, J ) = B( I, J ) - E( I-1 )*X( I-1, J ) - + $ D( I )*X( I, J ) - E( I )*X( I+1, J ) + 70 CONTINUE + END IF + 80 CONTINUE + END IF + RETURN +* +* End of DLAPTM +* + END diff --git a/dep/lapack/dlapy2.f b/dep/lapack/dlapy2.f new file mode 100644 index 00000000..c44b267a --- /dev/null +++ b/dep/lapack/dlapy2.f @@ -0,0 +1,54 @@ + DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y +* .. +* +* Purpose +* ======= +* +* DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary +* overflow. +* +* Arguments +* ========= +* +* X (input) DOUBLE PRECISION +* Y (input) DOUBLE PRECISION +* X and Y specify the values x and y. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION W, XABS, YABS, Z +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + XABS = ABS( X ) + YABS = ABS( Y ) + W = MAX( XABS, YABS ) + Z = MIN( XABS, YABS ) + IF( Z.EQ.ZERO ) THEN + DLAPY2 = W + ELSE + DLAPY2 = W*SQRT( ONE+( Z / W )**2 ) + END IF + RETURN +* +* End of DLAPY2 +* + END diff --git a/dep/lapack/dlapy3.f b/dep/lapack/dlapy3.f new file mode 100644 index 00000000..da63b413 --- /dev/null +++ b/dep/lapack/dlapy3.f @@ -0,0 +1,54 @@ + DOUBLE PRECISION FUNCTION DLAPY3( X, Y, Z ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y, Z +* .. +* +* Purpose +* ======= +* +* DLAPY3 returns sqrt(x**2+y**2+z**2), taking care not to cause +* unnecessary overflow. +* +* Arguments +* ========= +* +* X (input) DOUBLE PRECISION +* Y (input) DOUBLE PRECISION +* Z (input) DOUBLE PRECISION +* X, Y and Z specify the values x, y and z. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION W, XABS, YABS, ZABS +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* + XABS = ABS( X ) + YABS = ABS( Y ) + ZABS = ABS( Z ) + W = MAX( XABS, YABS, ZABS ) + IF( W.EQ.ZERO ) THEN + DLAPY3 = ZERO + ELSE + DLAPY3 = W*SQRT( ( XABS / W )**2+( YABS / W )**2+ + $ ( ZABS / W )**2 ) + END IF + RETURN +* +* End of DLAPY3 +* + END diff --git a/dep/lapack/dlaqr0.f b/dep/lapack/dlaqr0.f new file mode 100644 index 00000000..166a5fbb --- /dev/null +++ b/dep/lapack/dlaqr0.f @@ -0,0 +1,637 @@ + SUBROUTINE DLAQR0( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, + $ ILOZ, IHIZ, Z, LDZ, WORK, LWORK, INFO ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, LWORK, N + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ), + $ Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DLAQR0 computes the eigenvalues of a Hessenberg matrix H +* and, optionally, the matrices T and Z from the Schur decomposition +* H = Z T Z**T, where T is an upper quasi-triangular matrix (the +* Schur form), and Z is the orthogonal matrix of Schur vectors. +* +* Optionally Z may be postmultiplied into an input orthogonal +* matrix Q so that this routine can give the Schur factorization +* of a matrix A which has been reduced to the Hessenberg form H +* by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. +* +* Arguments +* ========= +* +* WANTT (input) LOGICAL +* = .TRUE. : the full Schur form T is required; +* = .FALSE.: only eigenvalues are required. +* +* WANTZ (input) LOGICAL +* = .TRUE. : the matrix of Schur vectors Z is required; +* = .FALSE.: Schur vectors are not required. +* +* N (input) INTEGER +* The order of the matrix H. N .GE. 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* It is assumed that H is already upper triangular in rows +* and columns 1:ILO-1 and IHI+1:N and, if ILO.GT.1, +* H(ILO,ILO-1) is zero. ILO and IHI are normally set by a +* previous call to DGEBAL, and then passed to DGEHRD when the +* matrix output by DGEBAL is reduced to Hessenberg form. +* Otherwise, ILO and IHI should be set to 1 and N, +* respectively. If N.GT.0, then 1.LE.ILO.LE.IHI.LE.N. +* If N = 0, then ILO = 1 and IHI = 0. +* +* H (input/output) DOUBLE PRECISION array, dimension (LDH,N) +* On entry, the upper Hessenberg matrix H. +* On exit, if INFO = 0 and WANTT is .TRUE., then H contains +* the upper quasi-triangular matrix T from the Schur +* decomposition (the Schur form); 2-by-2 diagonal blocks +* (corresponding to complex conjugate pairs of eigenvalues) +* are returned in standard form, with H(i,i) = H(i+1,i+1) +* and H(i+1,i)*H(i,i+1).LT.0. If INFO = 0 and WANTT is +* .FALSE., then the contents of H are unspecified on exit. +* (The output value of H when INFO.GT.0 is given under the +* description of INFO below.) +* +* This subroutine may explicitly set H(i,j) = 0 for i.GT.j and +* j = 1, 2, ... ILO-1 or j = IHI+1, IHI+2, ... N. +* +* LDH (input) INTEGER +* The leading dimension of the array H. LDH .GE. max(1,N). +* +* WR (output) DOUBLE PRECISION array, dimension (IHI) +* WI (output) DOUBLE PRECISION array, dimension (IHI) +* The real and imaginary parts, respectively, of the computed +* eigenvalues of H(ILO:IHI,ILO:IHI) are stored in WR(ILO:IHI) +* and WI(ILO:IHI). If two eigenvalues are computed as a +* complex conjugate pair, they are stored in consecutive +* elements of WR and WI, say the i-th and (i+1)th, with +* WI(i) .GT. 0 and WI(i+1) .LT. 0. If WANTT is .TRUE., then +* the eigenvalues are stored in the same order as on the +* diagonal of the Schur form returned in H, with +* WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 diagonal +* block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and +* WI(i+1) = -WI(i). +* +* ILOZ (input) INTEGER +* IHIZ (input) INTEGER +* Specify the rows of Z to which transformations must be +* applied if WANTZ is .TRUE.. +* 1 .LE. ILOZ .LE. ILO; IHI .LE. IHIZ .LE. N. +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,IHI) +* If WANTZ is .FALSE., then Z is not referenced. +* If WANTZ is .TRUE., then Z(ILO:IHI,ILOZ:IHIZ) is +* replaced by Z(ILO:IHI,ILOZ:IHIZ)*U where U is the +* orthogonal Schur factor of H(ILO:IHI,ILO:IHI). +* (The output value of Z when INFO.GT.0 is given under +* the description of INFO below.) +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. if WANTZ is .TRUE. +* then LDZ.GE.MAX(1,IHIZ). Otherwize, LDZ.GE.1. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension LWORK +* On exit, if LWORK = -1, WORK(1) returns an estimate of +* the optimal value for LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK .GE. max(1,N) +* is sufficient, but LWORK typically as large as 6*N may +* be required for optimal performance. A workspace query +* to determine the optimal workspace size is recommended. +* +* If LWORK = -1, then DLAQR0 does a workspace query. +* In this case, DLAQR0 checks the input parameters and +* estimates the optimal workspace size for the given +* values of N, ILO and IHI. The estimate is returned +* in WORK(1). No error message related to LWORK is +* issued by XERBLA. Neither H nor Z are accessed. +* +* +* INFO (output) INTEGER +* = 0: successful exit +* .GT. 0: if INFO = i, DLAQR0 failed to compute all of +* the eigenvalues. Elements 1:ilo-1 and i+1:n of WR +* and WI contain those eigenvalues which have been +* successfully computed. (Failures are rare.) +* +* If INFO .GT. 0 and WANT is .FALSE., then on exit, +* the remaining unconverged eigenvalues are the eigen- +* values of the upper Hessenberg matrix rows and +* columns ILO through INFO of the final, output +* value of H. +* +* If INFO .GT. 0 and WANTT is .TRUE., then on exit +* +* (*) (initial value of H)*U = U*(final value of H) +* +* where U is an orthogonal matrix. The final +* value of H is upper Hessenberg and quasi-triangular +* in rows and columns INFO+1 through IHI. +* +* If INFO .GT. 0 and WANTZ is .TRUE., then on exit +* +* (final value of Z(ILO:IHI,ILOZ:IHIZ) +* = (initial value of Z(ILO:IHI,ILOZ:IHIZ)*U +* +* where U is the orthogonal matrix in (*) (regard- +* less of the value of WANTT.) +* +* If INFO .GT. 0 and WANTZ is .FALSE., then Z is not +* accessed. +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* References: +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 +* Performance, SIAM Journal of Matrix Analysis, volume 23, pages +* 929--947, 2002. +* +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part II: Aggressive Early Deflation, SIAM Journal +* of Matrix Analysis, volume 23, pages 948--973, 2002. +* +* ================================================================ +* .. Parameters .. +* +* ==== Matrices of order NTINY or smaller must be processed by +* . DLAHQR because of insufficient subdiagonal scratch space. +* . (This is a hard limit.) ==== + INTEGER NTINY + PARAMETER ( NTINY = 11 ) +* +* ==== Exceptional deflation windows: try to cure rare +* . slow convergence by varying the size of the +* . deflation window after KEXNW iterations. ==== + INTEGER KEXNW + PARAMETER ( KEXNW = 5 ) +* +* ==== Exceptional shifts: try to cure rare slow convergence +* . with ad-hoc exceptional shifts every KEXSH iterations. +* . ==== + INTEGER KEXSH + PARAMETER ( KEXSH = 6 ) +* +* ==== The constants WILK1 and WILK2 are used to form the +* . exceptional shifts. ==== + DOUBLE PRECISION WILK1, WILK2 + PARAMETER ( WILK1 = 0.75d0, WILK2 = -0.4375d0 ) + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AA, BB, CC, CS, DD, SN, SS, SWAP + INTEGER I, INF, IT, ITMAX, K, KACC22, KBOT, KDU, KS, + $ KT, KTOP, KU, KV, KWH, KWTOP, KWV, LD, LS, + $ LWKOPT, NDEC, NDFL, NH, NHO, NIBBLE, NMIN, NS, + $ NSMAX, NSR, NVE, NW, NWMAX, NWR, NWUPBD + LOGICAL SORTED + CHARACTER JBCMPZ*2 +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Local Arrays .. + DOUBLE PRECISION ZDUM( 1, 1 ) +* .. +* .. External Subroutines .. + EXTERNAL DLACPY, DLAHQR, DLANV2, DLAQR3, DLAQR4, DLAQR5 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, INT, MAX, MIN, MOD +* .. +* .. Executable Statements .. + INFO = 0 +* +* ==== Quick return for N = 0: nothing to do. ==== +* + IF( N.EQ.0 ) THEN + WORK( 1 ) = ONE + RETURN + END IF +* + IF( N.LE.NTINY ) THEN +* +* ==== Tiny matrices must use DLAHQR. ==== +* + LWKOPT = 1 + IF( LWORK.NE.-1 ) + $ CALL DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, + $ ILOZ, IHIZ, Z, LDZ, INFO ) + ELSE +* +* ==== Use small bulge multi-shift QR with aggressive early +* . deflation on larger-than-tiny matrices. ==== +* +* ==== Hope for the best. ==== +* + INFO = 0 +* +* ==== Set up job flags for ILAENV. ==== +* + IF( WANTT ) THEN + JBCMPZ( 1: 1 ) = 'S' + ELSE + JBCMPZ( 1: 1 ) = 'E' + END IF + IF( WANTZ ) THEN + JBCMPZ( 2: 2 ) = 'V' + ELSE + JBCMPZ( 2: 2 ) = 'N' + END IF +* +* ==== NWR = recommended deflation window size. At this +* . point, N .GT. NTINY = 11, so there is enough +* . subdiagonal workspace for NWR.GE.2 as required. +* . (In fact, there is enough subdiagonal space for +* . NWR.GE.3.) ==== +* + NWR = ILAENV( 13, 'DLAQR0', JBCMPZ, N, ILO, IHI, LWORK ) + NWR = MAX( 2, NWR ) + NWR = MIN( IHI-ILO+1, ( N-1 ) / 3, NWR ) +* +* ==== NSR = recommended number of simultaneous shifts. +* . At this point N .GT. NTINY = 11, so there is at +* . enough subdiagonal workspace for NSR to be even +* . and greater than or equal to two as required. ==== +* + NSR = ILAENV( 15, 'DLAQR0', JBCMPZ, N, ILO, IHI, LWORK ) + NSR = MIN( NSR, ( N+6 ) / 9, IHI-ILO ) + NSR = MAX( 2, NSR-MOD( NSR, 2 ) ) +* +* ==== Estimate optimal workspace ==== +* +* ==== Workspace query call to DLAQR3 ==== +* + CALL DLAQR3( WANTT, WANTZ, N, ILO, IHI, NWR+1, H, LDH, ILOZ, + $ IHIZ, Z, LDZ, LS, LD, WR, WI, H, LDH, N, H, LDH, + $ N, H, LDH, WORK, -1 ) +* +* ==== Optimal workspace = MAX(DLAQR5, DLAQR3) ==== +* + LWKOPT = MAX( 3*NSR / 2, INT( WORK( 1 ) ) ) +* +* ==== Quick return in case of workspace query. ==== +* + IF( LWORK.EQ.-1 ) THEN + WORK( 1 ) = DBLE( LWKOPT ) + RETURN + END IF +* +* ==== DLAHQR/DLAQR0 crossover point ==== +* + NMIN = ILAENV( 12, 'DLAQR0', JBCMPZ, N, ILO, IHI, LWORK ) + NMIN = MAX( NTINY, NMIN ) +* +* ==== Nibble crossover point ==== +* + NIBBLE = ILAENV( 14, 'DLAQR0', JBCMPZ, N, ILO, IHI, LWORK ) + NIBBLE = MAX( 0, NIBBLE ) +* +* ==== Accumulate reflections during ttswp? Use block +* . 2-by-2 structure during matrix-matrix multiply? ==== +* + KACC22 = ILAENV( 16, 'DLAQR0', JBCMPZ, N, ILO, IHI, LWORK ) + KACC22 = MAX( 0, KACC22 ) + KACC22 = MIN( 2, KACC22 ) +* +* ==== NWMAX = the largest possible deflation window for +* . which there is sufficient workspace. ==== +* + NWMAX = MIN( ( N-1 ) / 3, LWORK / 2 ) + NW = NWMAX +* +* ==== NSMAX = the Largest number of simultaneous shifts +* . for which there is sufficient workspace. ==== +* + NSMAX = MIN( ( N+6 ) / 9, 2*LWORK / 3 ) + NSMAX = NSMAX - MOD( NSMAX, 2 ) +* +* ==== NDFL: an iteration count restarted at deflation. ==== +* + NDFL = 1 +* +* ==== ITMAX = iteration limit ==== +* + ITMAX = MAX( 30, 2*KEXSH )*MAX( 10, ( IHI-ILO+1 ) ) +* +* ==== Last row and column in the active block ==== +* + KBOT = IHI +* +* ==== Main Loop ==== +* + DO 80 IT = 1, ITMAX +* +* ==== Done when KBOT falls below ILO ==== +* + IF( KBOT.LT.ILO ) + $ GO TO 90 +* +* ==== Locate active block ==== +* + DO 10 K = KBOT, ILO + 1, -1 + IF( H( K, K-1 ).EQ.ZERO ) + $ GO TO 20 + 10 CONTINUE + K = ILO + 20 CONTINUE + KTOP = K +* +* ==== Select deflation window size: +* . Typical Case: +* . If possible and advisable, nibble the entire +* . active block. If not, use size MIN(NWR,NWMAX) +* . or MIN(NWR+1,NWMAX) depending upon which has +* . the smaller corresponding subdiagonal entry +* . (a heuristic). +* . +* . Exceptional Case: +* . If there have been no deflations in KEXNW or +* . more iterations, then vary the deflation window +* . size. At first, because, larger windows are, +* . in general, more powerful than smaller ones, +* . rapidly increase the window to the maximum possible. +* . Then, gradually reduce the window size. ==== +* + NH = KBOT - KTOP + 1 + NWUPBD = MIN( NH, NWMAX ) + IF( NDFL.LT.KEXNW ) THEN + NW = MIN( NWUPBD, NWR ) + ELSE + NW = MIN( NWUPBD, 2*NW ) + END IF + IF( NW.LT.NWMAX ) THEN + IF( NW.GE.NH-1 ) THEN + NW = NH + ELSE + KWTOP = KBOT - NW + 1 + IF( ABS( H( KWTOP, KWTOP-1 ) ).GT. + $ ABS( H( KWTOP-1, KWTOP-2 ) ) )NW = NW + 1 + END IF + END IF + IF( NDFL.LT.KEXNW ) THEN + NDEC = -1 + ELSE IF( NDEC.GE.0 .OR. NW.GE.NWUPBD ) THEN + NDEC = NDEC + 1 + IF( NW-NDEC.LT.2 ) + $ NDEC = 0 + NW = NW - NDEC + END IF +* +* ==== Aggressive early deflation: +* . split workspace under the subdiagonal into +* . - an nw-by-nw work array V in the lower +* . left-hand-corner, +* . - an NW-by-at-least-NW-but-more-is-better +* . (NW-by-NHO) horizontal work array along +* . the bottom edge, +* . - an at-least-NW-but-more-is-better (NHV-by-NW) +* . vertical work array along the left-hand-edge. +* . ==== +* + KV = N - NW + 1 + KT = NW + 1 + NHO = ( N-NW-1 ) - KT + 1 + KWV = NW + 2 + NVE = ( N-NW ) - KWV + 1 +* +* ==== Aggressive early deflation ==== +* + CALL DLAQR3( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ, + $ IHIZ, Z, LDZ, LS, LD, WR, WI, H( KV, 1 ), LDH, + $ NHO, H( KV, KT ), LDH, NVE, H( KWV, 1 ), LDH, + $ WORK, LWORK ) +* +* ==== Adjust KBOT accounting for new deflations. ==== +* + KBOT = KBOT - LD +* +* ==== KS points to the shifts. ==== +* + KS = KBOT - LS + 1 +* +* ==== Skip an expensive QR sweep if there is a (partly +* . heuristic) reason to expect that many eigenvalues +* . will deflate without it. Here, the QR sweep is +* . skipped if many eigenvalues have just been deflated +* . or if the remaining active block is small. +* + IF( ( LD.EQ.0 ) .OR. ( ( 100*LD.LE.NW*NIBBLE ) .AND. ( KBOT- + $ KTOP+1.GT.MIN( NMIN, NWMAX ) ) ) ) THEN +* +* ==== NS = nominal number of simultaneous shifts. +* . This may be lowered (slightly) if DLAQR3 +* . did not provide that many shifts. ==== +* + NS = MIN( NSMAX, NSR, MAX( 2, KBOT-KTOP ) ) + NS = NS - MOD( NS, 2 ) +* +* ==== If there have been no deflations +* . in a multiple of KEXSH iterations, +* . then try exceptional shifts. +* . Otherwise use shifts provided by +* . DLAQR3 above or from the eigenvalues +* . of a trailing principal submatrix. ==== +* + IF( MOD( NDFL, KEXSH ).EQ.0 ) THEN + KS = KBOT - NS + 1 + DO 30 I = KBOT, MAX( KS+1, KTOP+2 ), -2 + SS = ABS( H( I, I-1 ) ) + ABS( H( I-1, I-2 ) ) + AA = WILK1*SS + H( I, I ) + BB = SS + CC = WILK2*SS + DD = AA + CALL DLANV2( AA, BB, CC, DD, WR( I-1 ), WI( I-1 ), + $ WR( I ), WI( I ), CS, SN ) + 30 CONTINUE + IF( KS.EQ.KTOP ) THEN + WR( KS+1 ) = H( KS+1, KS+1 ) + WI( KS+1 ) = ZERO + WR( KS ) = WR( KS+1 ) + WI( KS ) = WI( KS+1 ) + END IF + ELSE +* +* ==== Got NS/2 or fewer shifts? Use DLAQR4 or +* . DLAHQR on a trailing principal submatrix to +* . get more. (Since NS.LE.NSMAX.LE.(N+6)/9, +* . there is enough space below the subdiagonal +* . to fit an NS-by-NS scratch array.) ==== +* + IF( KBOT-KS+1.LE.NS / 2 ) THEN + KS = KBOT - NS + 1 + KT = N - NS + 1 + CALL DLACPY( 'A', NS, NS, H( KS, KS ), LDH, + $ H( KT, 1 ), LDH ) + IF( NS.GT.NMIN ) THEN + CALL DLAQR4( .false., .false., NS, 1, NS, + $ H( KT, 1 ), LDH, WR( KS ), + $ WI( KS ), 1, 1, ZDUM, 1, WORK, + $ LWORK, INF ) + ELSE + CALL DLAHQR( .false., .false., NS, 1, NS, + $ H( KT, 1 ), LDH, WR( KS ), + $ WI( KS ), 1, 1, ZDUM, 1, INF ) + END IF + KS = KS + INF +* +* ==== In case of a rare QR failure use +* . eigenvalues of the trailing 2-by-2 +* . principal submatrix. ==== +* + IF( KS.GE.KBOT ) THEN + AA = H( KBOT-1, KBOT-1 ) + CC = H( KBOT, KBOT-1 ) + BB = H( KBOT-1, KBOT ) + DD = H( KBOT, KBOT ) + CALL DLANV2( AA, BB, CC, DD, WR( KBOT-1 ), + $ WI( KBOT-1 ), WR( KBOT ), + $ WI( KBOT ), CS, SN ) + KS = KBOT - 1 + END IF + END IF +* + IF( KBOT-KS+1.GT.NS ) THEN +* +* ==== Sort the shifts (Helps a little) +* . Bubble sort keeps complex conjugate +* . pairs together. ==== +* + SORTED = .false. + DO 50 K = KBOT, KS + 1, -1 + IF( SORTED ) + $ GO TO 60 + SORTED = .true. + DO 40 I = KS, K - 1 + IF( ABS( WR( I ) )+ABS( WI( I ) ).LT. + $ ABS( WR( I+1 ) )+ABS( WI( I+1 ) ) ) THEN + SORTED = .false. +* + SWAP = WR( I ) + WR( I ) = WR( I+1 ) + WR( I+1 ) = SWAP +* + SWAP = WI( I ) + WI( I ) = WI( I+1 ) + WI( I+1 ) = SWAP + END IF + 40 CONTINUE + 50 CONTINUE + 60 CONTINUE + END IF +* +* ==== Shuffle shifts into pairs of real shifts +* . and pairs of complex conjugate shifts +* . assuming complex conjugate shifts are +* . already adjacent to one another. (Yes, +* . they are.) ==== +* + DO 70 I = KBOT, KS + 2, -2 + IF( WI( I ).NE.-WI( I-1 ) ) THEN +* + SWAP = WR( I ) + WR( I ) = WR( I-1 ) + WR( I-1 ) = WR( I-2 ) + WR( I-2 ) = SWAP +* + SWAP = WI( I ) + WI( I ) = WI( I-1 ) + WI( I-1 ) = WI( I-2 ) + WI( I-2 ) = SWAP + END IF + 70 CONTINUE + END IF +* +* ==== If there are only two shifts and both are +* . real, then use only one. ==== +* + IF( KBOT-KS+1.EQ.2 ) THEN + IF( WI( KBOT ).EQ.ZERO ) THEN + IF( ABS( WR( KBOT )-H( KBOT, KBOT ) ).LT. + $ ABS( WR( KBOT-1 )-H( KBOT, KBOT ) ) ) THEN + WR( KBOT-1 ) = WR( KBOT ) + ELSE + WR( KBOT ) = WR( KBOT-1 ) + END IF + END IF + END IF +* +* ==== Use up to NS of the the smallest magnatiude +* . shifts. If there aren't NS shifts available, +* . then use them all, possibly dropping one to +* . make the number of shifts even. ==== +* + NS = MIN( NS, KBOT-KS+1 ) + NS = NS - MOD( NS, 2 ) + KS = KBOT - NS + 1 +* +* ==== Small-bulge multi-shift QR sweep: +* . split workspace under the subdiagonal into +* . - a KDU-by-KDU work array U in the lower +* . left-hand-corner, +* . - a KDU-by-at-least-KDU-but-more-is-better +* . (KDU-by-NHo) horizontal work array WH along +* . the bottom edge, +* . - and an at-least-KDU-but-more-is-better-by-KDU +* . (NVE-by-KDU) vertical work WV arrow along +* . the left-hand-edge. ==== +* + KDU = 3*NS - 3 + KU = N - KDU + 1 + KWH = KDU + 1 + NHO = ( N-KDU+1-4 ) - ( KDU+1 ) + 1 + KWV = KDU + 4 + NVE = N - KDU - KWV + 1 +* +* ==== Small-bulge multi-shift QR sweep ==== +* + CALL DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NS, + $ WR( KS ), WI( KS ), H, LDH, ILOZ, IHIZ, Z, + $ LDZ, WORK, 3, H( KU, 1 ), LDH, NVE, + $ H( KWV, 1 ), LDH, NHO, H( KU, KWH ), LDH ) + END IF +* +* ==== Note progress (or the lack of it). ==== +* + IF( LD.GT.0 ) THEN + NDFL = 1 + ELSE + NDFL = NDFL + 1 + END IF +* +* ==== End of main loop ==== + 80 CONTINUE +* +* ==== Iteration limit exceeded. Set INFO to show where +* . the problem occurred and exit. ==== +* + INFO = KBOT + 90 CONTINUE + END IF +* +* ==== Return the optimal value of LWORK. ==== +* + WORK( 1 ) = DBLE( LWKOPT ) +* +* ==== End of DLAQR0 ==== +* + END diff --git a/dep/lapack/dlaqr1.f b/dep/lapack/dlaqr1.f new file mode 100644 index 00000000..ae23573c --- /dev/null +++ b/dep/lapack/dlaqr1.f @@ -0,0 +1,97 @@ + SUBROUTINE DLAQR1( N, H, LDH, SR1, SI1, SR2, SI2, V ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION SI1, SI2, SR1, SR2 + INTEGER LDH, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), V( * ) +* .. +* +* Given a 2-by-2 or 3-by-3 matrix H, DLAQR1 sets v to a +* scalar multiple of the first column of the product +* +* (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) +* +* scaling to avoid overflows and most underflows. It +* is assumed that either +* +* 1) sr1 = sr2 and si1 = -si2 +* or +* 2) si1 = si2 = 0. +* +* This is useful for starting double implicit shift bulges +* in the QR algorithm. +* +* +* N (input) integer +* Order of the matrix H. N must be either 2 or 3. +* +* H (input) DOUBLE PRECISION array of dimension (LDH,N) +* The 2-by-2 or 3-by-3 matrix H in (*). +* +* LDH (input) integer +* The leading dimension of H as declared in +* the calling procedure. LDH.GE.N +* +* SR1 (input) DOUBLE PRECISION +* SI1 The shifts in (*). +* SR2 +* SI2 +* +* V (output) DOUBLE PRECISION array of dimension N +* A scalar multiple of the first column of the +* matrix K in (*). +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION H21S, H31S, S +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. + IF( N.EQ.2 ) THEN + S = ABS( H( 1, 1 )-SR2 ) + ABS( SI2 ) + ABS( H( 2, 1 ) ) + IF( S.EQ.ZERO ) THEN + V( 1 ) = ZERO + V( 2 ) = ZERO + ELSE + H21S = H( 2, 1 ) / S + V( 1 ) = H21S*H( 1, 2 ) + ( H( 1, 1 )-SR1 )* + $ ( ( H( 1, 1 )-SR2 ) / S ) - SI1*( SI2 / S ) + V( 2 ) = H21S*( H( 1, 1 )+H( 2, 2 )-SR1-SR2 ) + END IF + ELSE + S = ABS( H( 1, 1 )-SR2 ) + ABS( SI2 ) + ABS( H( 2, 1 ) ) + + $ ABS( H( 3, 1 ) ) + IF( S.EQ.ZERO ) THEN + V( 1 ) = ZERO + V( 2 ) = ZERO + V( 3 ) = ZERO + ELSE + H21S = H( 2, 1 ) / S + H31S = H( 3, 1 ) / S + V( 1 ) = ( H( 1, 1 )-SR1 )*( ( H( 1, 1 )-SR2 ) / S ) - + $ SI1*( SI2 / S ) + H( 1, 2 )*H21S + H( 1, 3 )*H31S + V( 2 ) = H21S*( H( 1, 1 )+H( 2, 2 )-SR1-SR2 ) + + $ H( 2, 3 )*H31S + V( 3 ) = H31S*( H( 1, 1 )+H( 3, 3 )-SR1-SR2 ) + + $ H21S*H( 3, 2 ) + END IF + END IF + END diff --git a/dep/lapack/dlaqr2.f b/dep/lapack/dlaqr2.f new file mode 100644 index 00000000..b5bf0010 --- /dev/null +++ b/dep/lapack/dlaqr2.f @@ -0,0 +1,547 @@ + SUBROUTINE DLAQR2( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ, + $ IHIZ, Z, LDZ, NS, ND, SR, SI, V, LDV, NH, T, + $ LDT, NV, WV, LDWV, WORK, LWORK ) +* +* -- LAPACK auxiliary routine (version 3.2.2) -- +* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +* -- June 2010 -- +* +* .. Scalar Arguments .. + INTEGER IHIZ, ILOZ, KBOT, KTOP, LDH, LDT, LDV, LDWV, + $ LDZ, LWORK, N, ND, NH, NS, NV, NW + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), T( LDT, * ), + $ V( LDV, * ), WORK( * ), WV( LDWV, * ), + $ Z( LDZ, * ) +* .. +* +* This subroutine is identical to DLAQR3 except that it avoids +* recursion by calling DLAHQR instead of DLAQR4. +* +* +* ****************************************************************** +* Aggressive early deflation: +* +* This subroutine accepts as input an upper Hessenberg matrix +* H and performs an orthogonal similarity transformation +* designed to detect and deflate fully converged eigenvalues from +* a trailing principal submatrix. On output H has been over- +* written by a new Hessenberg matrix that is a perturbation of +* an orthogonal similarity transformation of H. It is to be +* hoped that the final version of H has many zero subdiagonal +* entries. +* +* ****************************************************************** +* WANTT (input) LOGICAL +* If .TRUE., then the Hessenberg matrix H is fully updated +* so that the quasi-triangular Schur factor may be +* computed (in cooperation with the calling subroutine). +* If .FALSE., then only enough of H is updated to preserve +* the eigenvalues. +* +* WANTZ (input) LOGICAL +* If .TRUE., then the orthogonal matrix Z is updated so +* so that the orthogonal Schur factor may be computed +* (in cooperation with the calling subroutine). +* If .FALSE., then Z is not referenced. +* +* N (input) INTEGER +* The order of the matrix H and (if WANTZ is .TRUE.) the +* order of the orthogonal matrix Z. +* +* KTOP (input) INTEGER +* It is assumed that either KTOP = 1 or H(KTOP,KTOP-1)=0. +* KBOT and KTOP together determine an isolated block +* along the diagonal of the Hessenberg matrix. +* +* KBOT (input) INTEGER +* It is assumed without a check that either +* KBOT = N or H(KBOT+1,KBOT)=0. KBOT and KTOP together +* determine an isolated block along the diagonal of the +* Hessenberg matrix. +* +* NW (input) INTEGER +* Deflation window size. 1 .LE. NW .LE. (KBOT-KTOP+1). +* +* H (input/output) DOUBLE PRECISION array, dimension (LDH,N) +* On input the initial N-by-N section of H stores the +* Hessenberg matrix undergoing aggressive early deflation. +* On output H has been transformed by an orthogonal +* similarity transformation, perturbed, and the returned +* to Hessenberg form that (it is to be hoped) has some +* zero subdiagonal entries. +* +* LDH (input) integer +* Leading dimension of H just as declared in the calling +* subroutine. N .LE. LDH +* +* ILOZ (input) INTEGER +* IHIZ (input) INTEGER +* Specify the rows of Z to which transformations must be +* applied if WANTZ is .TRUE.. 1 .LE. ILOZ .LE. IHIZ .LE. N. +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N) +* IF WANTZ is .TRUE., then on output, the orthogonal +* similarity transformation mentioned above has been +* accumulated into Z(ILOZ:IHIZ,ILO:IHI) from the right. +* If WANTZ is .FALSE., then Z is unreferenced. +* +* LDZ (input) integer +* The leading dimension of Z just as declared in the +* calling subroutine. 1 .LE. LDZ. +* +* NS (output) integer +* The number of unconverged (ie approximate) eigenvalues +* returned in SR and SI that may be used as shifts by the +* calling subroutine. +* +* ND (output) integer +* The number of converged eigenvalues uncovered by this +* subroutine. +* +* SR (output) DOUBLE PRECISION array, dimension (KBOT) +* SI (output) DOUBLE PRECISION array, dimension (KBOT) +* On output, the real and imaginary parts of approximate +* eigenvalues that may be used for shifts are stored in +* SR(KBOT-ND-NS+1) through SR(KBOT-ND) and +* SI(KBOT-ND-NS+1) through SI(KBOT-ND), respectively. +* The real and imaginary parts of converged eigenvalues +* are stored in SR(KBOT-ND+1) through SR(KBOT) and +* SI(KBOT-ND+1) through SI(KBOT), respectively. +* +* V (workspace) DOUBLE PRECISION array, dimension (LDV,NW) +* An NW-by-NW work array. +* +* LDV (input) integer scalar +* The leading dimension of V just as declared in the +* calling subroutine. NW .LE. LDV +* +* NH (input) integer scalar +* The number of columns of T. NH.GE.NW. +* +* T (workspace) DOUBLE PRECISION array, dimension (LDT,NW) +* +* LDT (input) integer +* The leading dimension of T just as declared in the +* calling subroutine. NW .LE. LDT +* +* NV (input) integer +* The number of rows of work array WV available for +* workspace. NV.GE.NW. +* +* WV (workspace) DOUBLE PRECISION array, dimension (LDWV,NW) +* +* LDWV (input) integer +* The leading dimension of W just as declared in the +* calling subroutine. NW .LE. LDV +* +* WORK (workspace) DOUBLE PRECISION array, dimension (LWORK) +* On exit, WORK(1) is set to an estimate of the optimal value +* of LWORK for the given values of N, NW, KTOP and KBOT. +* +* LWORK (input) integer +* The dimension of the work array WORK. LWORK = 2*NW +* suffices, but greater efficiency may result from larger +* values of LWORK. +* +* If LWORK = -1, then a workspace query is assumed; DLAQR2 +* only estimates the optimal workspace size for the given +* values of N, NW, KTOP and KBOT. The estimate is returned +* in WORK(1). No error message related to LWORK is issued +* by XERBLA. Neither H nor Z are accessed. +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AA, BB, BETA, CC, CS, DD, EVI, EVK, FOO, S, + $ SAFMAX, SAFMIN, SMLNUM, SN, TAU, ULP + INTEGER I, IFST, ILST, INFO, INFQR, J, JW, K, KCOL, + $ KEND, KLN, KROW, KWTOP, LTOP, LWK1, LWK2, + $ LWKOPT + LOGICAL BULGE, SORTED +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DGEHRD, DGEMM, DLABAD, DLACPY, DLAHQR, + $ DLANV2, DLARF, DLARFG, DLASET, DORMHR, DTREXC +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, INT, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* ==== Estimate optimal workspace. ==== +* + JW = MIN( NW, KBOT-KTOP+1 ) + IF( JW.LE.2 ) THEN + LWKOPT = 1 + ELSE +* +* ==== Workspace query call to DGEHRD ==== +* + CALL DGEHRD( JW, 1, JW-1, T, LDT, WORK, WORK, -1, INFO ) + LWK1 = INT( WORK( 1 ) ) +* +* ==== Workspace query call to DORMHR ==== +* + CALL DORMHR( 'R', 'N', JW, JW, 1, JW-1, T, LDT, WORK, V, LDV, + $ WORK, -1, INFO ) + LWK2 = INT( WORK( 1 ) ) +* +* ==== Optimal workspace ==== +* + LWKOPT = JW + MAX( LWK1, LWK2 ) + END IF +* +* ==== Quick return in case of workspace query. ==== +* + IF( LWORK.EQ.-1 ) THEN + WORK( 1 ) = DBLE( LWKOPT ) + RETURN + END IF +* +* ==== Nothing to do ... +* ... for an empty active block ... ==== + NS = 0 + ND = 0 + WORK( 1 ) = ONE + IF( KTOP.GT.KBOT ) + $ RETURN +* ... nor for an empty deflation window. ==== + IF( NW.LT.1 ) + $ RETURN +* +* ==== Machine constants ==== +* + SAFMIN = DLAMCH( 'SAFE MINIMUM' ) + SAFMAX = ONE / SAFMIN + CALL DLABAD( SAFMIN, SAFMAX ) + ULP = DLAMCH( 'PRECISION' ) + SMLNUM = SAFMIN*( DBLE( N ) / ULP ) +* +* ==== Setup deflation window ==== +* + JW = MIN( NW, KBOT-KTOP+1 ) + KWTOP = KBOT - JW + 1 + IF( KWTOP.EQ.KTOP ) THEN + S = ZERO + ELSE + S = H( KWTOP, KWTOP-1 ) + END IF +* + IF( KBOT.EQ.KWTOP ) THEN +* +* ==== 1-by-1 deflation window: not much to do ==== +* + SR( KWTOP ) = H( KWTOP, KWTOP ) + SI( KWTOP ) = ZERO + NS = 1 + ND = 0 + IF( ABS( S ).LE.MAX( SMLNUM, ULP*ABS( H( KWTOP, KWTOP ) ) ) ) + $ THEN + NS = 0 + ND = 1 + IF( KWTOP.GT.KTOP ) + $ H( KWTOP, KWTOP-1 ) = ZERO + END IF + WORK( 1 ) = ONE + RETURN + END IF +* +* ==== Convert to spike-triangular form. (In case of a +* . rare QR failure, this routine continues to do +* . aggressive early deflation using that part of +* . the deflation window that converged using INFQR +* . here and there to keep track.) ==== +* + CALL DLACPY( 'U', JW, JW, H( KWTOP, KWTOP ), LDH, T, LDT ) + CALL DCOPY( JW-1, H( KWTOP+1, KWTOP ), LDH+1, T( 2, 1 ), LDT+1 ) +* + CALL DLASET( 'A', JW, JW, ZERO, ONE, V, LDV ) + CALL DLAHQR( .true., .true., JW, 1, JW, T, LDT, SR( KWTOP ), + $ SI( KWTOP ), 1, JW, V, LDV, INFQR ) +* +* ==== DTREXC needs a clean margin near the diagonal ==== +* + DO 10 J = 1, JW - 3 + T( J+2, J ) = ZERO + T( J+3, J ) = ZERO + 10 CONTINUE + IF( JW.GT.2 ) + $ T( JW, JW-2 ) = ZERO +* +* ==== Deflation detection loop ==== +* + NS = JW + ILST = INFQR + 1 + 20 CONTINUE + IF( ILST.LE.NS ) THEN + IF( NS.EQ.1 ) THEN + BULGE = .FALSE. + ELSE + BULGE = T( NS, NS-1 ).NE.ZERO + END IF +* +* ==== Small spike tip test for deflation ==== +* + IF( .NOT.BULGE ) THEN +* +* ==== Real eigenvalue ==== +* + FOO = ABS( T( NS, NS ) ) + IF( FOO.EQ.ZERO ) + $ FOO = ABS( S ) + IF( ABS( S*V( 1, NS ) ).LE.MAX( SMLNUM, ULP*FOO ) ) THEN +* +* ==== Deflatable ==== +* + NS = NS - 1 + ELSE +* +* ==== Undeflatable. Move it up out of the way. +* . (DTREXC can not fail in this case.) ==== +* + IFST = NS + CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK, + $ INFO ) + ILST = ILST + 1 + END IF + ELSE +* +* ==== Complex conjugate pair ==== +* + FOO = ABS( T( NS, NS ) ) + SQRT( ABS( T( NS, NS-1 ) ) )* + $ SQRT( ABS( T( NS-1, NS ) ) ) + IF( FOO.EQ.ZERO ) + $ FOO = ABS( S ) + IF( MAX( ABS( S*V( 1, NS ) ), ABS( S*V( 1, NS-1 ) ) ).LE. + $ MAX( SMLNUM, ULP*FOO ) ) THEN +* +* ==== Deflatable ==== +* + NS = NS - 2 + ELSE +* +* ==== Undeflatable. Move them up out of the way. +* . Fortunately, DTREXC does the right thing with +* . ILST in case of a rare exchange failure. ==== +* + IFST = NS + CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK, + $ INFO ) + ILST = ILST + 2 + END IF + END IF +* +* ==== End deflation detection loop ==== +* + GO TO 20 + END IF +* +* ==== Return to Hessenberg form ==== +* + IF( NS.EQ.0 ) + $ S = ZERO +* + IF( NS.LT.JW ) THEN +* +* ==== sorting diagonal blocks of T improves accuracy for +* . graded matrices. Bubble sort deals well with +* . exchange failures. ==== +* + SORTED = .false. + I = NS + 1 + 30 CONTINUE + IF( SORTED ) + $ GO TO 50 + SORTED = .true. +* + KEND = I - 1 + I = INFQR + 1 + IF( I.EQ.NS ) THEN + K = I + 1 + ELSE IF( T( I+1, I ).EQ.ZERO ) THEN + K = I + 1 + ELSE + K = I + 2 + END IF + 40 CONTINUE + IF( K.LE.KEND ) THEN + IF( K.EQ.I+1 ) THEN + EVI = ABS( T( I, I ) ) + ELSE + EVI = ABS( T( I, I ) ) + SQRT( ABS( T( I+1, I ) ) )* + $ SQRT( ABS( T( I, I+1 ) ) ) + END IF +* + IF( K.EQ.KEND ) THEN + EVK = ABS( T( K, K ) ) + ELSE IF( T( K+1, K ).EQ.ZERO ) THEN + EVK = ABS( T( K, K ) ) + ELSE + EVK = ABS( T( K, K ) ) + SQRT( ABS( T( K+1, K ) ) )* + $ SQRT( ABS( T( K, K+1 ) ) ) + END IF +* + IF( EVI.GE.EVK ) THEN + I = K + ELSE + SORTED = .false. + IFST = I + ILST = K + CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK, + $ INFO ) + IF( INFO.EQ.0 ) THEN + I = ILST + ELSE + I = K + END IF + END IF + IF( I.EQ.KEND ) THEN + K = I + 1 + ELSE IF( T( I+1, I ).EQ.ZERO ) THEN + K = I + 1 + ELSE + K = I + 2 + END IF + GO TO 40 + END IF + GO TO 30 + 50 CONTINUE + END IF +* +* ==== Restore shift/eigenvalue array from T ==== +* + I = JW + 60 CONTINUE + IF( I.GE.INFQR+1 ) THEN + IF( I.EQ.INFQR+1 ) THEN + SR( KWTOP+I-1 ) = T( I, I ) + SI( KWTOP+I-1 ) = ZERO + I = I - 1 + ELSE IF( T( I, I-1 ).EQ.ZERO ) THEN + SR( KWTOP+I-1 ) = T( I, I ) + SI( KWTOP+I-1 ) = ZERO + I = I - 1 + ELSE + AA = T( I-1, I-1 ) + CC = T( I, I-1 ) + BB = T( I-1, I ) + DD = T( I, I ) + CALL DLANV2( AA, BB, CC, DD, SR( KWTOP+I-2 ), + $ SI( KWTOP+I-2 ), SR( KWTOP+I-1 ), + $ SI( KWTOP+I-1 ), CS, SN ) + I = I - 2 + END IF + GO TO 60 + END IF +* + IF( NS.LT.JW .OR. S.EQ.ZERO ) THEN + IF( NS.GT.1 .AND. S.NE.ZERO ) THEN +* +* ==== Reflect spike back into lower triangle ==== +* + CALL DCOPY( NS, V, LDV, WORK, 1 ) + BETA = WORK( 1 ) + CALL DLARFG( NS, BETA, WORK( 2 ), 1, TAU ) + WORK( 1 ) = ONE +* + CALL DLASET( 'L', JW-2, JW-2, ZERO, ZERO, T( 3, 1 ), LDT ) +* + CALL DLARF( 'L', NS, JW, WORK, 1, TAU, T, LDT, + $ WORK( JW+1 ) ) + CALL DLARF( 'R', NS, NS, WORK, 1, TAU, T, LDT, + $ WORK( JW+1 ) ) + CALL DLARF( 'R', JW, NS, WORK, 1, TAU, V, LDV, + $ WORK( JW+1 ) ) +* + CALL DGEHRD( JW, 1, NS, T, LDT, WORK, WORK( JW+1 ), + $ LWORK-JW, INFO ) + END IF +* +* ==== Copy updated reduced window into place ==== +* + IF( KWTOP.GT.1 ) + $ H( KWTOP, KWTOP-1 ) = S*V( 1, 1 ) + CALL DLACPY( 'U', JW, JW, T, LDT, H( KWTOP, KWTOP ), LDH ) + CALL DCOPY( JW-1, T( 2, 1 ), LDT+1, H( KWTOP+1, KWTOP ), + $ LDH+1 ) +* +* ==== Accumulate orthogonal matrix in order update +* . H and Z, if requested. ==== +* + IF( NS.GT.1 .AND. S.NE.ZERO ) + $ CALL DORMHR( 'R', 'N', JW, NS, 1, NS, T, LDT, WORK, V, LDV, + $ WORK( JW+1 ), LWORK-JW, INFO ) +* +* ==== Update vertical slab in H ==== +* + IF( WANTT ) THEN + LTOP = 1 + ELSE + LTOP = KTOP + END IF + DO 70 KROW = LTOP, KWTOP - 1, NV + KLN = MIN( NV, KWTOP-KROW ) + CALL DGEMM( 'N', 'N', KLN, JW, JW, ONE, H( KROW, KWTOP ), + $ LDH, V, LDV, ZERO, WV, LDWV ) + CALL DLACPY( 'A', KLN, JW, WV, LDWV, H( KROW, KWTOP ), LDH ) + 70 CONTINUE +* +* ==== Update horizontal slab in H ==== +* + IF( WANTT ) THEN + DO 80 KCOL = KBOT + 1, N, NH + KLN = MIN( NH, N-KCOL+1 ) + CALL DGEMM( 'C', 'N', JW, KLN, JW, ONE, V, LDV, + $ H( KWTOP, KCOL ), LDH, ZERO, T, LDT ) + CALL DLACPY( 'A', JW, KLN, T, LDT, H( KWTOP, KCOL ), + $ LDH ) + 80 CONTINUE + END IF +* +* ==== Update vertical slab in Z ==== +* + IF( WANTZ ) THEN + DO 90 KROW = ILOZ, IHIZ, NV + KLN = MIN( NV, IHIZ-KROW+1 ) + CALL DGEMM( 'N', 'N', KLN, JW, JW, ONE, Z( KROW, KWTOP ), + $ LDZ, V, LDV, ZERO, WV, LDWV ) + CALL DLACPY( 'A', KLN, JW, WV, LDWV, Z( KROW, KWTOP ), + $ LDZ ) + 90 CONTINUE + END IF + END IF +* +* ==== Return the number of deflations ... ==== +* + ND = JW - NS +* +* ==== ... and the number of shifts. (Subtracting +* . INFQR from the spike length takes care +* . of the case of a rare QR failure while +* . calculating eigenvalues of the deflation +* . window.) ==== +* + NS = NS - INFQR +* +* ==== Return optimal workspace. ==== +* + WORK( 1 ) = DBLE( LWKOPT ) +* +* ==== End of DLAQR2 ==== +* + END diff --git a/dep/lapack/dlaqr3.f b/dep/lapack/dlaqr3.f new file mode 100644 index 00000000..2bcd852c --- /dev/null +++ b/dep/lapack/dlaqr3.f @@ -0,0 +1,557 @@ + SUBROUTINE DLAQR3( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ, + $ IHIZ, Z, LDZ, NS, ND, SR, SI, V, LDV, NH, T, + $ LDT, NV, WV, LDWV, WORK, LWORK ) +* +* -- LAPACK auxiliary routine (version 3.2.2) -- +* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +* -- June 2010 -- +* +* .. Scalar Arguments .. + INTEGER IHIZ, ILOZ, KBOT, KTOP, LDH, LDT, LDV, LDWV, + $ LDZ, LWORK, N, ND, NH, NS, NV, NW + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), T( LDT, * ), + $ V( LDV, * ), WORK( * ), WV( LDWV, * ), + $ Z( LDZ, * ) +* .. +* +* ****************************************************************** +* Aggressive early deflation: +* +* This subroutine accepts as input an upper Hessenberg matrix +* H and performs an orthogonal similarity transformation +* designed to detect and deflate fully converged eigenvalues from +* a trailing principal submatrix. On output H has been over- +* written by a new Hessenberg matrix that is a perturbation of +* an orthogonal similarity transformation of H. It is to be +* hoped that the final version of H has many zero subdiagonal +* entries. +* +* ****************************************************************** +* WANTT (input) LOGICAL +* If .TRUE., then the Hessenberg matrix H is fully updated +* so that the quasi-triangular Schur factor may be +* computed (in cooperation with the calling subroutine). +* If .FALSE., then only enough of H is updated to preserve +* the eigenvalues. +* +* WANTZ (input) LOGICAL +* If .TRUE., then the orthogonal matrix Z is updated so +* so that the orthogonal Schur factor may be computed +* (in cooperation with the calling subroutine). +* If .FALSE., then Z is not referenced. +* +* N (input) INTEGER +* The order of the matrix H and (if WANTZ is .TRUE.) the +* order of the orthogonal matrix Z. +* +* KTOP (input) INTEGER +* It is assumed that either KTOP = 1 or H(KTOP,KTOP-1)=0. +* KBOT and KTOP together determine an isolated block +* along the diagonal of the Hessenberg matrix. +* +* KBOT (input) INTEGER +* It is assumed without a check that either +* KBOT = N or H(KBOT+1,KBOT)=0. KBOT and KTOP together +* determine an isolated block along the diagonal of the +* Hessenberg matrix. +* +* NW (input) INTEGER +* Deflation window size. 1 .LE. NW .LE. (KBOT-KTOP+1). +* +* H (input/output) DOUBLE PRECISION array, dimension (LDH,N) +* On input the initial N-by-N section of H stores the +* Hessenberg matrix undergoing aggressive early deflation. +* On output H has been transformed by an orthogonal +* similarity transformation, perturbed, and the returned +* to Hessenberg form that (it is to be hoped) has some +* zero subdiagonal entries. +* +* LDH (input) integer +* Leading dimension of H just as declared in the calling +* subroutine. N .LE. LDH +* +* ILOZ (input) INTEGER +* IHIZ (input) INTEGER +* Specify the rows of Z to which transformations must be +* applied if WANTZ is .TRUE.. 1 .LE. ILOZ .LE. IHIZ .LE. N. +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N) +* IF WANTZ is .TRUE., then on output, the orthogonal +* similarity transformation mentioned above has been +* accumulated into Z(ILOZ:IHIZ,ILO:IHI) from the right. +* If WANTZ is .FALSE., then Z is unreferenced. +* +* LDZ (input) integer +* The leading dimension of Z just as declared in the +* calling subroutine. 1 .LE. LDZ. +* +* NS (output) integer +* The number of unconverged (ie approximate) eigenvalues +* returned in SR and SI that may be used as shifts by the +* calling subroutine. +* +* ND (output) integer +* The number of converged eigenvalues uncovered by this +* subroutine. +* +* SR (output) DOUBLE PRECISION array, dimension (KBOT) +* SI (output) DOUBLE PRECISION array, dimension (KBOT) +* On output, the real and imaginary parts of approximate +* eigenvalues that may be used for shifts are stored in +* SR(KBOT-ND-NS+1) through SR(KBOT-ND) and +* SI(KBOT-ND-NS+1) through SI(KBOT-ND), respectively. +* The real and imaginary parts of converged eigenvalues +* are stored in SR(KBOT-ND+1) through SR(KBOT) and +* SI(KBOT-ND+1) through SI(KBOT), respectively. +* +* V (workspace) DOUBLE PRECISION array, dimension (LDV,NW) +* An NW-by-NW work array. +* +* LDV (input) integer scalar +* The leading dimension of V just as declared in the +* calling subroutine. NW .LE. LDV +* +* NH (input) integer scalar +* The number of columns of T. NH.GE.NW. +* +* T (workspace) DOUBLE PRECISION array, dimension (LDT,NW) +* +* LDT (input) integer +* The leading dimension of T just as declared in the +* calling subroutine. NW .LE. LDT +* +* NV (input) integer +* The number of rows of work array WV available for +* workspace. NV.GE.NW. +* +* WV (workspace) DOUBLE PRECISION array, dimension (LDWV,NW) +* +* LDWV (input) integer +* The leading dimension of W just as declared in the +* calling subroutine. NW .LE. LDV +* +* WORK (workspace) DOUBLE PRECISION array, dimension (LWORK) +* On exit, WORK(1) is set to an estimate of the optimal value +* of LWORK for the given values of N, NW, KTOP and KBOT. +* +* LWORK (input) integer +* The dimension of the work array WORK. LWORK = 2*NW +* suffices, but greater efficiency may result from larger +* values of LWORK. +* +* If LWORK = -1, then a workspace query is assumed; DLAQR3 +* only estimates the optimal workspace size for the given +* values of N, NW, KTOP and KBOT. The estimate is returned +* in WORK(1). No error message related to LWORK is issued +* by XERBLA. Neither H nor Z are accessed. +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AA, BB, BETA, CC, CS, DD, EVI, EVK, FOO, S, + $ SAFMAX, SAFMIN, SMLNUM, SN, TAU, ULP + INTEGER I, IFST, ILST, INFO, INFQR, J, JW, K, KCOL, + $ KEND, KLN, KROW, KWTOP, LTOP, LWK1, LWK2, LWK3, + $ LWKOPT, NMIN + LOGICAL BULGE, SORTED +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + INTEGER ILAENV + EXTERNAL DLAMCH, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DGEHRD, DGEMM, DLABAD, DLACPY, DLAHQR, + $ DLANV2, DLAQR4, DLARF, DLARFG, DLASET, DORMHR, + $ DTREXC +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, INT, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* ==== Estimate optimal workspace. ==== +* + JW = MIN( NW, KBOT-KTOP+1 ) + IF( JW.LE.2 ) THEN + LWKOPT = 1 + ELSE +* +* ==== Workspace query call to DGEHRD ==== +* + CALL DGEHRD( JW, 1, JW-1, T, LDT, WORK, WORK, -1, INFO ) + LWK1 = INT( WORK( 1 ) ) +* +* ==== Workspace query call to DORMHR ==== +* + CALL DORMHR( 'R', 'N', JW, JW, 1, JW-1, T, LDT, WORK, V, LDV, + $ WORK, -1, INFO ) + LWK2 = INT( WORK( 1 ) ) +* +* ==== Workspace query call to DLAQR4 ==== +* + CALL DLAQR4( .true., .true., JW, 1, JW, T, LDT, SR, SI, 1, JW, + $ V, LDV, WORK, -1, INFQR ) + LWK3 = INT( WORK( 1 ) ) +* +* ==== Optimal workspace ==== +* + LWKOPT = MAX( JW+MAX( LWK1, LWK2 ), LWK3 ) + END IF +* +* ==== Quick return in case of workspace query. ==== +* + IF( LWORK.EQ.-1 ) THEN + WORK( 1 ) = DBLE( LWKOPT ) + RETURN + END IF +* +* ==== Nothing to do ... +* ... for an empty active block ... ==== + NS = 0 + ND = 0 + WORK( 1 ) = ONE + IF( KTOP.GT.KBOT ) + $ RETURN +* ... nor for an empty deflation window. ==== + IF( NW.LT.1 ) + $ RETURN +* +* ==== Machine constants ==== +* + SAFMIN = DLAMCH( 'SAFE MINIMUM' ) + SAFMAX = ONE / SAFMIN + CALL DLABAD( SAFMIN, SAFMAX ) + ULP = DLAMCH( 'PRECISION' ) + SMLNUM = SAFMIN*( DBLE( N ) / ULP ) +* +* ==== Setup deflation window ==== +* + JW = MIN( NW, KBOT-KTOP+1 ) + KWTOP = KBOT - JW + 1 + IF( KWTOP.EQ.KTOP ) THEN + S = ZERO + ELSE + S = H( KWTOP, KWTOP-1 ) + END IF +* + IF( KBOT.EQ.KWTOP ) THEN +* +* ==== 1-by-1 deflation window: not much to do ==== +* + SR( KWTOP ) = H( KWTOP, KWTOP ) + SI( KWTOP ) = ZERO + NS = 1 + ND = 0 + IF( ABS( S ).LE.MAX( SMLNUM, ULP*ABS( H( KWTOP, KWTOP ) ) ) ) + $ THEN + NS = 0 + ND = 1 + IF( KWTOP.GT.KTOP ) + $ H( KWTOP, KWTOP-1 ) = ZERO + END IF + WORK( 1 ) = ONE + RETURN + END IF +* +* ==== Convert to spike-triangular form. (In case of a +* . rare QR failure, this routine continues to do +* . aggressive early deflation using that part of +* . the deflation window that converged using INFQR +* . here and there to keep track.) ==== +* + CALL DLACPY( 'U', JW, JW, H( KWTOP, KWTOP ), LDH, T, LDT ) + CALL DCOPY( JW-1, H( KWTOP+1, KWTOP ), LDH+1, T( 2, 1 ), LDT+1 ) +* + CALL DLASET( 'A', JW, JW, ZERO, ONE, V, LDV ) + NMIN = ILAENV( 12, 'DLAQR3', 'SV', JW, 1, JW, LWORK ) + IF( JW.GT.NMIN ) THEN + CALL DLAQR4( .true., .true., JW, 1, JW, T, LDT, SR( KWTOP ), + $ SI( KWTOP ), 1, JW, V, LDV, WORK, LWORK, INFQR ) + ELSE + CALL DLAHQR( .true., .true., JW, 1, JW, T, LDT, SR( KWTOP ), + $ SI( KWTOP ), 1, JW, V, LDV, INFQR ) + END IF +* +* ==== DTREXC needs a clean margin near the diagonal ==== +* + DO 10 J = 1, JW - 3 + T( J+2, J ) = ZERO + T( J+3, J ) = ZERO + 10 CONTINUE + IF( JW.GT.2 ) + $ T( JW, JW-2 ) = ZERO +* +* ==== Deflation detection loop ==== +* + NS = JW + ILST = INFQR + 1 + 20 CONTINUE + IF( ILST.LE.NS ) THEN + IF( NS.EQ.1 ) THEN + BULGE = .FALSE. + ELSE + BULGE = T( NS, NS-1 ).NE.ZERO + END IF +* +* ==== Small spike tip test for deflation ==== +* + IF( .NOT.BULGE ) THEN +* +* ==== Real eigenvalue ==== +* + FOO = ABS( T( NS, NS ) ) + IF( FOO.EQ.ZERO ) + $ FOO = ABS( S ) + IF( ABS( S*V( 1, NS ) ).LE.MAX( SMLNUM, ULP*FOO ) ) THEN +* +* ==== Deflatable ==== +* + NS = NS - 1 + ELSE +* +* ==== Undeflatable. Move it up out of the way. +* . (DTREXC can not fail in this case.) ==== +* + IFST = NS + CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK, + $ INFO ) + ILST = ILST + 1 + END IF + ELSE +* +* ==== Complex conjugate pair ==== +* + FOO = ABS( T( NS, NS ) ) + SQRT( ABS( T( NS, NS-1 ) ) )* + $ SQRT( ABS( T( NS-1, NS ) ) ) + IF( FOO.EQ.ZERO ) + $ FOO = ABS( S ) + IF( MAX( ABS( S*V( 1, NS ) ), ABS( S*V( 1, NS-1 ) ) ).LE. + $ MAX( SMLNUM, ULP*FOO ) ) THEN +* +* ==== Deflatable ==== +* + NS = NS - 2 + ELSE +* +* ==== Undeflatable. Move them up out of the way. +* . Fortunately, DTREXC does the right thing with +* . ILST in case of a rare exchange failure. ==== +* + IFST = NS + CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK, + $ INFO ) + ILST = ILST + 2 + END IF + END IF +* +* ==== End deflation detection loop ==== +* + GO TO 20 + END IF +* +* ==== Return to Hessenberg form ==== +* + IF( NS.EQ.0 ) + $ S = ZERO +* + IF( NS.LT.JW ) THEN +* +* ==== sorting diagonal blocks of T improves accuracy for +* . graded matrices. Bubble sort deals well with +* . exchange failures. ==== +* + SORTED = .false. + I = NS + 1 + 30 CONTINUE + IF( SORTED ) + $ GO TO 50 + SORTED = .true. +* + KEND = I - 1 + I = INFQR + 1 + IF( I.EQ.NS ) THEN + K = I + 1 + ELSE IF( T( I+1, I ).EQ.ZERO ) THEN + K = I + 1 + ELSE + K = I + 2 + END IF + 40 CONTINUE + IF( K.LE.KEND ) THEN + IF( K.EQ.I+1 ) THEN + EVI = ABS( T( I, I ) ) + ELSE + EVI = ABS( T( I, I ) ) + SQRT( ABS( T( I+1, I ) ) )* + $ SQRT( ABS( T( I, I+1 ) ) ) + END IF +* + IF( K.EQ.KEND ) THEN + EVK = ABS( T( K, K ) ) + ELSE IF( T( K+1, K ).EQ.ZERO ) THEN + EVK = ABS( T( K, K ) ) + ELSE + EVK = ABS( T( K, K ) ) + SQRT( ABS( T( K+1, K ) ) )* + $ SQRT( ABS( T( K, K+1 ) ) ) + END IF +* + IF( EVI.GE.EVK ) THEN + I = K + ELSE + SORTED = .false. + IFST = I + ILST = K + CALL DTREXC( 'V', JW, T, LDT, V, LDV, IFST, ILST, WORK, + $ INFO ) + IF( INFO.EQ.0 ) THEN + I = ILST + ELSE + I = K + END IF + END IF + IF( I.EQ.KEND ) THEN + K = I + 1 + ELSE IF( T( I+1, I ).EQ.ZERO ) THEN + K = I + 1 + ELSE + K = I + 2 + END IF + GO TO 40 + END IF + GO TO 30 + 50 CONTINUE + END IF +* +* ==== Restore shift/eigenvalue array from T ==== +* + I = JW + 60 CONTINUE + IF( I.GE.INFQR+1 ) THEN + IF( I.EQ.INFQR+1 ) THEN + SR( KWTOP+I-1 ) = T( I, I ) + SI( KWTOP+I-1 ) = ZERO + I = I - 1 + ELSE IF( T( I, I-1 ).EQ.ZERO ) THEN + SR( KWTOP+I-1 ) = T( I, I ) + SI( KWTOP+I-1 ) = ZERO + I = I - 1 + ELSE + AA = T( I-1, I-1 ) + CC = T( I, I-1 ) + BB = T( I-1, I ) + DD = T( I, I ) + CALL DLANV2( AA, BB, CC, DD, SR( KWTOP+I-2 ), + $ SI( KWTOP+I-2 ), SR( KWTOP+I-1 ), + $ SI( KWTOP+I-1 ), CS, SN ) + I = I - 2 + END IF + GO TO 60 + END IF +* + IF( NS.LT.JW .OR. S.EQ.ZERO ) THEN + IF( NS.GT.1 .AND. S.NE.ZERO ) THEN +* +* ==== Reflect spike back into lower triangle ==== +* + CALL DCOPY( NS, V, LDV, WORK, 1 ) + BETA = WORK( 1 ) + CALL DLARFG( NS, BETA, WORK( 2 ), 1, TAU ) + WORK( 1 ) = ONE +* + CALL DLASET( 'L', JW-2, JW-2, ZERO, ZERO, T( 3, 1 ), LDT ) +* + CALL DLARF( 'L', NS, JW, WORK, 1, TAU, T, LDT, + $ WORK( JW+1 ) ) + CALL DLARF( 'R', NS, NS, WORK, 1, TAU, T, LDT, + $ WORK( JW+1 ) ) + CALL DLARF( 'R', JW, NS, WORK, 1, TAU, V, LDV, + $ WORK( JW+1 ) ) +* + CALL DGEHRD( JW, 1, NS, T, LDT, WORK, WORK( JW+1 ), + $ LWORK-JW, INFO ) + END IF +* +* ==== Copy updated reduced window into place ==== +* + IF( KWTOP.GT.1 ) + $ H( KWTOP, KWTOP-1 ) = S*V( 1, 1 ) + CALL DLACPY( 'U', JW, JW, T, LDT, H( KWTOP, KWTOP ), LDH ) + CALL DCOPY( JW-1, T( 2, 1 ), LDT+1, H( KWTOP+1, KWTOP ), + $ LDH+1 ) +* +* ==== Accumulate orthogonal matrix in order update +* . H and Z, if requested. ==== +* + IF( NS.GT.1 .AND. S.NE.ZERO ) + $ CALL DORMHR( 'R', 'N', JW, NS, 1, NS, T, LDT, WORK, V, LDV, + $ WORK( JW+1 ), LWORK-JW, INFO ) +* +* ==== Update vertical slab in H ==== +* + IF( WANTT ) THEN + LTOP = 1 + ELSE + LTOP = KTOP + END IF + DO 70 KROW = LTOP, KWTOP - 1, NV + KLN = MIN( NV, KWTOP-KROW ) + CALL DGEMM( 'N', 'N', KLN, JW, JW, ONE, H( KROW, KWTOP ), + $ LDH, V, LDV, ZERO, WV, LDWV ) + CALL DLACPY( 'A', KLN, JW, WV, LDWV, H( KROW, KWTOP ), LDH ) + 70 CONTINUE +* +* ==== Update horizontal slab in H ==== +* + IF( WANTT ) THEN + DO 80 KCOL = KBOT + 1, N, NH + KLN = MIN( NH, N-KCOL+1 ) + CALL DGEMM( 'C', 'N', JW, KLN, JW, ONE, V, LDV, + $ H( KWTOP, KCOL ), LDH, ZERO, T, LDT ) + CALL DLACPY( 'A', JW, KLN, T, LDT, H( KWTOP, KCOL ), + $ LDH ) + 80 CONTINUE + END IF +* +* ==== Update vertical slab in Z ==== +* + IF( WANTZ ) THEN + DO 90 KROW = ILOZ, IHIZ, NV + KLN = MIN( NV, IHIZ-KROW+1 ) + CALL DGEMM( 'N', 'N', KLN, JW, JW, ONE, Z( KROW, KWTOP ), + $ LDZ, V, LDV, ZERO, WV, LDWV ) + CALL DLACPY( 'A', KLN, JW, WV, LDWV, Z( KROW, KWTOP ), + $ LDZ ) + 90 CONTINUE + END IF + END IF +* +* ==== Return the number of deflations ... ==== +* + ND = JW - NS +* +* ==== ... and the number of shifts. (Subtracting +* . INFQR from the spike length takes care +* . of the case of a rare QR failure while +* . calculating eigenvalues of the deflation +* . window.) ==== +* + NS = NS - INFQR +* +* ==== Return optimal workspace. ==== +* + WORK( 1 ) = DBLE( LWKOPT ) +* +* ==== End of DLAQR3 ==== +* + END diff --git a/dep/lapack/dlaqr4.f b/dep/lapack/dlaqr4.f new file mode 100644 index 00000000..31b77d1f --- /dev/null +++ b/dep/lapack/dlaqr4.f @@ -0,0 +1,637 @@ + SUBROUTINE DLAQR4( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, + $ ILOZ, IHIZ, Z, LDZ, WORK, LWORK, INFO ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, LWORK, N + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), WI( * ), WORK( * ), WR( * ), + $ Z( LDZ, * ) +* .. +* +* This subroutine implements one level of recursion for DLAQR0. +* It is a complete implementation of the small bulge multi-shift +* QR algorithm. It may be called by DLAQR0 and, for large enough +* deflation window size, it may be called by DLAQR3. This +* subroutine is identical to DLAQR0 except that it calls DLAQR2 +* instead of DLAQR3. +* +* Purpose +* ======= +* +* DLAQR4 computes the eigenvalues of a Hessenberg matrix H +* and, optionally, the matrices T and Z from the Schur decomposition +* H = Z T Z**T, where T is an upper quasi-triangular matrix (the +* Schur form), and Z is the orthogonal matrix of Schur vectors. +* +* Optionally Z may be postmultiplied into an input orthogonal +* matrix Q so that this routine can give the Schur factorization +* of a matrix A which has been reduced to the Hessenberg form H +* by the orthogonal matrix Q: A = Q*H*Q**T = (QZ)*T*(QZ)**T. +* +* Arguments +* ========= +* +* WANTT (input) LOGICAL +* = .TRUE. : the full Schur form T is required; +* = .FALSE.: only eigenvalues are required. +* +* WANTZ (input) LOGICAL +* = .TRUE. : the matrix of Schur vectors Z is required; +* = .FALSE.: Schur vectors are not required. +* +* N (input) INTEGER +* The order of the matrix H. N .GE. 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* It is assumed that H is already upper triangular in rows +* and columns 1:ILO-1 and IHI+1:N and, if ILO.GT.1, +* H(ILO,ILO-1) is zero. ILO and IHI are normally set by a +* previous call to DGEBAL, and then passed to DGEHRD when the +* matrix output by DGEBAL is reduced to Hessenberg form. +* Otherwise, ILO and IHI should be set to 1 and N, +* respectively. If N.GT.0, then 1.LE.ILO.LE.IHI.LE.N. +* If N = 0, then ILO = 1 and IHI = 0. +* +* H (input/output) DOUBLE PRECISION array, dimension (LDH,N) +* On entry, the upper Hessenberg matrix H. +* On exit, if INFO = 0 and WANTT is .TRUE., then H contains +* the upper quasi-triangular matrix T from the Schur +* decomposition (the Schur form); 2-by-2 diagonal blocks +* (corresponding to complex conjugate pairs of eigenvalues) +* are returned in standard form, with H(i,i) = H(i+1,i+1) +* and H(i+1,i)*H(i,i+1).LT.0. If INFO = 0 and WANTT is +* .FALSE., then the contents of H are unspecified on exit. +* (The output value of H when INFO.GT.0 is given under the +* description of INFO below.) +* +* This subroutine may explicitly set H(i,j) = 0 for i.GT.j and +* j = 1, 2, ... ILO-1 or j = IHI+1, IHI+2, ... N. +* +* LDH (input) INTEGER +* The leading dimension of the array H. LDH .GE. max(1,N). +* +* WR (output) DOUBLE PRECISION array, dimension (IHI) +* WI (output) DOUBLE PRECISION array, dimension (IHI) +* The real and imaginary parts, respectively, of the computed +* eigenvalues of H(ILO:IHI,ILO:IHI) are stored in WR(ILO:IHI) +* and WI(ILO:IHI). If two eigenvalues are computed as a +* complex conjugate pair, they are stored in consecutive +* elements of WR and WI, say the i-th and (i+1)th, with +* WI(i) .GT. 0 and WI(i+1) .LT. 0. If WANTT is .TRUE., then +* the eigenvalues are stored in the same order as on the +* diagonal of the Schur form returned in H, with +* WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 diagonal +* block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and +* WI(i+1) = -WI(i). +* +* ILOZ (input) INTEGER +* IHIZ (input) INTEGER +* Specify the rows of Z to which transformations must be +* applied if WANTZ is .TRUE.. +* 1 .LE. ILOZ .LE. ILO; IHI .LE. IHIZ .LE. N. +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,IHI) +* If WANTZ is .FALSE., then Z is not referenced. +* If WANTZ is .TRUE., then Z(ILO:IHI,ILOZ:IHIZ) is +* replaced by Z(ILO:IHI,ILOZ:IHIZ)*U where U is the +* orthogonal Schur factor of H(ILO:IHI,ILO:IHI). +* (The output value of Z when INFO.GT.0 is given under +* the description of INFO below.) +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. if WANTZ is .TRUE. +* then LDZ.GE.MAX(1,IHIZ). Otherwize, LDZ.GE.1. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension LWORK +* On exit, if LWORK = -1, WORK(1) returns an estimate of +* the optimal value for LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK .GE. max(1,N) +* is sufficient, but LWORK typically as large as 6*N may +* be required for optimal performance. A workspace query +* to determine the optimal workspace size is recommended. +* +* If LWORK = -1, then DLAQR4 does a workspace query. +* In this case, DLAQR4 checks the input parameters and +* estimates the optimal workspace size for the given +* values of N, ILO and IHI. The estimate is returned +* in WORK(1). No error message related to LWORK is +* issued by XERBLA. Neither H nor Z are accessed. +* +* +* INFO (output) INTEGER +* = 0: successful exit +* .GT. 0: if INFO = i, DLAQR4 failed to compute all of +* the eigenvalues. Elements 1:ilo-1 and i+1:n of WR +* and WI contain those eigenvalues which have been +* successfully computed. (Failures are rare.) +* +* If INFO .GT. 0 and WANT is .FALSE., then on exit, +* the remaining unconverged eigenvalues are the eigen- +* values of the upper Hessenberg matrix rows and +* columns ILO through INFO of the final, output +* value of H. +* +* If INFO .GT. 0 and WANTT is .TRUE., then on exit +* +* (*) (initial value of H)*U = U*(final value of H) +* +* where U is an orthogonal matrix. The final +* value of H is upper Hessenberg and quasi-triangular +* in rows and columns INFO+1 through IHI. +* +* If INFO .GT. 0 and WANTZ is .TRUE., then on exit +* +* (final value of Z(ILO:IHI,ILOZ:IHIZ) +* = (initial value of Z(ILO:IHI,ILOZ:IHIZ)*U +* +* where U is the orthogonal matrix in (*) (regard- +* less of the value of WANTT.) +* +* If INFO .GT. 0 and WANTZ is .FALSE., then Z is not +* accessed. +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* References: +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 +* Performance, SIAM Journal of Matrix Analysis, volume 23, pages +* 929--947, 2002. +* +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part II: Aggressive Early Deflation, SIAM Journal +* of Matrix Analysis, volume 23, pages 948--973, 2002. +* +* ================================================================ +* .. Parameters .. +* +* ==== Matrices of order NTINY or smaller must be processed by +* . DLAHQR because of insufficient subdiagonal scratch space. +* . (This is a hard limit.) ==== + INTEGER NTINY + PARAMETER ( NTINY = 11 ) +* +* ==== Exceptional deflation windows: try to cure rare +* . slow convergence by varying the size of the +* . deflation window after KEXNW iterations. ==== + INTEGER KEXNW + PARAMETER ( KEXNW = 5 ) +* +* ==== Exceptional shifts: try to cure rare slow convergence +* . with ad-hoc exceptional shifts every KEXSH iterations. +* . ==== + INTEGER KEXSH + PARAMETER ( KEXSH = 6 ) +* +* ==== The constants WILK1 and WILK2 are used to form the +* . exceptional shifts. ==== + DOUBLE PRECISION WILK1, WILK2 + PARAMETER ( WILK1 = 0.75d0, WILK2 = -0.4375d0 ) + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AA, BB, CC, CS, DD, SN, SS, SWAP + INTEGER I, INF, IT, ITMAX, K, KACC22, KBOT, KDU, KS, + $ KT, KTOP, KU, KV, KWH, KWTOP, KWV, LD, LS, + $ LWKOPT, NDEC, NDFL, NH, NHO, NIBBLE, NMIN, NS, + $ NSMAX, NSR, NVE, NW, NWMAX, NWR, NWUPBD + LOGICAL SORTED + CHARACTER JBCMPZ*2 +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Local Arrays .. + DOUBLE PRECISION ZDUM( 1, 1 ) +* .. +* .. External Subroutines .. + EXTERNAL DLACPY, DLAHQR, DLANV2, DLAQR2, DLAQR5 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, INT, MAX, MIN, MOD +* .. +* .. Executable Statements .. + INFO = 0 +* +* ==== Quick return for N = 0: nothing to do. ==== +* + IF( N.EQ.0 ) THEN + WORK( 1 ) = ONE + RETURN + END IF +* + IF( N.LE.NTINY ) THEN +* +* ==== Tiny matrices must use DLAHQR. ==== +* + LWKOPT = 1 + IF( LWORK.NE.-1 ) + $ CALL DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI, + $ ILOZ, IHIZ, Z, LDZ, INFO ) + ELSE +* +* ==== Use small bulge multi-shift QR with aggressive early +* . deflation on larger-than-tiny matrices. ==== +* +* ==== Hope for the best. ==== +* + INFO = 0 +* +* ==== Set up job flags for ILAENV. ==== +* + IF( WANTT ) THEN + JBCMPZ( 1: 1 ) = 'S' + ELSE + JBCMPZ( 1: 1 ) = 'E' + END IF + IF( WANTZ ) THEN + JBCMPZ( 2: 2 ) = 'V' + ELSE + JBCMPZ( 2: 2 ) = 'N' + END IF +* +* ==== NWR = recommended deflation window size. At this +* . point, N .GT. NTINY = 11, so there is enough +* . subdiagonal workspace for NWR.GE.2 as required. +* . (In fact, there is enough subdiagonal space for +* . NWR.GE.3.) ==== +* + NWR = ILAENV( 13, 'DLAQR4', JBCMPZ, N, ILO, IHI, LWORK ) + NWR = MAX( 2, NWR ) + NWR = MIN( IHI-ILO+1, ( N-1 ) / 3, NWR ) +* +* ==== NSR = recommended number of simultaneous shifts. +* . At this point N .GT. NTINY = 11, so there is at +* . enough subdiagonal workspace for NSR to be even +* . and greater than or equal to two as required. ==== +* + NSR = ILAENV( 15, 'DLAQR4', JBCMPZ, N, ILO, IHI, LWORK ) + NSR = MIN( NSR, ( N+6 ) / 9, IHI-ILO ) + NSR = MAX( 2, NSR-MOD( NSR, 2 ) ) +* +* ==== Estimate optimal workspace ==== +* +* ==== Workspace query call to DLAQR2 ==== +* + CALL DLAQR2( WANTT, WANTZ, N, ILO, IHI, NWR+1, H, LDH, ILOZ, + $ IHIZ, Z, LDZ, LS, LD, WR, WI, H, LDH, N, H, LDH, + $ N, H, LDH, WORK, -1 ) +* +* ==== Optimal workspace = MAX(DLAQR5, DLAQR2) ==== +* + LWKOPT = MAX( 3*NSR / 2, INT( WORK( 1 ) ) ) +* +* ==== Quick return in case of workspace query. ==== +* + IF( LWORK.EQ.-1 ) THEN + WORK( 1 ) = DBLE( LWKOPT ) + RETURN + END IF +* +* ==== DLAHQR/DLAQR0 crossover point ==== +* + NMIN = ILAENV( 12, 'DLAQR4', JBCMPZ, N, ILO, IHI, LWORK ) + NMIN = MAX( NTINY, NMIN ) +* +* ==== Nibble crossover point ==== +* + NIBBLE = ILAENV( 14, 'DLAQR4', JBCMPZ, N, ILO, IHI, LWORK ) + NIBBLE = MAX( 0, NIBBLE ) +* +* ==== Accumulate reflections during ttswp? Use block +* . 2-by-2 structure during matrix-matrix multiply? ==== +* + KACC22 = ILAENV( 16, 'DLAQR4', JBCMPZ, N, ILO, IHI, LWORK ) + KACC22 = MAX( 0, KACC22 ) + KACC22 = MIN( 2, KACC22 ) +* +* ==== NWMAX = the largest possible deflation window for +* . which there is sufficient workspace. ==== +* + NWMAX = MIN( ( N-1 ) / 3, LWORK / 2 ) + NW = NWMAX +* +* ==== NSMAX = the Largest number of simultaneous shifts +* . for which there is sufficient workspace. ==== +* + NSMAX = MIN( ( N+6 ) / 9, 2*LWORK / 3 ) + NSMAX = NSMAX - MOD( NSMAX, 2 ) +* +* ==== NDFL: an iteration count restarted at deflation. ==== +* + NDFL = 1 +* +* ==== ITMAX = iteration limit ==== +* + ITMAX = MAX( 30, 2*KEXSH )*MAX( 10, ( IHI-ILO+1 ) ) +* +* ==== Last row and column in the active block ==== +* + KBOT = IHI +* +* ==== Main Loop ==== +* + DO 80 IT = 1, ITMAX +* +* ==== Done when KBOT falls below ILO ==== +* + IF( KBOT.LT.ILO ) + $ GO TO 90 +* +* ==== Locate active block ==== +* + DO 10 K = KBOT, ILO + 1, -1 + IF( H( K, K-1 ).EQ.ZERO ) + $ GO TO 20 + 10 CONTINUE + K = ILO + 20 CONTINUE + KTOP = K +* +* ==== Select deflation window size: +* . Typical Case: +* . If possible and advisable, nibble the entire +* . active block. If not, use size MIN(NWR,NWMAX) +* . or MIN(NWR+1,NWMAX) depending upon which has +* . the smaller corresponding subdiagonal entry +* . (a heuristic). +* . +* . Exceptional Case: +* . If there have been no deflations in KEXNW or +* . more iterations, then vary the deflation window +* . size. At first, because, larger windows are, +* . in general, more powerful than smaller ones, +* . rapidly increase the window to the maximum possible. +* . Then, gradually reduce the window size. ==== +* + NH = KBOT - KTOP + 1 + NWUPBD = MIN( NH, NWMAX ) + IF( NDFL.LT.KEXNW ) THEN + NW = MIN( NWUPBD, NWR ) + ELSE + NW = MIN( NWUPBD, 2*NW ) + END IF + IF( NW.LT.NWMAX ) THEN + IF( NW.GE.NH-1 ) THEN + NW = NH + ELSE + KWTOP = KBOT - NW + 1 + IF( ABS( H( KWTOP, KWTOP-1 ) ).GT. + $ ABS( H( KWTOP-1, KWTOP-2 ) ) )NW = NW + 1 + END IF + END IF + IF( NDFL.LT.KEXNW ) THEN + NDEC = -1 + ELSE IF( NDEC.GE.0 .OR. NW.GE.NWUPBD ) THEN + NDEC = NDEC + 1 + IF( NW-NDEC.LT.2 ) + $ NDEC = 0 + NW = NW - NDEC + END IF +* +* ==== Aggressive early deflation: +* . split workspace under the subdiagonal into +* . - an nw-by-nw work array V in the lower +* . left-hand-corner, +* . - an NW-by-at-least-NW-but-more-is-better +* . (NW-by-NHO) horizontal work array along +* . the bottom edge, +* . - an at-least-NW-but-more-is-better (NHV-by-NW) +* . vertical work array along the left-hand-edge. +* . ==== +* + KV = N - NW + 1 + KT = NW + 1 + NHO = ( N-NW-1 ) - KT + 1 + KWV = NW + 2 + NVE = ( N-NW ) - KWV + 1 +* +* ==== Aggressive early deflation ==== +* + CALL DLAQR2( WANTT, WANTZ, N, KTOP, KBOT, NW, H, LDH, ILOZ, + $ IHIZ, Z, LDZ, LS, LD, WR, WI, H( KV, 1 ), LDH, + $ NHO, H( KV, KT ), LDH, NVE, H( KWV, 1 ), LDH, + $ WORK, LWORK ) +* +* ==== Adjust KBOT accounting for new deflations. ==== +* + KBOT = KBOT - LD +* +* ==== KS points to the shifts. ==== +* + KS = KBOT - LS + 1 +* +* ==== Skip an expensive QR sweep if there is a (partly +* . heuristic) reason to expect that many eigenvalues +* . will deflate without it. Here, the QR sweep is +* . skipped if many eigenvalues have just been deflated +* . or if the remaining active block is small. +* + IF( ( LD.EQ.0 ) .OR. ( ( 100*LD.LE.NW*NIBBLE ) .AND. ( KBOT- + $ KTOP+1.GT.MIN( NMIN, NWMAX ) ) ) ) THEN +* +* ==== NS = nominal number of simultaneous shifts. +* . This may be lowered (slightly) if DLAQR2 +* . did not provide that many shifts. ==== +* + NS = MIN( NSMAX, NSR, MAX( 2, KBOT-KTOP ) ) + NS = NS - MOD( NS, 2 ) +* +* ==== If there have been no deflations +* . in a multiple of KEXSH iterations, +* . then try exceptional shifts. +* . Otherwise use shifts provided by +* . DLAQR2 above or from the eigenvalues +* . of a trailing principal submatrix. ==== +* + IF( MOD( NDFL, KEXSH ).EQ.0 ) THEN + KS = KBOT - NS + 1 + DO 30 I = KBOT, MAX( KS+1, KTOP+2 ), -2 + SS = ABS( H( I, I-1 ) ) + ABS( H( I-1, I-2 ) ) + AA = WILK1*SS + H( I, I ) + BB = SS + CC = WILK2*SS + DD = AA + CALL DLANV2( AA, BB, CC, DD, WR( I-1 ), WI( I-1 ), + $ WR( I ), WI( I ), CS, SN ) + 30 CONTINUE + IF( KS.EQ.KTOP ) THEN + WR( KS+1 ) = H( KS+1, KS+1 ) + WI( KS+1 ) = ZERO + WR( KS ) = WR( KS+1 ) + WI( KS ) = WI( KS+1 ) + END IF + ELSE +* +* ==== Got NS/2 or fewer shifts? Use DLAHQR +* . on a trailing principal submatrix to +* . get more. (Since NS.LE.NSMAX.LE.(N+6)/9, +* . there is enough space below the subdiagonal +* . to fit an NS-by-NS scratch array.) ==== +* + IF( KBOT-KS+1.LE.NS / 2 ) THEN + KS = KBOT - NS + 1 + KT = N - NS + 1 + CALL DLACPY( 'A', NS, NS, H( KS, KS ), LDH, + $ H( KT, 1 ), LDH ) + CALL DLAHQR( .false., .false., NS, 1, NS, + $ H( KT, 1 ), LDH, WR( KS ), WI( KS ), + $ 1, 1, ZDUM, 1, INF ) + KS = KS + INF +* +* ==== In case of a rare QR failure use +* . eigenvalues of the trailing 2-by-2 +* . principal submatrix. ==== +* + IF( KS.GE.KBOT ) THEN + AA = H( KBOT-1, KBOT-1 ) + CC = H( KBOT, KBOT-1 ) + BB = H( KBOT-1, KBOT ) + DD = H( KBOT, KBOT ) + CALL DLANV2( AA, BB, CC, DD, WR( KBOT-1 ), + $ WI( KBOT-1 ), WR( KBOT ), + $ WI( KBOT ), CS, SN ) + KS = KBOT - 1 + END IF + END IF +* + IF( KBOT-KS+1.GT.NS ) THEN +* +* ==== Sort the shifts (Helps a little) +* . Bubble sort keeps complex conjugate +* . pairs together. ==== +* + SORTED = .false. + DO 50 K = KBOT, KS + 1, -1 + IF( SORTED ) + $ GO TO 60 + SORTED = .true. + DO 40 I = KS, K - 1 + IF( ABS( WR( I ) )+ABS( WI( I ) ).LT. + $ ABS( WR( I+1 ) )+ABS( WI( I+1 ) ) ) THEN + SORTED = .false. +* + SWAP = WR( I ) + WR( I ) = WR( I+1 ) + WR( I+1 ) = SWAP +* + SWAP = WI( I ) + WI( I ) = WI( I+1 ) + WI( I+1 ) = SWAP + END IF + 40 CONTINUE + 50 CONTINUE + 60 CONTINUE + END IF +* +* ==== Shuffle shifts into pairs of real shifts +* . and pairs of complex conjugate shifts +* . assuming complex conjugate shifts are +* . already adjacent to one another. (Yes, +* . they are.) ==== +* + DO 70 I = KBOT, KS + 2, -2 + IF( WI( I ).NE.-WI( I-1 ) ) THEN +* + SWAP = WR( I ) + WR( I ) = WR( I-1 ) + WR( I-1 ) = WR( I-2 ) + WR( I-2 ) = SWAP +* + SWAP = WI( I ) + WI( I ) = WI( I-1 ) + WI( I-1 ) = WI( I-2 ) + WI( I-2 ) = SWAP + END IF + 70 CONTINUE + END IF +* +* ==== If there are only two shifts and both are +* . real, then use only one. ==== +* + IF( KBOT-KS+1.EQ.2 ) THEN + IF( WI( KBOT ).EQ.ZERO ) THEN + IF( ABS( WR( KBOT )-H( KBOT, KBOT ) ).LT. + $ ABS( WR( KBOT-1 )-H( KBOT, KBOT ) ) ) THEN + WR( KBOT-1 ) = WR( KBOT ) + ELSE + WR( KBOT ) = WR( KBOT-1 ) + END IF + END IF + END IF +* +* ==== Use up to NS of the the smallest magnatiude +* . shifts. If there aren't NS shifts available, +* . then use them all, possibly dropping one to +* . make the number of shifts even. ==== +* + NS = MIN( NS, KBOT-KS+1 ) + NS = NS - MOD( NS, 2 ) + KS = KBOT - NS + 1 +* +* ==== Small-bulge multi-shift QR sweep: +* . split workspace under the subdiagonal into +* . - a KDU-by-KDU work array U in the lower +* . left-hand-corner, +* . - a KDU-by-at-least-KDU-but-more-is-better +* . (KDU-by-NHo) horizontal work array WH along +* . the bottom edge, +* . - and an at-least-KDU-but-more-is-better-by-KDU +* . (NVE-by-KDU) vertical work WV arrow along +* . the left-hand-edge. ==== +* + KDU = 3*NS - 3 + KU = N - KDU + 1 + KWH = KDU + 1 + NHO = ( N-KDU+1-4 ) - ( KDU+1 ) + 1 + KWV = KDU + 4 + NVE = N - KDU - KWV + 1 +* +* ==== Small-bulge multi-shift QR sweep ==== +* + CALL DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NS, + $ WR( KS ), WI( KS ), H, LDH, ILOZ, IHIZ, Z, + $ LDZ, WORK, 3, H( KU, 1 ), LDH, NVE, + $ H( KWV, 1 ), LDH, NHO, H( KU, KWH ), LDH ) + END IF +* +* ==== Note progress (or the lack of it). ==== +* + IF( LD.GT.0 ) THEN + NDFL = 1 + ELSE + NDFL = NDFL + 1 + END IF +* +* ==== End of main loop ==== + 80 CONTINUE +* +* ==== Iteration limit exceeded. Set INFO to show where +* . the problem occurred and exit. ==== +* + INFO = KBOT + 90 CONTINUE + END IF +* +* ==== Return the optimal value of LWORK. ==== +* + WORK( 1 ) = DBLE( LWKOPT ) +* +* ==== End of DLAQR4 ==== +* + END diff --git a/dep/lapack/dlaqr5.f b/dep/lapack/dlaqr5.f new file mode 100644 index 00000000..0615eaf8 --- /dev/null +++ b/dep/lapack/dlaqr5.f @@ -0,0 +1,784 @@ + SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS, + $ SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U, + $ LDU, NV, WV, LDWV, NH, WH, LDWH ) +* +* -- LAPACK auxiliary routine (version 3.3.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2010 +* +* .. Scalar Arguments .. + INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV, + $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ), + $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ), + $ Z( LDZ, * ) +* .. +* +* This auxiliary subroutine called by DLAQR0 performs a +* single small-bulge multi-shift QR sweep. +* +* WANTT (input) logical scalar +* WANTT = .true. if the quasi-triangular Schur factor +* is being computed. WANTT is set to .false. otherwise. +* +* WANTZ (input) logical scalar +* WANTZ = .true. if the orthogonal Schur factor is being +* computed. WANTZ is set to .false. otherwise. +* +* KACC22 (input) integer with value 0, 1, or 2. +* Specifies the computation mode of far-from-diagonal +* orthogonal updates. +* = 0: DLAQR5 does not accumulate reflections and does not +* use matrix-matrix multiply to update far-from-diagonal +* matrix entries. +* = 1: DLAQR5 accumulates reflections and uses matrix-matrix +* multiply to update the far-from-diagonal matrix entries. +* = 2: DLAQR5 accumulates reflections, uses matrix-matrix +* multiply to update the far-from-diagonal matrix entries, +* and takes advantage of 2-by-2 block structure during +* matrix multiplies. +* +* N (input) integer scalar +* N is the order of the Hessenberg matrix H upon which this +* subroutine operates. +* +* KTOP (input) integer scalar +* KBOT (input) integer scalar +* These are the first and last rows and columns of an +* isolated diagonal block upon which the QR sweep is to be +* applied. It is assumed without a check that +* either KTOP = 1 or H(KTOP,KTOP-1) = 0 +* and +* either KBOT = N or H(KBOT+1,KBOT) = 0. +* +* NSHFTS (input) integer scalar +* NSHFTS gives the number of simultaneous shifts. NSHFTS +* must be positive and even. +* +* SR (input/output) DOUBLE PRECISION array of size (NSHFTS) +* SI (input/output) DOUBLE PRECISION array of size (NSHFTS) +* SR contains the real parts and SI contains the imaginary +* parts of the NSHFTS shifts of origin that define the +* multi-shift QR sweep. On output SR and SI may be +* reordered. +* +* H (input/output) DOUBLE PRECISION array of size (LDH,N) +* On input H contains a Hessenberg matrix. On output a +* multi-shift QR sweep with shifts SR(J)+i*SI(J) is applied +* to the isolated diagonal block in rows and columns KTOP +* through KBOT. +* +* LDH (input) integer scalar +* LDH is the leading dimension of H just as declared in the +* calling procedure. LDH.GE.MAX(1,N). +* +* ILOZ (input) INTEGER +* IHIZ (input) INTEGER +* Specify the rows of Z to which transformations must be +* applied if WANTZ is .TRUE.. 1 .LE. ILOZ .LE. IHIZ .LE. N +* +* Z (input/output) DOUBLE PRECISION array of size (LDZ,IHI) +* If WANTZ = .TRUE., then the QR Sweep orthogonal +* similarity transformation is accumulated into +* Z(ILOZ:IHIZ,ILO:IHI) from the right. +* If WANTZ = .FALSE., then Z is unreferenced. +* +* LDZ (input) integer scalar +* LDA is the leading dimension of Z just as declared in +* the calling procedure. LDZ.GE.N. +* +* V (workspace) DOUBLE PRECISION array of size (LDV,NSHFTS/2) +* +* LDV (input) integer scalar +* LDV is the leading dimension of V as declared in the +* calling procedure. LDV.GE.3. +* +* U (workspace) DOUBLE PRECISION array of size +* (LDU,3*NSHFTS-3) +* +* LDU (input) integer scalar +* LDU is the leading dimension of U just as declared in the +* in the calling subroutine. LDU.GE.3*NSHFTS-3. +* +* NH (input) integer scalar +* NH is the number of columns in array WH available for +* workspace. NH.GE.1. +* +* WH (workspace) DOUBLE PRECISION array of size (LDWH,NH) +* +* LDWH (input) integer scalar +* Leading dimension of WH just as declared in the +* calling procedure. LDWH.GE.3*NSHFTS-3. +* +* NV (input) integer scalar +* NV is the number of rows in WV agailable for workspace. +* NV.GE.1. +* +* WV (workspace) DOUBLE PRECISION array of size +* (LDWV,3*NSHFTS-3) +* +* LDWV (input) integer scalar +* LDWV is the leading dimension of WV as declared in the +* in the calling subroutine. LDWV.GE.NV. +* +* ================================================================ +* Based on contributions by +* Karen Braman and Ralph Byers, Department of Mathematics, +* University of Kansas, USA +* +* ================================================================ +* Reference: +* +* K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +* Algorithm Part I: Maintaining Well Focused Shifts, and +* Level 3 Performance, SIAM Journal of Matrix Analysis, +* volume 23, pages 929--947, 2002. +* +* ================================================================ +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, BETA, H11, H12, H21, H22, REFSUM, + $ SAFMAX, SAFMIN, SCL, SMLNUM, SWAP, TST1, TST2, + $ ULP + INTEGER I, I2, I4, INCOL, J, J2, J4, JBOT, JCOL, JLEN, + $ JROW, JTOP, K, K1, KDU, KMS, KNZ, KRCOL, KZS, + $ M, M22, MBOT, MEND, MSTART, MTOP, NBMPS, NDCOL, + $ NS, NU + LOGICAL ACCUM, BLK22, BMP22 +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. +* + INTRINSIC ABS, DBLE, MAX, MIN, MOD +* .. +* .. Local Arrays .. + DOUBLE PRECISION VT( 3 ) +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DLABAD, DLACPY, DLAQR1, DLARFG, DLASET, + $ DTRMM +* .. +* .. Executable Statements .. +* +* ==== If there are no shifts, then there is nothing to do. ==== +* + IF( NSHFTS.LT.2 ) + $ RETURN +* +* ==== If the active block is empty or 1-by-1, then there +* . is nothing to do. ==== +* + IF( KTOP.GE.KBOT ) + $ RETURN +* +* ==== Shuffle shifts into pairs of real shifts and pairs +* . of complex conjugate shifts assuming complex +* . conjugate shifts are already adjacent to one +* . another. ==== +* + DO 10 I = 1, NSHFTS - 2, 2 + IF( SI( I ).NE.-SI( I+1 ) ) THEN +* + SWAP = SR( I ) + SR( I ) = SR( I+1 ) + SR( I+1 ) = SR( I+2 ) + SR( I+2 ) = SWAP +* + SWAP = SI( I ) + SI( I ) = SI( I+1 ) + SI( I+1 ) = SI( I+2 ) + SI( I+2 ) = SWAP + END IF + 10 CONTINUE +* +* ==== NSHFTS is supposed to be even, but if it is odd, +* . then simply reduce it by one. The shuffle above +* . ensures that the dropped shift is real and that +* . the remaining shifts are paired. ==== +* + NS = NSHFTS - MOD( NSHFTS, 2 ) +* +* ==== Machine constants for deflation ==== +* + SAFMIN = DLAMCH( 'SAFE MINIMUM' ) + SAFMAX = ONE / SAFMIN + CALL DLABAD( SAFMIN, SAFMAX ) + ULP = DLAMCH( 'PRECISION' ) + SMLNUM = SAFMIN*( DBLE( N ) / ULP ) +* +* ==== Use accumulated reflections to update far-from-diagonal +* . entries ? ==== +* + ACCUM = ( KACC22.EQ.1 ) .OR. ( KACC22.EQ.2 ) +* +* ==== If so, exploit the 2-by-2 block structure? ==== +* + BLK22 = ( NS.GT.2 ) .AND. ( KACC22.EQ.2 ) +* +* ==== clear trash ==== +* + IF( KTOP+2.LE.KBOT ) + $ H( KTOP+2, KTOP ) = ZERO +* +* ==== NBMPS = number of 2-shift bulges in the chain ==== +* + NBMPS = NS / 2 +* +* ==== KDU = width of slab ==== +* + KDU = 6*NBMPS - 3 +* +* ==== Create and chase chains of NBMPS bulges ==== +* + DO 220 INCOL = 3*( 1-NBMPS ) + KTOP - 1, KBOT - 2, 3*NBMPS - 2 + NDCOL = INCOL + KDU + IF( ACCUM ) + $ CALL DLASET( 'ALL', KDU, KDU, ZERO, ONE, U, LDU ) +* +* ==== Near-the-diagonal bulge chase. The following loop +* . performs the near-the-diagonal part of a small bulge +* . multi-shift QR sweep. Each 6*NBMPS-2 column diagonal +* . chunk extends from column INCOL to column NDCOL +* . (including both column INCOL and column NDCOL). The +* . following loop chases a 3*NBMPS column long chain of +* . NBMPS bulges 3*NBMPS-2 columns to the right. (INCOL +* . may be less than KTOP and and NDCOL may be greater than +* . KBOT indicating phantom columns from which to chase +* . bulges before they are actually introduced or to which +* . to chase bulges beyond column KBOT.) ==== +* + DO 150 KRCOL = INCOL, MIN( INCOL+3*NBMPS-3, KBOT-2 ) +* +* ==== Bulges number MTOP to MBOT are active double implicit +* . shift bulges. There may or may not also be small +* . 2-by-2 bulge, if there is room. The inactive bulges +* . (if any) must wait until the active bulges have moved +* . down the diagonal to make room. The phantom matrix +* . paradigm described above helps keep track. ==== +* + MTOP = MAX( 1, ( ( KTOP-1 )-KRCOL+2 ) / 3+1 ) + MBOT = MIN( NBMPS, ( KBOT-KRCOL ) / 3 ) + M22 = MBOT + 1 + BMP22 = ( MBOT.LT.NBMPS ) .AND. ( KRCOL+3*( M22-1 ) ).EQ. + $ ( KBOT-2 ) +* +* ==== Generate reflections to chase the chain right +* . one column. (The minimum value of K is KTOP-1.) ==== +* + DO 20 M = MTOP, MBOT + K = KRCOL + 3*( M-1 ) + IF( K.EQ.KTOP-1 ) THEN + CALL DLAQR1( 3, H( KTOP, KTOP ), LDH, SR( 2*M-1 ), + $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ), + $ V( 1, M ) ) + ALPHA = V( 1, M ) + CALL DLARFG( 3, ALPHA, V( 2, M ), 1, V( 1, M ) ) + ELSE + BETA = H( K+1, K ) + V( 2, M ) = H( K+2, K ) + V( 3, M ) = H( K+3, K ) + CALL DLARFG( 3, BETA, V( 2, M ), 1, V( 1, M ) ) +* +* ==== A Bulge may collapse because of vigilant +* . deflation or destructive underflow. In the +* . underflow case, try the two-small-subdiagonals +* . trick to try to reinflate the bulge. ==== +* + IF( H( K+3, K ).NE.ZERO .OR. H( K+3, K+1 ).NE. + $ ZERO .OR. H( K+3, K+2 ).EQ.ZERO ) THEN +* +* ==== Typical case: not collapsed (yet). ==== +* + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + ELSE +* +* ==== Atypical case: collapsed. Attempt to +* . reintroduce ignoring H(K+1,K) and H(K+2,K). +* . If the fill resulting from the new +* . reflector is too large, then abandon it. +* . Otherwise, use the new one. ==== +* + CALL DLAQR1( 3, H( K+1, K+1 ), LDH, SR( 2*M-1 ), + $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ), + $ VT ) + ALPHA = VT( 1 ) + CALL DLARFG( 3, ALPHA, VT( 2 ), 1, VT( 1 ) ) + REFSUM = VT( 1 )*( H( K+1, K )+VT( 2 )* + $ H( K+2, K ) ) +* + IF( ABS( H( K+2, K )-REFSUM*VT( 2 ) )+ + $ ABS( REFSUM*VT( 3 ) ).GT.ULP* + $ ( ABS( H( K, K ) )+ABS( H( K+1, + $ K+1 ) )+ABS( H( K+2, K+2 ) ) ) ) THEN +* +* ==== Starting a new bulge here would +* . create non-negligible fill. Use +* . the old one with trepidation. ==== +* + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + ELSE +* +* ==== Stating a new bulge here would +* . create only negligible fill. +* . Replace the old reflector with +* . the new one. ==== +* + H( K+1, K ) = H( K+1, K ) - REFSUM + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + V( 1, M ) = VT( 1 ) + V( 2, M ) = VT( 2 ) + V( 3, M ) = VT( 3 ) + END IF + END IF + END IF + 20 CONTINUE +* +* ==== Generate a 2-by-2 reflection, if needed. ==== +* + K = KRCOL + 3*( M22-1 ) + IF( BMP22 ) THEN + IF( K.EQ.KTOP-1 ) THEN + CALL DLAQR1( 2, H( K+1, K+1 ), LDH, SR( 2*M22-1 ), + $ SI( 2*M22-1 ), SR( 2*M22 ), SI( 2*M22 ), + $ V( 1, M22 ) ) + BETA = V( 1, M22 ) + CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) ) + ELSE + BETA = H( K+1, K ) + V( 2, M22 ) = H( K+2, K ) + CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) ) + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + END IF + END IF +* +* ==== Multiply H by reflections from the left ==== +* + IF( ACCUM ) THEN + JBOT = MIN( NDCOL, KBOT ) + ELSE IF( WANTT ) THEN + JBOT = N + ELSE + JBOT = KBOT + END IF + DO 40 J = MAX( KTOP, KRCOL ), JBOT + MEND = MIN( MBOT, ( J-KRCOL+2 ) / 3 ) + DO 30 M = MTOP, MEND + K = KRCOL + 3*( M-1 ) + REFSUM = V( 1, M )*( H( K+1, J )+V( 2, M )* + $ H( K+2, J )+V( 3, M )*H( K+3, J ) ) + H( K+1, J ) = H( K+1, J ) - REFSUM + H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M ) + H( K+3, J ) = H( K+3, J ) - REFSUM*V( 3, M ) + 30 CONTINUE + 40 CONTINUE + IF( BMP22 ) THEN + K = KRCOL + 3*( M22-1 ) + DO 50 J = MAX( K+1, KTOP ), JBOT + REFSUM = V( 1, M22 )*( H( K+1, J )+V( 2, M22 )* + $ H( K+2, J ) ) + H( K+1, J ) = H( K+1, J ) - REFSUM + H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M22 ) + 50 CONTINUE + END IF +* +* ==== Multiply H by reflections from the right. +* . Delay filling in the last row until the +* . vigilant deflation check is complete. ==== +* + IF( ACCUM ) THEN + JTOP = MAX( KTOP, INCOL ) + ELSE IF( WANTT ) THEN + JTOP = 1 + ELSE + JTOP = KTOP + END IF + DO 90 M = MTOP, MBOT + IF( V( 1, M ).NE.ZERO ) THEN + K = KRCOL + 3*( M-1 ) + DO 60 J = JTOP, MIN( KBOT, K+3 ) + REFSUM = V( 1, M )*( H( J, K+1 )+V( 2, M )* + $ H( J, K+2 )+V( 3, M )*H( J, K+3 ) ) + H( J, K+1 ) = H( J, K+1 ) - REFSUM + H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M ) + H( J, K+3 ) = H( J, K+3 ) - REFSUM*V( 3, M ) + 60 CONTINUE +* + IF( ACCUM ) THEN +* +* ==== Accumulate U. (If necessary, update Z later +* . with with an efficient matrix-matrix +* . multiply.) ==== +* + KMS = K - INCOL + DO 70 J = MAX( 1, KTOP-INCOL ), KDU + REFSUM = V( 1, M )*( U( J, KMS+1 )+V( 2, M )* + $ U( J, KMS+2 )+V( 3, M )*U( J, KMS+3 ) ) + U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM + U( J, KMS+2 ) = U( J, KMS+2 ) - REFSUM*V( 2, M ) + U( J, KMS+3 ) = U( J, KMS+3 ) - REFSUM*V( 3, M ) + 70 CONTINUE + ELSE IF( WANTZ ) THEN +* +* ==== U is not accumulated, so update Z +* . now by multiplying by reflections +* . from the right. ==== +* + DO 80 J = ILOZ, IHIZ + REFSUM = V( 1, M )*( Z( J, K+1 )+V( 2, M )* + $ Z( J, K+2 )+V( 3, M )*Z( J, K+3 ) ) + Z( J, K+1 ) = Z( J, K+1 ) - REFSUM + Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M ) + Z( J, K+3 ) = Z( J, K+3 ) - REFSUM*V( 3, M ) + 80 CONTINUE + END IF + END IF + 90 CONTINUE +* +* ==== Special case: 2-by-2 reflection (if needed) ==== +* + K = KRCOL + 3*( M22-1 ) + IF( BMP22 ) THEN + IF ( V( 1, M22 ).NE.ZERO ) THEN + DO 100 J = JTOP, MIN( KBOT, K+3 ) + REFSUM = V( 1, M22 )*( H( J, K+1 )+V( 2, M22 )* + $ H( J, K+2 ) ) + H( J, K+1 ) = H( J, K+1 ) - REFSUM + H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M22 ) + 100 CONTINUE +* + IF( ACCUM ) THEN + KMS = K - INCOL + DO 110 J = MAX( 1, KTOP-INCOL ), KDU + REFSUM = V( 1, M22 )*( U( J, KMS+1 )+ + $ V( 2, M22 )*U( J, KMS+2 ) ) + U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM + U( J, KMS+2 ) = U( J, KMS+2 ) - + $ REFSUM*V( 2, M22 ) + 110 CONTINUE + ELSE IF( WANTZ ) THEN + DO 120 J = ILOZ, IHIZ + REFSUM = V( 1, M22 )*( Z( J, K+1 )+V( 2, M22 )* + $ Z( J, K+2 ) ) + Z( J, K+1 ) = Z( J, K+1 ) - REFSUM + Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M22 ) + 120 CONTINUE + END IF + END IF + END IF +* +* ==== Vigilant deflation check ==== +* + MSTART = MTOP + IF( KRCOL+3*( MSTART-1 ).LT.KTOP ) + $ MSTART = MSTART + 1 + MEND = MBOT + IF( BMP22 ) + $ MEND = MEND + 1 + IF( KRCOL.EQ.KBOT-2 ) + $ MEND = MEND + 1 + DO 130 M = MSTART, MEND + K = MIN( KBOT-1, KRCOL+3*( M-1 ) ) +* +* ==== The following convergence test requires that +* . the tradition small-compared-to-nearby-diagonals +* . criterion and the Ahues & Tisseur (LAWN 122, 1997) +* . criteria both be satisfied. The latter improves +* . accuracy in some examples. Falling back on an +* . alternate convergence criterion when TST1 or TST2 +* . is zero (as done here) is traditional but probably +* . unnecessary. ==== +* + IF( H( K+1, K ).NE.ZERO ) THEN + TST1 = ABS( H( K, K ) ) + ABS( H( K+1, K+1 ) ) + IF( TST1.EQ.ZERO ) THEN + IF( K.GE.KTOP+1 ) + $ TST1 = TST1 + ABS( H( K, K-1 ) ) + IF( K.GE.KTOP+2 ) + $ TST1 = TST1 + ABS( H( K, K-2 ) ) + IF( K.GE.KTOP+3 ) + $ TST1 = TST1 + ABS( H( K, K-3 ) ) + IF( K.LE.KBOT-2 ) + $ TST1 = TST1 + ABS( H( K+2, K+1 ) ) + IF( K.LE.KBOT-3 ) + $ TST1 = TST1 + ABS( H( K+3, K+1 ) ) + IF( K.LE.KBOT-4 ) + $ TST1 = TST1 + ABS( H( K+4, K+1 ) ) + END IF + IF( ABS( H( K+1, K ) ).LE.MAX( SMLNUM, ULP*TST1 ) ) + $ THEN + H12 = MAX( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) ) + H21 = MIN( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) ) + H11 = MAX( ABS( H( K+1, K+1 ) ), + $ ABS( H( K, K )-H( K+1, K+1 ) ) ) + H22 = MIN( ABS( H( K+1, K+1 ) ), + $ ABS( H( K, K )-H( K+1, K+1 ) ) ) + SCL = H11 + H12 + TST2 = H22*( H11 / SCL ) +* + IF( TST2.EQ.ZERO .OR. H21*( H12 / SCL ).LE. + $ MAX( SMLNUM, ULP*TST2 ) )H( K+1, K ) = ZERO + END IF + END IF + 130 CONTINUE +* +* ==== Fill in the last row of each bulge. ==== +* + MEND = MIN( NBMPS, ( KBOT-KRCOL-1 ) / 3 ) + DO 140 M = MTOP, MEND + K = KRCOL + 3*( M-1 ) + REFSUM = V( 1, M )*V( 3, M )*H( K+4, K+3 ) + H( K+4, K+1 ) = -REFSUM + H( K+4, K+2 ) = -REFSUM*V( 2, M ) + H( K+4, K+3 ) = H( K+4, K+3 ) - REFSUM*V( 3, M ) + 140 CONTINUE +* +* ==== End of near-the-diagonal bulge chase. ==== +* + 150 CONTINUE +* +* ==== Use U (if accumulated) to update far-from-diagonal +* . entries in H. If required, use U to update Z as +* . well. ==== +* + IF( ACCUM ) THEN + IF( WANTT ) THEN + JTOP = 1 + JBOT = N + ELSE + JTOP = KTOP + JBOT = KBOT + END IF + IF( ( .NOT.BLK22 ) .OR. ( INCOL.LT.KTOP ) .OR. + $ ( NDCOL.GT.KBOT ) .OR. ( NS.LE.2 ) ) THEN +* +* ==== Updates not exploiting the 2-by-2 block +* . structure of U. K1 and NU keep track of +* . the location and size of U in the special +* . cases of introducing bulges and chasing +* . bulges off the bottom. In these special +* . cases and in case the number of shifts +* . is NS = 2, there is no 2-by-2 block +* . structure to exploit. ==== +* + K1 = MAX( 1, KTOP-INCOL ) + NU = ( KDU-MAX( 0, NDCOL-KBOT ) ) - K1 + 1 +* +* ==== Horizontal Multiply ==== +* + DO 160 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH + JLEN = MIN( NH, JBOT-JCOL+1 ) + CALL DGEMM( 'C', 'N', NU, JLEN, NU, ONE, U( K1, K1 ), + $ LDU, H( INCOL+K1, JCOL ), LDH, ZERO, WH, + $ LDWH ) + CALL DLACPY( 'ALL', NU, JLEN, WH, LDWH, + $ H( INCOL+K1, JCOL ), LDH ) + 160 CONTINUE +* +* ==== Vertical multiply ==== +* + DO 170 JROW = JTOP, MAX( KTOP, INCOL ) - 1, NV + JLEN = MIN( NV, MAX( KTOP, INCOL )-JROW ) + CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE, + $ H( JROW, INCOL+K1 ), LDH, U( K1, K1 ), + $ LDU, ZERO, WV, LDWV ) + CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV, + $ H( JROW, INCOL+K1 ), LDH ) + 170 CONTINUE +* +* ==== Z multiply (also vertical) ==== +* + IF( WANTZ ) THEN + DO 180 JROW = ILOZ, IHIZ, NV + JLEN = MIN( NV, IHIZ-JROW+1 ) + CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE, + $ Z( JROW, INCOL+K1 ), LDZ, U( K1, K1 ), + $ LDU, ZERO, WV, LDWV ) + CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV, + $ Z( JROW, INCOL+K1 ), LDZ ) + 180 CONTINUE + END IF + ELSE +* +* ==== Updates exploiting U's 2-by-2 block structure. +* . (I2, I4, J2, J4 are the last rows and columns +* . of the blocks.) ==== +* + I2 = ( KDU+1 ) / 2 + I4 = KDU + J2 = I4 - I2 + J4 = KDU +* +* ==== KZS and KNZ deal with the band of zeros +* . along the diagonal of one of the triangular +* . blocks. ==== +* + KZS = ( J4-J2 ) - ( NS+1 ) + KNZ = NS + 1 +* +* ==== Horizontal multiply ==== +* + DO 190 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH + JLEN = MIN( NH, JBOT-JCOL+1 ) +* +* ==== Copy bottom of H to top+KZS of scratch ==== +* (The first KZS rows get multiplied by zero.) ==== +* + CALL DLACPY( 'ALL', KNZ, JLEN, H( INCOL+1+J2, JCOL ), + $ LDH, WH( KZS+1, 1 ), LDWH ) +* +* ==== Multiply by U21**T ==== +* + CALL DLASET( 'ALL', KZS, JLEN, ZERO, ZERO, WH, LDWH ) + CALL DTRMM( 'L', 'U', 'C', 'N', KNZ, JLEN, ONE, + $ U( J2+1, 1+KZS ), LDU, WH( KZS+1, 1 ), + $ LDWH ) +* +* ==== Multiply top of H by U11**T ==== +* + CALL DGEMM( 'C', 'N', I2, JLEN, J2, ONE, U, LDU, + $ H( INCOL+1, JCOL ), LDH, ONE, WH, LDWH ) +* +* ==== Copy top of H to bottom of WH ==== +* + CALL DLACPY( 'ALL', J2, JLEN, H( INCOL+1, JCOL ), LDH, + $ WH( I2+1, 1 ), LDWH ) +* +* ==== Multiply by U21**T ==== +* + CALL DTRMM( 'L', 'L', 'C', 'N', J2, JLEN, ONE, + $ U( 1, I2+1 ), LDU, WH( I2+1, 1 ), LDWH ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'C', 'N', I4-I2, JLEN, J4-J2, ONE, + $ U( J2+1, I2+1 ), LDU, + $ H( INCOL+1+J2, JCOL ), LDH, ONE, + $ WH( I2+1, 1 ), LDWH ) +* +* ==== Copy it back ==== +* + CALL DLACPY( 'ALL', KDU, JLEN, WH, LDWH, + $ H( INCOL+1, JCOL ), LDH ) + 190 CONTINUE +* +* ==== Vertical multiply ==== +* + DO 200 JROW = JTOP, MAX( INCOL, KTOP ) - 1, NV + JLEN = MIN( NV, MAX( INCOL, KTOP )-JROW ) +* +* ==== Copy right of H to scratch (the first KZS +* . columns get multiplied by zero) ==== +* + CALL DLACPY( 'ALL', JLEN, KNZ, H( JROW, INCOL+1+J2 ), + $ LDH, WV( 1, 1+KZS ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, LDWV ) + CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE, + $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ), + $ LDWV ) +* +* ==== Multiply by U11 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE, + $ H( JROW, INCOL+1 ), LDH, U, LDU, ONE, WV, + $ LDWV ) +* +* ==== Copy left of H to right of scratch ==== +* + CALL DLACPY( 'ALL', JLEN, J2, H( JROW, INCOL+1 ), LDH, + $ WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE, + $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE, + $ H( JROW, INCOL+1+J2 ), LDH, + $ U( J2+1, I2+1 ), LDU, ONE, WV( 1, 1+I2 ), + $ LDWV ) +* +* ==== Copy it back ==== +* + CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV, + $ H( JROW, INCOL+1 ), LDH ) + 200 CONTINUE +* +* ==== Multiply Z (also vertical) ==== +* + IF( WANTZ ) THEN + DO 210 JROW = ILOZ, IHIZ, NV + JLEN = MIN( NV, IHIZ-JROW+1 ) +* +* ==== Copy right of Z to left of scratch (first +* . KZS columns get multiplied by zero) ==== +* + CALL DLACPY( 'ALL', JLEN, KNZ, + $ Z( JROW, INCOL+1+J2 ), LDZ, + $ WV( 1, 1+KZS ), LDWV ) +* +* ==== Multiply by U12 ==== +* + CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, + $ LDWV ) + CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE, + $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ), + $ LDWV ) +* +* ==== Multiply by U11 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE, + $ Z( JROW, INCOL+1 ), LDZ, U, LDU, ONE, + $ WV, LDWV ) +* +* ==== Copy left of Z to right of scratch ==== +* + CALL DLACPY( 'ALL', JLEN, J2, Z( JROW, INCOL+1 ), + $ LDZ, WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE, + $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), + $ LDWV ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE, + $ Z( JROW, INCOL+1+J2 ), LDZ, + $ U( J2+1, I2+1 ), LDU, ONE, + $ WV( 1, 1+I2 ), LDWV ) +* +* ==== Copy the result back to Z ==== +* + CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV, + $ Z( JROW, INCOL+1 ), LDZ ) + 210 CONTINUE + END IF + END IF + END IF + 220 CONTINUE +* +* ==== End of DLAQR5 ==== +* + END diff --git a/dep/lapack/dlaran.f b/dep/lapack/dlaran.f new file mode 100644 index 00000000..81a6ad65 --- /dev/null +++ b/dep/lapack/dlaran.f @@ -0,0 +1,89 @@ + DOUBLE PRECISION FUNCTION DLARAN( ISEED ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Array Arguments .. + INTEGER ISEED( 4 ) +* .. +* +* Purpose +* ======= +* +* DLARAN returns a random real number from a uniform (0,1) +* distribution. +* +* Arguments +* ========= +* +* ISEED (input/output) INTEGER array, dimension (4) +* On entry, the seed of the random number generator; the array +* elements must be between 0 and 4095, and ISEED(4) must be +* odd. +* On exit, the seed is updated. +* +* Further Details +* =============== +* +* This routine uses a multiplicative congruential method with modulus +* 2**48 and multiplier 33952834046453 (see G.S.Fishman, +* 'Multiplicative congruential random number generators with modulus +* 2**b: an exhaustive analysis for b = 32 and a partial analysis for +* b = 48', Math. Comp. 189, pp 331-344, 1990). +* +* 48-bit integers are stored in 4 integer array elements with 12 bits +* per element. Hence the routine is portable across machines with +* integers of 32 bits or more. +* +* ===================================================================== +* +* .. Parameters .. + INTEGER M1, M2, M3, M4 + PARAMETER ( M1 = 494, M2 = 322, M3 = 2508, M4 = 2549 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) + INTEGER IPW2 + DOUBLE PRECISION R + PARAMETER ( IPW2 = 4096, R = ONE / IPW2 ) +* .. +* .. Local Scalars .. + INTEGER IT1, IT2, IT3, IT4 +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, MOD +* .. +* .. Executable Statements .. +* +* multiply the seed by the multiplier modulo 2**48 +* + IT4 = ISEED( 4 )*M4 + IT3 = IT4 / IPW2 + IT4 = IT4 - IPW2*IT3 + IT3 = IT3 + ISEED( 3 )*M4 + ISEED( 4 )*M3 + IT2 = IT3 / IPW2 + IT3 = IT3 - IPW2*IT2 + IT2 = IT2 + ISEED( 2 )*M4 + ISEED( 3 )*M3 + ISEED( 4 )*M2 + IT1 = IT2 / IPW2 + IT2 = IT2 - IPW2*IT1 + IT1 = IT1 + ISEED( 1 )*M4 + ISEED( 2 )*M3 + ISEED( 3 )*M2 + + $ ISEED( 4 )*M1 + IT1 = MOD( IT1, IPW2 ) +* +* return updated seed +* + ISEED( 1 ) = IT1 + ISEED( 2 ) = IT2 + ISEED( 3 ) = IT3 + ISEED( 4 ) = IT4 +* +* convert 48-bit integer to a real number in the interval (0,1) +* + DLARAN = R*( DBLE( IT1 )+R*( DBLE( IT2 )+R*( DBLE( IT3 )+R* + $ ( DBLE( IT4 ) ) ) ) ) + RETURN +* +* End of DLARAN +* + END diff --git a/dep/lapack/dlarf.f b/dep/lapack/dlarf.f new file mode 100644 index 00000000..0d9278c9 --- /dev/null +++ b/dep/lapack/dlarf.f @@ -0,0 +1,153 @@ + SUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK ) + IMPLICIT NONE +* +* -- LAPACK auxiliary routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER SIDE + INTEGER INCV, LDC, M, N + DOUBLE PRECISION TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLARF applies a real elementary reflector H to a real m by n matrix +* C, from either the left or the right. H is represented in the form +* +* H = I - tau * v * v**T +* +* where tau is a real scalar and v is a real vector. +* +* If tau = 0, then H is taken to be the unit matrix. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': form H * C +* = 'R': form C * H +* +* M (input) INTEGER +* The number of rows of the matrix C. +* +* N (input) INTEGER +* The number of columns of the matrix C. +* +* V (input) DOUBLE PRECISION array, dimension +* (1 + (M-1)*abs(INCV)) if SIDE = 'L' +* or (1 + (N-1)*abs(INCV)) if SIDE = 'R' +* The vector v in the representation of H. V is not used if +* TAU = 0. +* +* INCV (input) INTEGER +* The increment between elements of v. INCV <> 0. +* +* TAU (input) DOUBLE PRECISION +* The value tau in the representation of H. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the m by n matrix C. +* On exit, C is overwritten by the matrix H * C if SIDE = 'L', +* or C * H if SIDE = 'R'. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace) DOUBLE PRECISION array, dimension +* (N) if SIDE = 'L' +* or (M) if SIDE = 'R' +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL APPLYLEFT + INTEGER I, LASTV, LASTC +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DGER +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILADLR, ILADLC + EXTERNAL LSAME, ILADLR, ILADLC +* .. +* .. Executable Statements .. +* + APPLYLEFT = LSAME( SIDE, 'L' ) + LASTV = 0 + LASTC = 0 + IF( TAU.NE.ZERO ) THEN +! Set up variables for scanning V. LASTV begins pointing to the end +! of V. + IF( APPLYLEFT ) THEN + LASTV = M + ELSE + LASTV = N + END IF + IF( INCV.GT.0 ) THEN + I = 1 + (LASTV-1) * INCV + ELSE + I = 1 + END IF +! Look for the last non-zero row in V. + DO WHILE( LASTV.GT.0 .AND. V( I ).EQ.ZERO ) + LASTV = LASTV - 1 + I = I - INCV + END DO + IF( APPLYLEFT ) THEN +! Scan for the last non-zero column in C(1:lastv,:). + LASTC = ILADLC(LASTV, N, C, LDC) + ELSE +! Scan for the last non-zero row in C(:,1:lastv). + LASTC = ILADLR(M, LASTV, C, LDC) + END IF + END IF +! Note that lastc.eq.0 renders the BLAS operations null; no special +! case is needed at this level. + IF( APPLYLEFT ) THEN +* +* Form H * C +* + IF( LASTV.GT.0 ) THEN +* +* w(1:lastc,1) := C(1:lastv,1:lastc)**T * v(1:lastv,1) +* + CALL DGEMV( 'Transpose', LASTV, LASTC, ONE, C, LDC, V, INCV, + $ ZERO, WORK, 1 ) +* +* C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**T +* + CALL DGER( LASTV, LASTC, -TAU, V, INCV, WORK, 1, C, LDC ) + END IF + ELSE +* +* Form C * H +* + IF( LASTV.GT.0 ) THEN +* +* w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1) +* + CALL DGEMV( 'No transpose', LASTC, LASTV, ONE, C, LDC, + $ V, INCV, ZERO, WORK, 1 ) +* +* C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**T +* + CALL DGER( LASTC, LASTV, -TAU, WORK, 1, V, INCV, C, LDC ) + END IF + END IF + RETURN +* +* End of DLARF +* + END diff --git a/dep/lapack/dlarfb.f b/dep/lapack/dlarfb.f new file mode 100644 index 00000000..3338bbf6 --- /dev/null +++ b/dep/lapack/dlarfb.f @@ -0,0 +1,666 @@ + SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV, + $ T, LDT, C, LDC, WORK, LDWORK ) + IMPLICIT NONE +* +* -- LAPACK auxiliary routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER DIRECT, SIDE, STOREV, TRANS + INTEGER K, LDC, LDT, LDV, LDWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ), + $ WORK( LDWORK, * ) +* .. +* +* Purpose +* ======= +* +* DLARFB applies a real block reflector H or its transpose H**T to a +* real m by n matrix C, from either the left or the right. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply H or H**T from the Left +* = 'R': apply H or H**T from the Right +* +* TRANS (input) CHARACTER*1 +* = 'N': apply H (No transpose) +* = 'T': apply H**T (Transpose) +* +* DIRECT (input) CHARACTER*1 +* Indicates how H is formed from a product of elementary +* reflectors +* = 'F': H = H(1) H(2) . . . H(k) (Forward) +* = 'B': H = H(k) . . . H(2) H(1) (Backward) +* +* STOREV (input) CHARACTER*1 +* Indicates how the vectors which define the elementary +* reflectors are stored: +* = 'C': Columnwise +* = 'R': Rowwise +* +* M (input) INTEGER +* The number of rows of the matrix C. +* +* N (input) INTEGER +* The number of columns of the matrix C. +* +* K (input) INTEGER +* The order of the matrix T (= the number of elementary +* reflectors whose product defines the block reflector). +* +* V (input) DOUBLE PRECISION array, dimension +* (LDV,K) if STOREV = 'C' +* (LDV,M) if STOREV = 'R' and SIDE = 'L' +* (LDV,N) if STOREV = 'R' and SIDE = 'R' +* The matrix V. See Further Details. +* +* LDV (input) INTEGER +* The leading dimension of the array V. +* If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M); +* if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N); +* if STOREV = 'R', LDV >= K. +* +* T (input) DOUBLE PRECISION array, dimension (LDT,K) +* The triangular k by k matrix T in the representation of the +* block reflector. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= K. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the m by n matrix C. +* On exit, C is overwritten by H*C or H**T*C or C*H or C*H**T. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,K) +* +* LDWORK (input) INTEGER +* The leading dimension of the array WORK. +* If SIDE = 'L', LDWORK >= max(1,N); +* if SIDE = 'R', LDWORK >= max(1,M). +* +* Further Details +* =============== +* +* The shape of the matrix V and the storage of the vectors which define +* the H(i) is best illustrated by the following example with n = 5 and +* k = 3. The elements equal to 1 are not stored; the corresponding +* array elements are modified but restored on exit. The rest of the +* array is not used. +* +* DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R': +* +* V = ( 1 ) V = ( 1 v1 v1 v1 v1 ) +* ( v1 1 ) ( 1 v2 v2 v2 ) +* ( v1 v2 1 ) ( 1 v3 v3 ) +* ( v1 v2 v3 ) +* ( v1 v2 v3 ) +* +* DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R': +* +* V = ( v1 v2 v3 ) V = ( v1 v1 1 ) +* ( v1 v2 v3 ) ( v2 v2 v2 1 ) +* ( 1 v2 v3 ) ( v3 v3 v3 v3 1 ) +* ( 1 v3 ) +* ( 1 ) +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + CHARACTER TRANST + INTEGER I, J, LASTV, LASTC +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILADLR, ILADLC + EXTERNAL LSAME, ILADLR, ILADLC +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DGEMM, DTRMM +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( M.LE.0 .OR. N.LE.0 ) + $ RETURN +* + IF( LSAME( TRANS, 'N' ) ) THEN + TRANST = 'T' + ELSE + TRANST = 'N' + END IF +* + IF( LSAME( STOREV, 'C' ) ) THEN +* + IF( LSAME( DIRECT, 'F' ) ) THEN +* +* Let V = ( V1 ) (first K rows) +* ( V2 ) +* where V1 is unit lower triangular. +* + IF( LSAME( SIDE, 'L' ) ) THEN +* +* Form H * C or H**T * C where C = ( C1 ) +* ( C2 ) +* + LASTV = MAX( K, ILADLR( M, K, V, LDV ) ) + LASTC = ILADLC( LASTV, N, C, LDC ) +* +* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK) +* +* W := C1**T +* + DO 10 J = 1, K + CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 ) + 10 CONTINUE +* +* W := W * V1 +* + CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C2**T *V2 +* + CALL DGEMM( 'Transpose', 'No transpose', + $ LASTC, K, LASTV-K, + $ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T**T or W * T +* + CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - V * W**T +* + IF( LASTV.GT.K ) THEN +* +* C2 := C2 - V2 * W**T +* + CALL DGEMM( 'No transpose', 'Transpose', + $ LASTV-K, LASTC, K, + $ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE, + $ C( K+1, 1 ), LDC ) + END IF +* +* W := W * V1**T +* + CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) +* +* C1 := C1 - W**T +* + DO 30 J = 1, K + DO 20 I = 1, LASTC + C( J, I ) = C( J, I ) - WORK( I, J ) + 20 CONTINUE + 30 CONTINUE +* + ELSE IF( LSAME( SIDE, 'R' ) ) THEN +* +* Form C * H or C * H**T where C = ( C1 C2 ) +* + LASTV = MAX( K, ILADLR( N, K, V, LDV ) ) + LASTC = ILADLR( M, LASTV, C, LDC ) +* +* W := C * V = (C1*V1 + C2*V2) (stored in WORK) +* +* W := C1 +* + DO 40 J = 1, K + CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 ) + 40 CONTINUE +* +* W := W * V1 +* + CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C2 * V2 +* + CALL DGEMM( 'No transpose', 'No transpose', + $ LASTC, K, LASTV-K, + $ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T or W * T**T +* + CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - W * V**T +* + IF( LASTV.GT.K ) THEN +* +* C2 := C2 - W * V2**T +* + CALL DGEMM( 'No transpose', 'Transpose', + $ LASTC, LASTV-K, K, + $ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE, + $ C( 1, K+1 ), LDC ) + END IF +* +* W := W * V1**T +* + CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) +* +* C1 := C1 - W +* + DO 60 J = 1, K + DO 50 I = 1, LASTC + C( I, J ) = C( I, J ) - WORK( I, J ) + 50 CONTINUE + 60 CONTINUE + END IF +* + ELSE +* +* Let V = ( V1 ) +* ( V2 ) (last K rows) +* where V2 is unit upper triangular. +* + IF( LSAME( SIDE, 'L' ) ) THEN +* +* Form H * C or H**T * C where C = ( C1 ) +* ( C2 ) +* + LASTV = MAX( K, ILADLR( M, K, V, LDV ) ) + LASTC = ILADLC( LASTV, N, C, LDC ) +* +* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK) +* +* W := C2**T +* + DO 70 J = 1, K + CALL DCOPY( LASTC, C( LASTV-K+J, 1 ), LDC, + $ WORK( 1, J ), 1 ) + 70 CONTINUE +* +* W := W * V2 +* + CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', + $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV, + $ WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C1**T*V1 +* + CALL DGEMM( 'Transpose', 'No transpose', + $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T**T or W * T +* + CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - V * W**T +* + IF( LASTV.GT.K ) THEN +* +* C1 := C1 - V1 * W**T +* + CALL DGEMM( 'No transpose', 'Transpose', + $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK, + $ ONE, C, LDC ) + END IF +* +* W := W * V2**T +* + CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', + $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV, + $ WORK, LDWORK ) +* +* C2 := C2 - W**T +* + DO 90 J = 1, K + DO 80 I = 1, LASTC + C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J) + 80 CONTINUE + 90 CONTINUE +* + ELSE IF( LSAME( SIDE, 'R' ) ) THEN +* +* Form C * H or C * H**T where C = ( C1 C2 ) +* + LASTV = MAX( K, ILADLR( N, K, V, LDV ) ) + LASTC = ILADLR( M, LASTV, C, LDC ) +* +* W := C * V = (C1*V1 + C2*V2) (stored in WORK) +* +* W := C2 +* + DO 100 J = 1, K + CALL DCOPY( LASTC, C( 1, N-K+J ), 1, WORK( 1, J ), 1 ) + 100 CONTINUE +* +* W := W * V2 +* + CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', + $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV, + $ WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C1 * V1 +* + CALL DGEMM( 'No transpose', 'No transpose', + $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T or W * T**T +* + CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - W * V**T +* + IF( LASTV.GT.K ) THEN +* +* C1 := C1 - W * V1**T +* + CALL DGEMM( 'No transpose', 'Transpose', + $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV, + $ ONE, C, LDC ) + END IF +* +* W := W * V2**T +* + CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', + $ LASTC, K, ONE, V( LASTV-K+1, 1 ), LDV, + $ WORK, LDWORK ) +* +* C2 := C2 - W +* + DO 120 J = 1, K + DO 110 I = 1, LASTC + C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J) + 110 CONTINUE + 120 CONTINUE + END IF + END IF +* + ELSE IF( LSAME( STOREV, 'R' ) ) THEN +* + IF( LSAME( DIRECT, 'F' ) ) THEN +* +* Let V = ( V1 V2 ) (V1: first K columns) +* where V1 is unit upper triangular. +* + IF( LSAME( SIDE, 'L' ) ) THEN +* +* Form H * C or H**T * C where C = ( C1 ) +* ( C2 ) +* + LASTV = MAX( K, ILADLC( K, M, V, LDV ) ) + LASTC = ILADLC( LASTV, N, C, LDC ) +* +* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK) +* +* W := C1**T +* + DO 130 J = 1, K + CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 ) + 130 CONTINUE +* +* W := W * V1**T +* + CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C2**T*V2**T +* + CALL DGEMM( 'Transpose', 'Transpose', + $ LASTC, K, LASTV-K, + $ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T**T or W * T +* + CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - V**T * W**T +* + IF( LASTV.GT.K ) THEN +* +* C2 := C2 - V2**T * W**T +* + CALL DGEMM( 'Transpose', 'Transpose', + $ LASTV-K, LASTC, K, + $ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK, + $ ONE, C( K+1, 1 ), LDC ) + END IF +* +* W := W * V1 +* + CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) +* +* C1 := C1 - W**T +* + DO 150 J = 1, K + DO 140 I = 1, LASTC + C( J, I ) = C( J, I ) - WORK( I, J ) + 140 CONTINUE + 150 CONTINUE +* + ELSE IF( LSAME( SIDE, 'R' ) ) THEN +* +* Form C * H or C * H**T where C = ( C1 C2 ) +* + LASTV = MAX( K, ILADLC( K, N, V, LDV ) ) + LASTC = ILADLR( M, LASTV, C, LDC ) +* +* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK) +* +* W := C1 +* + DO 160 J = 1, K + CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 ) + 160 CONTINUE +* +* W := W * V1**T +* + CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C2 * V2**T +* + CALL DGEMM( 'No transpose', 'Transpose', + $ LASTC, K, LASTV-K, + $ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T or W * T**T +* + CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - W * V +* + IF( LASTV.GT.K ) THEN +* +* C2 := C2 - W * V2 +* + CALL DGEMM( 'No transpose', 'No transpose', + $ LASTC, LASTV-K, K, + $ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV, + $ ONE, C( 1, K+1 ), LDC ) + END IF +* +* W := W * V1 +* + CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', + $ LASTC, K, ONE, V, LDV, WORK, LDWORK ) +* +* C1 := C1 - W +* + DO 180 J = 1, K + DO 170 I = 1, LASTC + C( I, J ) = C( I, J ) - WORK( I, J ) + 170 CONTINUE + 180 CONTINUE +* + END IF +* + ELSE +* +* Let V = ( V1 V2 ) (V2: last K columns) +* where V2 is unit lower triangular. +* + IF( LSAME( SIDE, 'L' ) ) THEN +* +* Form H * C or H**T * C where C = ( C1 ) +* ( C2 ) +* + LASTV = MAX( K, ILADLC( K, M, V, LDV ) ) + LASTC = ILADLC( LASTV, N, C, LDC ) +* +* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK) +* +* W := C2**T +* + DO 190 J = 1, K + CALL DCOPY( LASTC, C( LASTV-K+J, 1 ), LDC, + $ WORK( 1, J ), 1 ) + 190 CONTINUE +* +* W := W * V2**T +* + CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', + $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV, + $ WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C1**T * V1**T +* + CALL DGEMM( 'Transpose', 'Transpose', + $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T**T or W * T +* + CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - V**T * W**T +* + IF( LASTV.GT.K ) THEN +* +* C1 := C1 - V1**T * W**T +* + CALL DGEMM( 'Transpose', 'Transpose', + $ LASTV-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK, + $ ONE, C, LDC ) + END IF +* +* W := W * V2 +* + CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', + $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV, + $ WORK, LDWORK ) +* +* C2 := C2 - W**T +* + DO 210 J = 1, K + DO 200 I = 1, LASTC + C( LASTV-K+J, I ) = C( LASTV-K+J, I ) - WORK(I, J) + 200 CONTINUE + 210 CONTINUE +* + ELSE IF( LSAME( SIDE, 'R' ) ) THEN +* +* Form C * H or C * H**T where C = ( C1 C2 ) +* + LASTV = MAX( K, ILADLC( K, N, V, LDV ) ) + LASTC = ILADLR( M, LASTV, C, LDC ) +* +* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK) +* +* W := C2 +* + DO 220 J = 1, K + CALL DCOPY( LASTC, C( 1, LASTV-K+J ), 1, + $ WORK( 1, J ), 1 ) + 220 CONTINUE +* +* W := W * V2**T +* + CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', + $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV, + $ WORK, LDWORK ) + IF( LASTV.GT.K ) THEN +* +* W := W + C1 * V1**T +* + CALL DGEMM( 'No transpose', 'Transpose', + $ LASTC, K, LASTV-K, ONE, C, LDC, V, LDV, + $ ONE, WORK, LDWORK ) + END IF +* +* W := W * T or W * T**T +* + CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit', + $ LASTC, K, ONE, T, LDT, WORK, LDWORK ) +* +* C := C - W * V +* + IF( LASTV.GT.K ) THEN +* +* C1 := C1 - W * V1 +* + CALL DGEMM( 'No transpose', 'No transpose', + $ LASTC, LASTV-K, K, -ONE, WORK, LDWORK, V, LDV, + $ ONE, C, LDC ) + END IF +* +* W := W * V2 +* + CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', + $ LASTC, K, ONE, V( 1, LASTV-K+1 ), LDV, + $ WORK, LDWORK ) +* +* C1 := C1 - W +* + DO 240 J = 1, K + DO 230 I = 1, LASTC + C( I, LASTV-K+J ) = C( I, LASTV-K+J ) - WORK(I, J) + 230 CONTINUE + 240 CONTINUE +* + END IF +* + END IF + END IF +* + RETURN +* +* End of DLARFB +* + END diff --git a/dep/lapack/dlarfg.f b/dep/lapack/dlarfg.f new file mode 100644 index 00000000..a4221e79 --- /dev/null +++ b/dep/lapack/dlarfg.f @@ -0,0 +1,134 @@ + SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU ) +* +* -- LAPACK auxiliary routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INCX, N + DOUBLE PRECISION ALPHA, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION X( * ) +* .. +* +* Purpose +* ======= +* +* DLARFG generates a real elementary reflector H of order n, such +* that +* +* H * ( alpha ) = ( beta ), H**T * H = I. +* ( x ) ( 0 ) +* +* where alpha and beta are scalars, and x is an (n-1)-element real +* vector. H is represented in the form +* +* H = I - tau * ( 1 ) * ( 1 v**T ) , +* ( v ) +* +* where tau is a real scalar and v is a real (n-1)-element +* vector. +* +* If the elements of x are all zero, then tau = 0 and H is taken to be +* the unit matrix. +* +* Otherwise 1 <= tau <= 2. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the elementary reflector. +* +* ALPHA (input/output) DOUBLE PRECISION +* On entry, the value alpha. +* On exit, it is overwritten with the value beta. +* +* X (input/output) DOUBLE PRECISION array, dimension +* (1+(N-2)*abs(INCX)) +* On entry, the vector x. +* On exit, it is overwritten with the vector v. +* +* INCX (input) INTEGER +* The increment between elements of X. INCX > 0. +* +* TAU (output) DOUBLE PRECISION +* The value tau. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER J, KNT + DOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2 + EXTERNAL DLAMCH, DLAPY2, DNRM2 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN +* .. +* .. External Subroutines .. + EXTERNAL DSCAL +* .. +* .. Executable Statements .. +* + IF( N.LE.1 ) THEN + TAU = ZERO + RETURN + END IF +* + XNORM = DNRM2( N-1, X, INCX ) +* + IF( XNORM.EQ.ZERO ) THEN +* +* H = I +* + TAU = ZERO + ELSE +* +* general case +* + BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA ) + SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' ) + KNT = 0 + IF( ABS( BETA ).LT.SAFMIN ) THEN +* +* XNORM, BETA may be inaccurate; scale X and recompute them +* + RSAFMN = ONE / SAFMIN + 10 CONTINUE + KNT = KNT + 1 + CALL DSCAL( N-1, RSAFMN, X, INCX ) + BETA = BETA*RSAFMN + ALPHA = ALPHA*RSAFMN + IF( ABS( BETA ).LT.SAFMIN ) + $ GO TO 10 +* +* New BETA is at most 1, at least SAFMIN +* + XNORM = DNRM2( N-1, X, INCX ) + BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA ) + END IF + TAU = ( BETA-ALPHA ) / BETA + CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX ) +* +* If ALPHA is subnormal, it may lose relative accuracy +* + DO 20 J = 1, KNT + BETA = BETA*SAFMIN + 20 CONTINUE + ALPHA = BETA + END IF +* + RETURN +* +* End of DLARFG +* + END diff --git a/dep/lapack/dlarft.f b/dep/lapack/dlarft.f new file mode 100644 index 00000000..bbfa9c78 --- /dev/null +++ b/dep/lapack/dlarft.f @@ -0,0 +1,252 @@ + SUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT ) + IMPLICIT NONE +* +* -- LAPACK auxiliary routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER DIRECT, STOREV + INTEGER K, LDT, LDV, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * ) +* .. +* +* Purpose +* ======= +* +* DLARFT forms the triangular factor T of a real block reflector H +* of order n, which is defined as a product of k elementary reflectors. +* +* If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular; +* +* If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular. +* +* If STOREV = 'C', the vector which defines the elementary reflector +* H(i) is stored in the i-th column of the array V, and +* +* H = I - V * T * V**T +* +* If STOREV = 'R', the vector which defines the elementary reflector +* H(i) is stored in the i-th row of the array V, and +* +* H = I - V**T * T * V +* +* Arguments +* ========= +* +* DIRECT (input) CHARACTER*1 +* Specifies the order in which the elementary reflectors are +* multiplied to form the block reflector: +* = 'F': H = H(1) H(2) . . . H(k) (Forward) +* = 'B': H = H(k) . . . H(2) H(1) (Backward) +* +* STOREV (input) CHARACTER*1 +* Specifies how the vectors which define the elementary +* reflectors are stored (see also Further Details): +* = 'C': columnwise +* = 'R': rowwise +* +* N (input) INTEGER +* The order of the block reflector H. N >= 0. +* +* K (input) INTEGER +* The order of the triangular factor T (= the number of +* elementary reflectors). K >= 1. +* +* V (input/output) DOUBLE PRECISION array, dimension +* (LDV,K) if STOREV = 'C' +* (LDV,N) if STOREV = 'R' +* The matrix V. See further details. +* +* LDV (input) INTEGER +* The leading dimension of the array V. +* If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K. +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i). +* +* T (output) DOUBLE PRECISION array, dimension (LDT,K) +* The k by k triangular factor T of the block reflector. +* If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is +* lower triangular. The rest of the array is not used. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= K. +* +* Further Details +* =============== +* +* The shape of the matrix V and the storage of the vectors which define +* the H(i) is best illustrated by the following example with n = 5 and +* k = 3. The elements equal to 1 are not stored; the corresponding +* array elements are modified but restored on exit. The rest of the +* array is not used. +* +* DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R': +* +* V = ( 1 ) V = ( 1 v1 v1 v1 v1 ) +* ( v1 1 ) ( 1 v2 v2 v2 ) +* ( v1 v2 1 ) ( 1 v3 v3 ) +* ( v1 v2 v3 ) +* ( v1 v2 v3 ) +* +* DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R': +* +* V = ( v1 v2 v3 ) V = ( v1 v1 1 ) +* ( v1 v2 v3 ) ( v2 v2 v2 1 ) +* ( 1 v2 v3 ) ( v3 v3 v3 v3 1 ) +* ( 1 v3 ) +* ( 1 ) +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J, PREVLASTV, LASTV + DOUBLE PRECISION VII +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DTRMV +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + IF( LSAME( DIRECT, 'F' ) ) THEN + PREVLASTV = N + DO 20 I = 1, K + PREVLASTV = MAX( I, PREVLASTV ) + IF( TAU( I ).EQ.ZERO ) THEN +* +* H(i) = I +* + DO 10 J = 1, I + T( J, I ) = ZERO + 10 CONTINUE + ELSE +* +* general case +* + VII = V( I, I ) + V( I, I ) = ONE + IF( LSAME( STOREV, 'C' ) ) THEN +! Skip any trailing zeros. + DO LASTV = N, I+1, -1 + IF( V( LASTV, I ).NE.ZERO ) EXIT + END DO + J = MIN( LASTV, PREVLASTV ) +* +* T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**T * V(i:j,i) +* + CALL DGEMV( 'Transpose', J-I+1, I-1, -TAU( I ), + $ V( I, 1 ), LDV, V( I, I ), 1, ZERO, + $ T( 1, I ), 1 ) + ELSE +! Skip any trailing zeros. + DO LASTV = N, I+1, -1 + IF( V( I, LASTV ).NE.ZERO ) EXIT + END DO + J = MIN( LASTV, PREVLASTV ) +* +* T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**T +* + CALL DGEMV( 'No transpose', I-1, J-I+1, -TAU( I ), + $ V( 1, I ), LDV, V( I, I ), LDV, ZERO, + $ T( 1, I ), 1 ) + END IF + V( I, I ) = VII +* +* T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i) +* + CALL DTRMV( 'Upper', 'No transpose', 'Non-unit', I-1, T, + $ LDT, T( 1, I ), 1 ) + T( I, I ) = TAU( I ) + IF( I.GT.1 ) THEN + PREVLASTV = MAX( PREVLASTV, LASTV ) + ELSE + PREVLASTV = LASTV + END IF + END IF + 20 CONTINUE + ELSE + PREVLASTV = 1 + DO 40 I = K, 1, -1 + IF( TAU( I ).EQ.ZERO ) THEN +* +* H(i) = I +* + DO 30 J = I, K + T( J, I ) = ZERO + 30 CONTINUE + ELSE +* +* general case +* + IF( I.LT.K ) THEN + IF( LSAME( STOREV, 'C' ) ) THEN + VII = V( N-K+I, I ) + V( N-K+I, I ) = ONE +! Skip any leading zeros. + DO LASTV = 1, I-1 + IF( V( LASTV, I ).NE.ZERO ) EXIT + END DO + J = MAX( LASTV, PREVLASTV ) +* +* T(i+1:k,i) := +* - tau(i) * V(j:n-k+i,i+1:k)**T * V(j:n-k+i,i) +* + CALL DGEMV( 'Transpose', N-K+I-J+1, K-I, -TAU( I ), + $ V( J, I+1 ), LDV, V( J, I ), 1, ZERO, + $ T( I+1, I ), 1 ) + V( N-K+I, I ) = VII + ELSE + VII = V( I, N-K+I ) + V( I, N-K+I ) = ONE +! Skip any leading zeros. + DO LASTV = 1, I-1 + IF( V( I, LASTV ).NE.ZERO ) EXIT + END DO + J = MAX( LASTV, PREVLASTV ) +* +* T(i+1:k,i) := +* - tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**T +* + CALL DGEMV( 'No transpose', K-I, N-K+I-J+1, + $ -TAU( I ), V( I+1, J ), LDV, V( I, J ), LDV, + $ ZERO, T( I+1, I ), 1 ) + V( I, N-K+I ) = VII + END IF +* +* T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i) +* + CALL DTRMV( 'Lower', 'No transpose', 'Non-unit', K-I, + $ T( I+1, I+1 ), LDT, T( I+1, I ), 1 ) + IF( I.GT.1 ) THEN + PREVLASTV = MIN( PREVLASTV, LASTV ) + ELSE + PREVLASTV = LASTV + END IF + END IF + T( I, I ) = TAU( I ) + END IF + 40 CONTINUE + END IF + RETURN +* +* End of DLARFT +* + END diff --git a/dep/lapack/dlarfx.f b/dep/lapack/dlarfx.f new file mode 100644 index 00000000..a3e46acd --- /dev/null +++ b/dep/lapack/dlarfx.f @@ -0,0 +1,639 @@ + SUBROUTINE DLARFX( SIDE, M, N, V, TAU, C, LDC, WORK ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + CHARACTER SIDE + INTEGER LDC, M, N + DOUBLE PRECISION TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLARFX applies a real elementary reflector H to a real m by n +* matrix C, from either the left or the right. H is represented in the +* form +* +* H = I - tau * v * v' +* +* where tau is a real scalar and v is a real vector. +* +* If tau = 0, then H is taken to be the unit matrix +* +* This version uses inline code if H has order < 11. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': form H * C +* = 'R': form C * H +* +* M (input) INTEGER +* The number of rows of the matrix C. +* +* N (input) INTEGER +* The number of columns of the matrix C. +* +* V (input) DOUBLE PRECISION array, dimension (M) if SIDE = 'L' +* or (N) if SIDE = 'R' +* The vector v in the representation of H. +* +* TAU (input) DOUBLE PRECISION +* The value tau in the representation of H. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the m by n matrix C. +* On exit, C is overwritten by the matrix H * C if SIDE = 'L', +* or C * H if SIDE = 'R'. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDA >= (1,M). +* +* WORK (workspace) DOUBLE PRECISION array, dimension +* (N) if SIDE = 'L' +* or (M) if SIDE = 'R' +* WORK is not referenced if H has order < 11. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER J + DOUBLE PRECISION SUM, T1, T10, T2, T3, T4, T5, T6, T7, T8, T9, + $ V1, V10, V2, V3, V4, V5, V6, V7, V8, V9 +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DGER +* .. +* .. Executable Statements .. +* + IF( TAU.EQ.ZERO ) + $ RETURN + IF( LSAME( SIDE, 'L' ) ) THEN +* +* Form H * C, where H has order m. +* + GO TO ( 10, 30, 50, 70, 90, 110, 130, 150, + $ 170, 190 )M +* +* Code for general M +* +* w := C'*v +* + CALL DGEMV( 'Transpose', M, N, ONE, C, LDC, V, 1, ZERO, WORK, + $ 1 ) +* +* C := C - tau * v * w' +* + CALL DGER( M, N, -TAU, V, 1, WORK, 1, C, LDC ) + GO TO 410 + 10 CONTINUE +* +* Special code for 1 x 1 Householder +* + T1 = ONE - TAU*V( 1 )*V( 1 ) + DO 20 J = 1, N + C( 1, J ) = T1*C( 1, J ) + 20 CONTINUE + GO TO 410 + 30 CONTINUE +* +* Special code for 2 x 2 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + DO 40 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + 40 CONTINUE + GO TO 410 + 50 CONTINUE +* +* Special code for 3 x 3 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + DO 60 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + 60 CONTINUE + GO TO 410 + 70 CONTINUE +* +* Special code for 4 x 4 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + DO 80 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + 80 CONTINUE + GO TO 410 + 90 CONTINUE +* +* Special code for 5 x 5 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + DO 100 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + V5*C( 5, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + C( 5, J ) = C( 5, J ) - SUM*T5 + 100 CONTINUE + GO TO 410 + 110 CONTINUE +* +* Special code for 6 x 6 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + DO 120 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + C( 5, J ) = C( 5, J ) - SUM*T5 + C( 6, J ) = C( 6, J ) - SUM*T6 + 120 CONTINUE + GO TO 410 + 130 CONTINUE +* +* Special code for 7 x 7 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + DO 140 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) + + $ V7*C( 7, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + C( 5, J ) = C( 5, J ) - SUM*T5 + C( 6, J ) = C( 6, J ) - SUM*T6 + C( 7, J ) = C( 7, J ) - SUM*T7 + 140 CONTINUE + GO TO 410 + 150 CONTINUE +* +* Special code for 8 x 8 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + V8 = V( 8 ) + T8 = TAU*V8 + DO 160 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) + + $ V7*C( 7, J ) + V8*C( 8, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + C( 5, J ) = C( 5, J ) - SUM*T5 + C( 6, J ) = C( 6, J ) - SUM*T6 + C( 7, J ) = C( 7, J ) - SUM*T7 + C( 8, J ) = C( 8, J ) - SUM*T8 + 160 CONTINUE + GO TO 410 + 170 CONTINUE +* +* Special code for 9 x 9 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + V8 = V( 8 ) + T8 = TAU*V8 + V9 = V( 9 ) + T9 = TAU*V9 + DO 180 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) + + $ V7*C( 7, J ) + V8*C( 8, J ) + V9*C( 9, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + C( 5, J ) = C( 5, J ) - SUM*T5 + C( 6, J ) = C( 6, J ) - SUM*T6 + C( 7, J ) = C( 7, J ) - SUM*T7 + C( 8, J ) = C( 8, J ) - SUM*T8 + C( 9, J ) = C( 9, J ) - SUM*T9 + 180 CONTINUE + GO TO 410 + 190 CONTINUE +* +* Special code for 10 x 10 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + V8 = V( 8 ) + T8 = TAU*V8 + V9 = V( 9 ) + T9 = TAU*V9 + V10 = V( 10 ) + T10 = TAU*V10 + DO 200 J = 1, N + SUM = V1*C( 1, J ) + V2*C( 2, J ) + V3*C( 3, J ) + + $ V4*C( 4, J ) + V5*C( 5, J ) + V6*C( 6, J ) + + $ V7*C( 7, J ) + V8*C( 8, J ) + V9*C( 9, J ) + + $ V10*C( 10, J ) + C( 1, J ) = C( 1, J ) - SUM*T1 + C( 2, J ) = C( 2, J ) - SUM*T2 + C( 3, J ) = C( 3, J ) - SUM*T3 + C( 4, J ) = C( 4, J ) - SUM*T4 + C( 5, J ) = C( 5, J ) - SUM*T5 + C( 6, J ) = C( 6, J ) - SUM*T6 + C( 7, J ) = C( 7, J ) - SUM*T7 + C( 8, J ) = C( 8, J ) - SUM*T8 + C( 9, J ) = C( 9, J ) - SUM*T9 + C( 10, J ) = C( 10, J ) - SUM*T10 + 200 CONTINUE + GO TO 410 + ELSE +* +* Form C * H, where H has order n. +* + GO TO ( 210, 230, 250, 270, 290, 310, 330, 350, + $ 370, 390 )N +* +* Code for general N +* +* w := C * v +* + CALL DGEMV( 'No transpose', M, N, ONE, C, LDC, V, 1, ZERO, + $ WORK, 1 ) +* +* C := C - tau * w * v' +* + CALL DGER( M, N, -TAU, WORK, 1, V, 1, C, LDC ) + GO TO 410 + 210 CONTINUE +* +* Special code for 1 x 1 Householder +* + T1 = ONE - TAU*V( 1 )*V( 1 ) + DO 220 J = 1, M + C( J, 1 ) = T1*C( J, 1 ) + 220 CONTINUE + GO TO 410 + 230 CONTINUE +* +* Special code for 2 x 2 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + DO 240 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + 240 CONTINUE + GO TO 410 + 250 CONTINUE +* +* Special code for 3 x 3 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + DO 260 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + 260 CONTINUE + GO TO 410 + 270 CONTINUE +* +* Special code for 4 x 4 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + DO 280 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + 280 CONTINUE + GO TO 410 + 290 CONTINUE +* +* Special code for 5 x 5 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + DO 300 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + V5*C( J, 5 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + C( J, 5 ) = C( J, 5 ) - SUM*T5 + 300 CONTINUE + GO TO 410 + 310 CONTINUE +* +* Special code for 6 x 6 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + DO 320 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + C( J, 5 ) = C( J, 5 ) - SUM*T5 + C( J, 6 ) = C( J, 6 ) - SUM*T6 + 320 CONTINUE + GO TO 410 + 330 CONTINUE +* +* Special code for 7 x 7 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + DO 340 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) + + $ V7*C( J, 7 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + C( J, 5 ) = C( J, 5 ) - SUM*T5 + C( J, 6 ) = C( J, 6 ) - SUM*T6 + C( J, 7 ) = C( J, 7 ) - SUM*T7 + 340 CONTINUE + GO TO 410 + 350 CONTINUE +* +* Special code for 8 x 8 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + V8 = V( 8 ) + T8 = TAU*V8 + DO 360 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) + + $ V7*C( J, 7 ) + V8*C( J, 8 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + C( J, 5 ) = C( J, 5 ) - SUM*T5 + C( J, 6 ) = C( J, 6 ) - SUM*T6 + C( J, 7 ) = C( J, 7 ) - SUM*T7 + C( J, 8 ) = C( J, 8 ) - SUM*T8 + 360 CONTINUE + GO TO 410 + 370 CONTINUE +* +* Special code for 9 x 9 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + V8 = V( 8 ) + T8 = TAU*V8 + V9 = V( 9 ) + T9 = TAU*V9 + DO 380 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) + + $ V7*C( J, 7 ) + V8*C( J, 8 ) + V9*C( J, 9 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + C( J, 5 ) = C( J, 5 ) - SUM*T5 + C( J, 6 ) = C( J, 6 ) - SUM*T6 + C( J, 7 ) = C( J, 7 ) - SUM*T7 + C( J, 8 ) = C( J, 8 ) - SUM*T8 + C( J, 9 ) = C( J, 9 ) - SUM*T9 + 380 CONTINUE + GO TO 410 + 390 CONTINUE +* +* Special code for 10 x 10 Householder +* + V1 = V( 1 ) + T1 = TAU*V1 + V2 = V( 2 ) + T2 = TAU*V2 + V3 = V( 3 ) + T3 = TAU*V3 + V4 = V( 4 ) + T4 = TAU*V4 + V5 = V( 5 ) + T5 = TAU*V5 + V6 = V( 6 ) + T6 = TAU*V6 + V7 = V( 7 ) + T7 = TAU*V7 + V8 = V( 8 ) + T8 = TAU*V8 + V9 = V( 9 ) + T9 = TAU*V9 + V10 = V( 10 ) + T10 = TAU*V10 + DO 400 J = 1, M + SUM = V1*C( J, 1 ) + V2*C( J, 2 ) + V3*C( J, 3 ) + + $ V4*C( J, 4 ) + V5*C( J, 5 ) + V6*C( J, 6 ) + + $ V7*C( J, 7 ) + V8*C( J, 8 ) + V9*C( J, 9 ) + + $ V10*C( J, 10 ) + C( J, 1 ) = C( J, 1 ) - SUM*T1 + C( J, 2 ) = C( J, 2 ) - SUM*T2 + C( J, 3 ) = C( J, 3 ) - SUM*T3 + C( J, 4 ) = C( J, 4 ) - SUM*T4 + C( J, 5 ) = C( J, 5 ) - SUM*T5 + C( J, 6 ) = C( J, 6 ) - SUM*T6 + C( J, 7 ) = C( J, 7 ) - SUM*T7 + C( J, 8 ) = C( J, 8 ) - SUM*T8 + C( J, 9 ) = C( J, 9 ) - SUM*T9 + C( J, 10 ) = C( J, 10 ) - SUM*T10 + 400 CONTINUE + GO TO 410 + END IF + 410 CONTINUE + RETURN +* +* End of DLARFX +* + END diff --git a/dep/lapack/dlarnd.f b/dep/lapack/dlarnd.f new file mode 100644 index 00000000..770b525c --- /dev/null +++ b/dep/lapack/dlarnd.f @@ -0,0 +1,88 @@ + DOUBLE PRECISION FUNCTION DLARND( IDIST, ISEED ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER IDIST +* .. +* .. Array Arguments .. + INTEGER ISEED( 4 ) +* .. +* +* Purpose +* ======= +* +* DLARND returns a random real number from a uniform or normal +* distribution. +* +* Arguments +* ========= +* +* IDIST (input) INTEGER +* Specifies the distribution of the random numbers: +* = 1: uniform (0,1) +* = 2: uniform (-1,1) +* = 3: normal (0,1) +* +* ISEED (input/output) INTEGER array, dimension (4) +* On entry, the seed of the random number generator; the array +* elements must be between 0 and 4095, and ISEED(4) must be +* odd. +* On exit, the seed is updated. +* +* Further Details +* =============== +* +* This routine calls the auxiliary routine DLARAN to generate a random +* real number from a uniform (0,1) distribution. The Box-Muller method +* is used to transform numbers from a uniform to a normal distribution. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, TWO + PARAMETER ( ONE = 1.0D+0, TWO = 2.0D+0 ) + DOUBLE PRECISION TWOPI + PARAMETER ( TWOPI = 6.2831853071795864769252867663D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION T1, T2 +* .. +* .. External Functions .. + DOUBLE PRECISION DLARAN + EXTERNAL DLARAN +* .. +* .. Intrinsic Functions .. + INTRINSIC COS, LOG, SQRT +* .. +* .. Executable Statements .. +* +* Generate a real random number from a uniform (0,1) distribution +* + T1 = DLARAN( ISEED ) +* + IF( IDIST.EQ.1 ) THEN +* +* uniform (0,1) +* + DLARND = T1 + ELSE IF( IDIST.EQ.2 ) THEN +* +* uniform (-1,1) +* + DLARND = TWO*T1 - ONE + ELSE IF( IDIST.EQ.3 ) THEN +* +* normal (0,1) +* + T2 = DLARAN( ISEED ) + DLARND = SQRT( -TWO*LOG( T1 ) )*COS( TWOPI*T2 ) + END IF + RETURN +* +* End of DLARND +* + END diff --git a/dep/lapack/dlarnv.f b/dep/lapack/dlarnv.f new file mode 100644 index 00000000..bc3273c0 --- /dev/null +++ b/dep/lapack/dlarnv.f @@ -0,0 +1,115 @@ + SUBROUTINE DLARNV( IDIST, ISEED, N, X ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER IDIST, N +* .. +* .. Array Arguments .. + INTEGER ISEED( 4 ) + DOUBLE PRECISION X( * ) +* .. +* +* Purpose +* ======= +* +* DLARNV returns a vector of n random real numbers from a uniform or +* normal distribution. +* +* Arguments +* ========= +* +* IDIST (input) INTEGER +* Specifies the distribution of the random numbers: +* = 1: uniform (0,1) +* = 2: uniform (-1,1) +* = 3: normal (0,1) +* +* ISEED (input/output) INTEGER array, dimension (4) +* On entry, the seed of the random number generator; the array +* elements must be between 0 and 4095, and ISEED(4) must be +* odd. +* On exit, the seed is updated. +* +* N (input) INTEGER +* The number of random numbers to be generated. +* +* X (output) DOUBLE PRECISION array, dimension (N) +* The generated random numbers. +* +* Further Details +* =============== +* +* This routine calls the auxiliary routine DLARUV to generate random +* real numbers from a uniform (0,1) distribution, in batches of up to +* 128 using vectorisable code. The Box-Muller method is used to +* transform numbers from a uniform to a normal distribution. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, TWO + PARAMETER ( ONE = 1.0D+0, TWO = 2.0D+0 ) + INTEGER LV + PARAMETER ( LV = 128 ) + DOUBLE PRECISION TWOPI + PARAMETER ( TWOPI = 6.2831853071795864769252867663D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, IL, IL2, IV +* .. +* .. Local Arrays .. + DOUBLE PRECISION U( LV ) +* .. +* .. Intrinsic Functions .. + INTRINSIC COS, LOG, MIN, SQRT +* .. +* .. External Subroutines .. + EXTERNAL DLARUV +* .. +* .. Executable Statements .. +* + DO 40 IV = 1, N, LV / 2 + IL = MIN( LV / 2, N-IV+1 ) + IF( IDIST.EQ.3 ) THEN + IL2 = 2*IL + ELSE + IL2 = IL + END IF +* +* Call DLARUV to generate IL2 numbers from a uniform (0,1) +* distribution (IL2 <= LV) +* + CALL DLARUV( ISEED, IL2, U ) +* + IF( IDIST.EQ.1 ) THEN +* +* Copy generated numbers +* + DO 10 I = 1, IL + X( IV+I-1 ) = U( I ) + 10 CONTINUE + ELSE IF( IDIST.EQ.2 ) THEN +* +* Convert generated numbers to uniform (-1,1) distribution +* + DO 20 I = 1, IL + X( IV+I-1 ) = TWO*U( I ) - ONE + 20 CONTINUE + ELSE IF( IDIST.EQ.3 ) THEN +* +* Convert generated numbers to normal (0,1) distribution +* + DO 30 I = 1, IL + X( IV+I-1 ) = SQRT( -TWO*LOG( U( 2*I-1 ) ) )* + $ COS( TWOPI*U( 2*I ) ) + 30 CONTINUE + END IF + 40 CONTINUE + RETURN +* +* End of DLARNV +* + END diff --git a/dep/lapack/dlartg.f b/dep/lapack/dlartg.f new file mode 100644 index 00000000..b708beda --- /dev/null +++ b/dep/lapack/dlartg.f @@ -0,0 +1,146 @@ + SUBROUTINE DLARTG( F, G, CS, SN, R ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION CS, F, G, R, SN +* .. +* +* Purpose +* ======= +* +* DLARTG generate a plane rotation so that +* +* [ CS SN ] . [ F ] = [ R ] where CS**2 + SN**2 = 1. +* [ -SN CS ] [ G ] [ 0 ] +* +* This is a slower, more accurate version of the BLAS1 routine DROTG, +* with the following other differences: +* F and G are unchanged on return. +* If G=0, then CS=1 and SN=0. +* If F=0 and (G .ne. 0), then CS=0 and SN=1 without doing any +* floating point operations (saves work in DBDSQR when +* there are zeros on the diagonal). +* +* If F exceeds G in magnitude, CS will be positive. +* +* Arguments +* ========= +* +* F (input) DOUBLE PRECISION +* The first component of vector to be rotated. +* +* G (input) DOUBLE PRECISION +* The second component of vector to be rotated. +* +* CS (output) DOUBLE PRECISION +* The cosine of the rotation. +* +* SN (output) DOUBLE PRECISION +* The sine of the rotation. +* +* R (output) DOUBLE PRECISION +* The nonzero component of the rotated vector. +* +* This version has a few statements commented out for thread safety +* (machine parameters are computed on each entry). 10 feb 03, SJH. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) +* .. +* .. Local Scalars .. +* LOGICAL FIRST + INTEGER COUNT, I + DOUBLE PRECISION EPS, F1, G1, SAFMIN, SAFMN2, SAFMX2, SCALE +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, INT, LOG, MAX, SQRT +* .. +* .. Save statement .. +* SAVE FIRST, SAFMX2, SAFMIN, SAFMN2 +* .. +* .. Data statements .. +* DATA FIRST / .TRUE. / +* .. +* .. Executable Statements .. +* +* IF( FIRST ) THEN + SAFMIN = DLAMCH( 'S' ) + EPS = DLAMCH( 'E' ) + SAFMN2 = DLAMCH( 'B' )**INT( LOG( SAFMIN / EPS ) / + $ LOG( DLAMCH( 'B' ) ) / TWO ) + SAFMX2 = ONE / SAFMN2 +* FIRST = .FALSE. +* END IF + IF( G.EQ.ZERO ) THEN + CS = ONE + SN = ZERO + R = F + ELSE IF( F.EQ.ZERO ) THEN + CS = ZERO + SN = ONE + R = G + ELSE + F1 = F + G1 = G + SCALE = MAX( ABS( F1 ), ABS( G1 ) ) + IF( SCALE.GE.SAFMX2 ) THEN + COUNT = 0 + 10 CONTINUE + COUNT = COUNT + 1 + F1 = F1*SAFMN2 + G1 = G1*SAFMN2 + SCALE = MAX( ABS( F1 ), ABS( G1 ) ) + IF( SCALE.GE.SAFMX2 ) + $ GO TO 10 + R = SQRT( F1**2+G1**2 ) + CS = F1 / R + SN = G1 / R + DO 20 I = 1, COUNT + R = R*SAFMX2 + 20 CONTINUE + ELSE IF( SCALE.LE.SAFMN2 ) THEN + COUNT = 0 + 30 CONTINUE + COUNT = COUNT + 1 + F1 = F1*SAFMX2 + G1 = G1*SAFMX2 + SCALE = MAX( ABS( F1 ), ABS( G1 ) ) + IF( SCALE.LE.SAFMN2 ) + $ GO TO 30 + R = SQRT( F1**2+G1**2 ) + CS = F1 / R + SN = G1 / R + DO 40 I = 1, COUNT + R = R*SAFMN2 + 40 CONTINUE + ELSE + R = SQRT( F1**2+G1**2 ) + CS = F1 / R + SN = G1 / R + END IF + IF( ABS( F ).GT.ABS( G ) .AND. CS.LT.ZERO ) THEN + CS = -CS + SN = -SN + R = -R + END IF + END IF + RETURN +* +* End of DLARTG +* + END diff --git a/dep/lapack/dlaruv.f b/dep/lapack/dlaruv.f new file mode 100644 index 00000000..687c2c45 --- /dev/null +++ b/dep/lapack/dlaruv.f @@ -0,0 +1,386 @@ + SUBROUTINE DLARUV( ISEED, N, X ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER N +* .. +* .. Array Arguments .. + INTEGER ISEED( 4 ) + DOUBLE PRECISION X( N ) +* .. +* +* Purpose +* ======= +* +* DLARUV returns a vector of n random real numbers from a uniform (0,1) +* distribution (n <= 128). +* +* This is an auxiliary routine called by DLARNV and ZLARNV. +* +* Arguments +* ========= +* +* ISEED (input/output) INTEGER array, dimension (4) +* On entry, the seed of the random number generator; the array +* elements must be between 0 and 4095, and ISEED(4) must be +* odd. +* On exit, the seed is updated. +* +* N (input) INTEGER +* The number of random numbers to be generated. N <= 128. +* +* X (output) DOUBLE PRECISION array, dimension (N) +* The generated random numbers. +* +* Further Details +* =============== +* +* This routine uses a multiplicative congruential method with modulus +* 2**48 and multiplier 33952834046453 (see G.S.Fishman, +* 'Multiplicative congruential random number generators with modulus +* 2**b: an exhaustive analysis for b = 32 and a partial analysis for +* b = 48', Math. Comp. 189, pp 331-344, 1990). +* +* 48-bit integers are stored in 4 integer array elements with 12 bits +* per element. Hence the routine is portable across machines with +* integers of 32 bits or more. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + INTEGER LV, IPW2 + DOUBLE PRECISION R + PARAMETER ( LV = 128, IPW2 = 4096, R = ONE / IPW2 ) +* .. +* .. Local Scalars .. + INTEGER I, I1, I2, I3, I4, IT1, IT2, IT3, IT4, J +* .. +* .. Local Arrays .. + INTEGER MM( LV, 4 ) +* .. +* .. Intrinsic Functions .. + INTRINSIC DBLE, MIN, MOD +* .. +* .. Data statements .. + DATA ( MM( 1, J ), J = 1, 4 ) / 494, 322, 2508, + $ 2549 / + DATA ( MM( 2, J ), J = 1, 4 ) / 2637, 789, 3754, + $ 1145 / + DATA ( MM( 3, J ), J = 1, 4 ) / 255, 1440, 1766, + $ 2253 / + DATA ( MM( 4, J ), J = 1, 4 ) / 2008, 752, 3572, + $ 305 / + DATA ( MM( 5, J ), J = 1, 4 ) / 1253, 2859, 2893, + $ 3301 / + DATA ( MM( 6, J ), J = 1, 4 ) / 3344, 123, 307, + $ 1065 / + DATA ( MM( 7, J ), J = 1, 4 ) / 4084, 1848, 1297, + $ 3133 / + DATA ( MM( 8, J ), J = 1, 4 ) / 1739, 643, 3966, + $ 2913 / + DATA ( MM( 9, J ), J = 1, 4 ) / 3143, 2405, 758, + $ 3285 / + DATA ( MM( 10, J ), J = 1, 4 ) / 3468, 2638, 2598, + $ 1241 / + DATA ( MM( 11, J ), J = 1, 4 ) / 688, 2344, 3406, + $ 1197 / + DATA ( MM( 12, J ), J = 1, 4 ) / 1657, 46, 2922, + $ 3729 / + DATA ( MM( 13, J ), J = 1, 4 ) / 1238, 3814, 1038, + $ 2501 / + DATA ( MM( 14, J ), J = 1, 4 ) / 3166, 913, 2934, + $ 1673 / + DATA ( MM( 15, J ), J = 1, 4 ) / 1292, 3649, 2091, + $ 541 / + DATA ( MM( 16, J ), J = 1, 4 ) / 3422, 339, 2451, + $ 2753 / + DATA ( MM( 17, J ), J = 1, 4 ) / 1270, 3808, 1580, + $ 949 / + DATA ( MM( 18, J ), J = 1, 4 ) / 2016, 822, 1958, + $ 2361 / + DATA ( MM( 19, J ), J = 1, 4 ) / 154, 2832, 2055, + $ 1165 / + DATA ( MM( 20, J ), J = 1, 4 ) / 2862, 3078, 1507, + $ 4081 / + DATA ( MM( 21, J ), J = 1, 4 ) / 697, 3633, 1078, + $ 2725 / + DATA ( MM( 22, J ), J = 1, 4 ) / 1706, 2970, 3273, + $ 3305 / + DATA ( MM( 23, J ), J = 1, 4 ) / 491, 637, 17, + $ 3069 / + DATA ( MM( 24, J ), J = 1, 4 ) / 931, 2249, 854, + $ 3617 / + DATA ( MM( 25, J ), J = 1, 4 ) / 1444, 2081, 2916, + $ 3733 / + DATA ( MM( 26, J ), J = 1, 4 ) / 444, 4019, 3971, + $ 409 / + DATA ( MM( 27, J ), J = 1, 4 ) / 3577, 1478, 2889, + $ 2157 / + DATA ( MM( 28, J ), J = 1, 4 ) / 3944, 242, 3831, + $ 1361 / + DATA ( MM( 29, J ), J = 1, 4 ) / 2184, 481, 2621, + $ 3973 / + DATA ( MM( 30, J ), J = 1, 4 ) / 1661, 2075, 1541, + $ 1865 / + DATA ( MM( 31, J ), J = 1, 4 ) / 3482, 4058, 893, + $ 2525 / + DATA ( MM( 32, J ), J = 1, 4 ) / 657, 622, 736, + $ 1409 / + DATA ( MM( 33, J ), J = 1, 4 ) / 3023, 3376, 3992, + $ 3445 / + DATA ( MM( 34, J ), J = 1, 4 ) / 3618, 812, 787, + $ 3577 / + DATA ( MM( 35, J ), J = 1, 4 ) / 1267, 234, 2125, + $ 77 / + DATA ( MM( 36, J ), J = 1, 4 ) / 1828, 641, 2364, + $ 3761 / + DATA ( MM( 37, J ), J = 1, 4 ) / 164, 4005, 2460, + $ 2149 / + DATA ( MM( 38, J ), J = 1, 4 ) / 3798, 1122, 257, + $ 1449 / + DATA ( MM( 39, J ), J = 1, 4 ) / 3087, 3135, 1574, + $ 3005 / + DATA ( MM( 40, J ), J = 1, 4 ) / 2400, 2640, 3912, + $ 225 / + DATA ( MM( 41, J ), J = 1, 4 ) / 2870, 2302, 1216, + $ 85 / + DATA ( MM( 42, J ), J = 1, 4 ) / 3876, 40, 3248, + $ 3673 / + DATA ( MM( 43, J ), J = 1, 4 ) / 1905, 1832, 3401, + $ 3117 / + DATA ( MM( 44, J ), J = 1, 4 ) / 1593, 2247, 2124, + $ 3089 / + DATA ( MM( 45, J ), J = 1, 4 ) / 1797, 2034, 2762, + $ 1349 / + DATA ( MM( 46, J ), J = 1, 4 ) / 1234, 2637, 149, + $ 2057 / + DATA ( MM( 47, J ), J = 1, 4 ) / 3460, 1287, 2245, + $ 413 / + DATA ( MM( 48, J ), J = 1, 4 ) / 328, 1691, 166, + $ 65 / + DATA ( MM( 49, J ), J = 1, 4 ) / 2861, 496, 466, + $ 1845 / + DATA ( MM( 50, J ), J = 1, 4 ) / 1950, 1597, 4018, + $ 697 / + DATA ( MM( 51, J ), J = 1, 4 ) / 617, 2394, 1399, + $ 3085 / + DATA ( MM( 52, J ), J = 1, 4 ) / 2070, 2584, 190, + $ 3441 / + DATA ( MM( 53, J ), J = 1, 4 ) / 3331, 1843, 2879, + $ 1573 / + DATA ( MM( 54, J ), J = 1, 4 ) / 769, 336, 153, + $ 3689 / + DATA ( MM( 55, J ), J = 1, 4 ) / 1558, 1472, 2320, + $ 2941 / + DATA ( MM( 56, J ), J = 1, 4 ) / 2412, 2407, 18, + $ 929 / + DATA ( MM( 57, J ), J = 1, 4 ) / 2800, 433, 712, + $ 533 / + DATA ( MM( 58, J ), J = 1, 4 ) / 189, 2096, 2159, + $ 2841 / + DATA ( MM( 59, J ), J = 1, 4 ) / 287, 1761, 2318, + $ 4077 / + DATA ( MM( 60, J ), J = 1, 4 ) / 2045, 2810, 2091, + $ 721 / + DATA ( MM( 61, J ), J = 1, 4 ) / 1227, 566, 3443, + $ 2821 / + DATA ( MM( 62, J ), J = 1, 4 ) / 2838, 442, 1510, + $ 2249 / + DATA ( MM( 63, J ), J = 1, 4 ) / 209, 41, 449, + $ 2397 / + DATA ( MM( 64, J ), J = 1, 4 ) / 2770, 1238, 1956, + $ 2817 / + DATA ( MM( 65, J ), J = 1, 4 ) / 3654, 1086, 2201, + $ 245 / + DATA ( MM( 66, J ), J = 1, 4 ) / 3993, 603, 3137, + $ 1913 / + DATA ( MM( 67, J ), J = 1, 4 ) / 192, 840, 3399, + $ 1997 / + DATA ( MM( 68, J ), J = 1, 4 ) / 2253, 3168, 1321, + $ 3121 / + DATA ( MM( 69, J ), J = 1, 4 ) / 3491, 1499, 2271, + $ 997 / + DATA ( MM( 70, J ), J = 1, 4 ) / 2889, 1084, 3667, + $ 1833 / + DATA ( MM( 71, J ), J = 1, 4 ) / 2857, 3438, 2703, + $ 2877 / + DATA ( MM( 72, J ), J = 1, 4 ) / 2094, 2408, 629, + $ 1633 / + DATA ( MM( 73, J ), J = 1, 4 ) / 1818, 1589, 2365, + $ 981 / + DATA ( MM( 74, J ), J = 1, 4 ) / 688, 2391, 2431, + $ 2009 / + DATA ( MM( 75, J ), J = 1, 4 ) / 1407, 288, 1113, + $ 941 / + DATA ( MM( 76, J ), J = 1, 4 ) / 634, 26, 3922, + $ 2449 / + DATA ( MM( 77, J ), J = 1, 4 ) / 3231, 512, 2554, + $ 197 / + DATA ( MM( 78, J ), J = 1, 4 ) / 815, 1456, 184, + $ 2441 / + DATA ( MM( 79, J ), J = 1, 4 ) / 3524, 171, 2099, + $ 285 / + DATA ( MM( 80, J ), J = 1, 4 ) / 1914, 1677, 3228, + $ 1473 / + DATA ( MM( 81, J ), J = 1, 4 ) / 516, 2657, 4012, + $ 2741 / + DATA ( MM( 82, J ), J = 1, 4 ) / 164, 2270, 1921, + $ 3129 / + DATA ( MM( 83, J ), J = 1, 4 ) / 303, 2587, 3452, + $ 909 / + DATA ( MM( 84, J ), J = 1, 4 ) / 2144, 2961, 3901, + $ 2801 / + DATA ( MM( 85, J ), J = 1, 4 ) / 3480, 1970, 572, + $ 421 / + DATA ( MM( 86, J ), J = 1, 4 ) / 119, 1817, 3309, + $ 4073 / + DATA ( MM( 87, J ), J = 1, 4 ) / 3357, 676, 3171, + $ 2813 / + DATA ( MM( 88, J ), J = 1, 4 ) / 837, 1410, 817, + $ 2337 / + DATA ( MM( 89, J ), J = 1, 4 ) / 2826, 3723, 3039, + $ 1429 / + DATA ( MM( 90, J ), J = 1, 4 ) / 2332, 2803, 1696, + $ 1177 / + DATA ( MM( 91, J ), J = 1, 4 ) / 2089, 3185, 1256, + $ 1901 / + DATA ( MM( 92, J ), J = 1, 4 ) / 3780, 184, 3715, + $ 81 / + DATA ( MM( 93, J ), J = 1, 4 ) / 1700, 663, 2077, + $ 1669 / + DATA ( MM( 94, J ), J = 1, 4 ) / 3712, 499, 3019, + $ 2633 / + DATA ( MM( 95, J ), J = 1, 4 ) / 150, 3784, 1497, + $ 2269 / + DATA ( MM( 96, J ), J = 1, 4 ) / 2000, 1631, 1101, + $ 129 / + DATA ( MM( 97, J ), J = 1, 4 ) / 3375, 1925, 717, + $ 1141 / + DATA ( MM( 98, J ), J = 1, 4 ) / 1621, 3912, 51, + $ 249 / + DATA ( MM( 99, J ), J = 1, 4 ) / 3090, 1398, 981, + $ 3917 / + DATA ( MM( 100, J ), J = 1, 4 ) / 3765, 1349, 1978, + $ 2481 / + DATA ( MM( 101, J ), J = 1, 4 ) / 1149, 1441, 1813, + $ 3941 / + DATA ( MM( 102, J ), J = 1, 4 ) / 3146, 2224, 3881, + $ 2217 / + DATA ( MM( 103, J ), J = 1, 4 ) / 33, 2411, 76, + $ 2749 / + DATA ( MM( 104, J ), J = 1, 4 ) / 3082, 1907, 3846, + $ 3041 / + DATA ( MM( 105, J ), J = 1, 4 ) / 2741, 3192, 3694, + $ 1877 / + DATA ( MM( 106, J ), J = 1, 4 ) / 359, 2786, 1682, + $ 345 / + DATA ( MM( 107, J ), J = 1, 4 ) / 3316, 382, 124, + $ 2861 / + DATA ( MM( 108, J ), J = 1, 4 ) / 1749, 37, 1660, + $ 1809 / + DATA ( MM( 109, J ), J = 1, 4 ) / 185, 759, 3997, + $ 3141 / + DATA ( MM( 110, J ), J = 1, 4 ) / 2784, 2948, 479, + $ 2825 / + DATA ( MM( 111, J ), J = 1, 4 ) / 2202, 1862, 1141, + $ 157 / + DATA ( MM( 112, J ), J = 1, 4 ) / 2199, 3802, 886, + $ 2881 / + DATA ( MM( 113, J ), J = 1, 4 ) / 1364, 2423, 3514, + $ 3637 / + DATA ( MM( 114, J ), J = 1, 4 ) / 1244, 2051, 1301, + $ 1465 / + DATA ( MM( 115, J ), J = 1, 4 ) / 2020, 2295, 3604, + $ 2829 / + DATA ( MM( 116, J ), J = 1, 4 ) / 3160, 1332, 1888, + $ 2161 / + DATA ( MM( 117, J ), J = 1, 4 ) / 2785, 1832, 1836, + $ 3365 / + DATA ( MM( 118, J ), J = 1, 4 ) / 2772, 2405, 1990, + $ 361 / + DATA ( MM( 119, J ), J = 1, 4 ) / 1217, 3638, 2058, + $ 2685 / + DATA ( MM( 120, J ), J = 1, 4 ) / 1822, 3661, 692, + $ 3745 / + DATA ( MM( 121, J ), J = 1, 4 ) / 1245, 327, 1194, + $ 2325 / + DATA ( MM( 122, J ), J = 1, 4 ) / 2252, 3660, 20, + $ 3609 / + DATA ( MM( 123, J ), J = 1, 4 ) / 3904, 716, 3285, + $ 3821 / + DATA ( MM( 124, J ), J = 1, 4 ) / 2774, 1842, 2046, + $ 3537 / + DATA ( MM( 125, J ), J = 1, 4 ) / 997, 3987, 2107, + $ 517 / + DATA ( MM( 126, J ), J = 1, 4 ) / 2573, 1368, 3508, + $ 3017 / + DATA ( MM( 127, J ), J = 1, 4 ) / 1148, 1848, 3525, + $ 2141 / + DATA ( MM( 128, J ), J = 1, 4 ) / 545, 2366, 3801, + $ 1537 / +* .. +* .. Executable Statements .. +* + I1 = ISEED( 1 ) + I2 = ISEED( 2 ) + I3 = ISEED( 3 ) + I4 = ISEED( 4 ) +* + DO 10 I = 1, MIN( N, LV ) +* + 20 CONTINUE +* +* Multiply the seed by i-th power of the multiplier modulo 2**48 +* + IT4 = I4*MM( I, 4 ) + IT3 = IT4 / IPW2 + IT4 = IT4 - IPW2*IT3 + IT3 = IT3 + I3*MM( I, 4 ) + I4*MM( I, 3 ) + IT2 = IT3 / IPW2 + IT3 = IT3 - IPW2*IT2 + IT2 = IT2 + I2*MM( I, 4 ) + I3*MM( I, 3 ) + I4*MM( I, 2 ) + IT1 = IT2 / IPW2 + IT2 = IT2 - IPW2*IT1 + IT1 = IT1 + I1*MM( I, 4 ) + I2*MM( I, 3 ) + I3*MM( I, 2 ) + + $ I4*MM( I, 1 ) + IT1 = MOD( IT1, IPW2 ) +* +* Convert 48-bit integer to a real number in the interval (0,1) +* + X( I ) = R*( DBLE( IT1 )+R*( DBLE( IT2 )+R*( DBLE( IT3 )+R* + $ DBLE( IT4 ) ) ) ) +* + IF (X( I ).EQ.1.0D0) THEN +* If a real number has n bits of precision, and the first +* n bits of the 48-bit integer above happen to be all 1 (which +* will occur about once every 2**n calls), then X( I ) will +* be rounded to exactly 1.0. +* Since X( I ) is not supposed to return exactly 0.0 or 1.0, +* the statistically correct thing to do in this situation is +* simply to iterate again. +* N.B. the case X( I ) = 0.0 should not be possible. + I1 = I1 + 2 + I2 = I2 + 2 + I3 = I3 + 2 + I4 = I4 + 2 + GOTO 20 + END IF +* + 10 CONTINUE +* +* Return final value of seed +* + ISEED( 1 ) = IT1 + ISEED( 2 ) = IT2 + ISEED( 3 ) = IT3 + ISEED( 4 ) = IT4 + RETURN +* +* End of DLARUV +* + END diff --git a/dep/lapack/dlas2.f b/dep/lapack/dlas2.f new file mode 100644 index 00000000..27e09b44 --- /dev/null +++ b/dep/lapack/dlas2.f @@ -0,0 +1,122 @@ + SUBROUTINE DLAS2( F, G, H, SSMIN, SSMAX ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION F, G, H, SSMAX, SSMIN +* .. +* +* Purpose +* ======= +* +* DLAS2 computes the singular values of the 2-by-2 matrix +* [ F G ] +* [ 0 H ]. +* On return, SSMIN is the smaller singular value and SSMAX is the +* larger singular value. +* +* Arguments +* ========= +* +* F (input) DOUBLE PRECISION +* The (1,1) element of the 2-by-2 matrix. +* +* G (input) DOUBLE PRECISION +* The (1,2) element of the 2-by-2 matrix. +* +* H (input) DOUBLE PRECISION +* The (2,2) element of the 2-by-2 matrix. +* +* SSMIN (output) DOUBLE PRECISION +* The smaller singular value. +* +* SSMAX (output) DOUBLE PRECISION +* The larger singular value. +* +* Further Details +* =============== +* +* Barring over/underflow, all output quantities are correct to within +* a few units in the last place (ulps), even in the absence of a guard +* digit in addition/subtraction. +* +* In IEEE arithmetic, the code works correctly if one matrix element is +* infinite. +* +* Overflow will not occur unless the largest singular value itself +* overflows, or is within a few ulps of overflow. (On machines with +* partial overflow, like the Cray, overflow may occur if the largest +* singular value is within a factor of 2 of overflow.) +* +* Underflow is harmless if underflow is gradual. Otherwise, results +* may correspond to a matrix modified by perturbations of size near +* the underflow threshold. +* +* ==================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AS, AT, AU, C, FA, FHMN, FHMX, GA, HA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + FA = ABS( F ) + GA = ABS( G ) + HA = ABS( H ) + FHMN = MIN( FA, HA ) + FHMX = MAX( FA, HA ) + IF( FHMN.EQ.ZERO ) THEN + SSMIN = ZERO + IF( FHMX.EQ.ZERO ) THEN + SSMAX = GA + ELSE + SSMAX = MAX( FHMX, GA )*SQRT( ONE+ + $ ( MIN( FHMX, GA ) / MAX( FHMX, GA ) )**2 ) + END IF + ELSE + IF( GA.LT.FHMX ) THEN + AS = ONE + FHMN / FHMX + AT = ( FHMX-FHMN ) / FHMX + AU = ( GA / FHMX )**2 + C = TWO / ( SQRT( AS*AS+AU )+SQRT( AT*AT+AU ) ) + SSMIN = FHMN*C + SSMAX = FHMX / C + ELSE + AU = FHMX / GA + IF( AU.EQ.ZERO ) THEN +* +* Avoid possible harmful underflow if exponent range +* asymmetric (true SSMIN may not underflow even if +* AU underflows) +* + SSMIN = ( FHMN*FHMX ) / GA + SSMAX = GA + ELSE + AS = ONE + FHMN / FHMX + AT = ( FHMX-FHMN ) / FHMX + C = ONE / ( SQRT( ONE+( AS*AU )**2 )+ + $ SQRT( ONE+( AT*AU )**2 ) ) + SSMIN = ( FHMN*C )*AU + SSMIN = SSMIN + SSMIN + SSMAX = GA / ( C+C ) + END IF + END IF + END IF + RETURN +* +* End of DLAS2 +* + END diff --git a/dep/lapack/dlascl.f b/dep/lapack/dlascl.f new file mode 100644 index 00000000..ffbb5715 --- /dev/null +++ b/dep/lapack/dlascl.f @@ -0,0 +1,284 @@ + SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.3.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2010 +* +* .. Scalar Arguments .. + CHARACTER TYPE + INTEGER INFO, KL, KU, LDA, M, N + DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DLASCL multiplies the M by N real matrix A by the real scalar +* CTO/CFROM. This is done without over/underflow as long as the final +* result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that +* A may be full, upper triangular, lower triangular, upper Hessenberg, +* or banded. +* +* Arguments +* ========= +* +* TYPE (input) CHARACTER*1 +* TYPE indices the storage type of the input matrix. +* = 'G': A is a full matrix. +* = 'L': A is a lower triangular matrix. +* = 'U': A is an upper triangular matrix. +* = 'H': A is an upper Hessenberg matrix. +* = 'B': A is a symmetric band matrix with lower bandwidth KL +* and upper bandwidth KU and with the only the lower +* half stored. +* = 'Q': A is a symmetric band matrix with lower bandwidth KL +* and upper bandwidth KU and with the only the upper +* half stored. +* = 'Z': A is a band matrix with lower bandwidth KL and upper +* bandwidth KU. See DGBTRF for storage details. +* +* KL (input) INTEGER +* The lower bandwidth of A. Referenced only if TYPE = 'B', +* 'Q' or 'Z'. +* +* KU (input) INTEGER +* The upper bandwidth of A. Referenced only if TYPE = 'B', +* 'Q' or 'Z'. +* +* CFROM (input) DOUBLE PRECISION +* CTO (input) DOUBLE PRECISION +* The matrix A is multiplied by CTO/CFROM. A(I,J) is computed +* without over/underflow if the final result CTO*A(I,J)/CFROM +* can be represented without over/underflow. CFROM must be +* nonzero. +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* The matrix to be multiplied by CTO/CFROM. See TYPE for the +* storage type. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* INFO (output) INTEGER +* 0 - successful exit +* <0 - if INFO = -i, the i-th argument had an illegal value. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL DONE + INTEGER I, ITYPE, J, K1, K2, K3, K4 + DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, DLAMCH, DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 +* + IF( LSAME( TYPE, 'G' ) ) THEN + ITYPE = 0 + ELSE IF( LSAME( TYPE, 'L' ) ) THEN + ITYPE = 1 + ELSE IF( LSAME( TYPE, 'U' ) ) THEN + ITYPE = 2 + ELSE IF( LSAME( TYPE, 'H' ) ) THEN + ITYPE = 3 + ELSE IF( LSAME( TYPE, 'B' ) ) THEN + ITYPE = 4 + ELSE IF( LSAME( TYPE, 'Q' ) ) THEN + ITYPE = 5 + ELSE IF( LSAME( TYPE, 'Z' ) ) THEN + ITYPE = 6 + ELSE + ITYPE = -1 + END IF +* + IF( ITYPE.EQ.-1 ) THEN + INFO = -1 + ELSE IF( CFROM.EQ.ZERO .OR. DISNAN(CFROM) ) THEN + INFO = -4 + ELSE IF( DISNAN(CTO) ) THEN + INFO = -5 + ELSE IF( M.LT.0 ) THEN + INFO = -6 + ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR. + $ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THEN + INFO = -7 + ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THEN + INFO = -9 + ELSE IF( ITYPE.GE.4 ) THEN + IF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THEN + INFO = -2 + ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR. + $ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) ) + $ THEN + INFO = -3 + ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR. + $ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR. + $ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THEN + INFO = -9 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASCL', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. M.EQ.0 ) + $ RETURN +* +* Get machine parameters +* + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM +* + CFROMC = CFROM + CTOC = CTO +* + 10 CONTINUE + CFROM1 = CFROMC*SMLNUM + IF( CFROM1.EQ.CFROMC ) THEN +! CFROMC is an inf. Multiply by a correctly signed zero for +! finite CTOC, or a NaN if CTOC is infinite. + MUL = CTOC / CFROMC + DONE = .TRUE. + CTO1 = CTOC + ELSE + CTO1 = CTOC / BIGNUM + IF( CTO1.EQ.CTOC ) THEN +! CTOC is either 0 or an inf. In both cases, CTOC itself +! serves as the correct multiplication factor. + MUL = CTOC + DONE = .TRUE. + CFROMC = ONE + ELSE IF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THEN + MUL = SMLNUM + DONE = .FALSE. + CFROMC = CFROM1 + ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THEN + MUL = BIGNUM + DONE = .FALSE. + CTOC = CTO1 + ELSE + MUL = CTOC / CFROMC + DONE = .TRUE. + END IF + END IF +* + IF( ITYPE.EQ.0 ) THEN +* +* Full matrix +* + DO 30 J = 1, N + DO 20 I = 1, M + A( I, J ) = A( I, J )*MUL + 20 CONTINUE + 30 CONTINUE +* + ELSE IF( ITYPE.EQ.1 ) THEN +* +* Lower triangular matrix +* + DO 50 J = 1, N + DO 40 I = J, M + A( I, J ) = A( I, J )*MUL + 40 CONTINUE + 50 CONTINUE +* + ELSE IF( ITYPE.EQ.2 ) THEN +* +* Upper triangular matrix +* + DO 70 J = 1, N + DO 60 I = 1, MIN( J, M ) + A( I, J ) = A( I, J )*MUL + 60 CONTINUE + 70 CONTINUE +* + ELSE IF( ITYPE.EQ.3 ) THEN +* +* Upper Hessenberg matrix +* + DO 90 J = 1, N + DO 80 I = 1, MIN( J+1, M ) + A( I, J ) = A( I, J )*MUL + 80 CONTINUE + 90 CONTINUE +* + ELSE IF( ITYPE.EQ.4 ) THEN +* +* Lower half of a symmetric band matrix +* + K3 = KL + 1 + K4 = N + 1 + DO 110 J = 1, N + DO 100 I = 1, MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 100 CONTINUE + 110 CONTINUE +* + ELSE IF( ITYPE.EQ.5 ) THEN +* +* Upper half of a symmetric band matrix +* + K1 = KU + 2 + K3 = KU + 1 + DO 130 J = 1, N + DO 120 I = MAX( K1-J, 1 ), K3 + A( I, J ) = A( I, J )*MUL + 120 CONTINUE + 130 CONTINUE +* + ELSE IF( ITYPE.EQ.6 ) THEN +* +* Band matrix +* + K1 = KL + KU + 2 + K2 = KL + 1 + K3 = 2*KL + KU + 1 + K4 = KL + KU + 1 + M + DO 150 J = 1, N + DO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 140 CONTINUE + 150 CONTINUE +* + END IF +* + IF( .NOT.DONE ) + $ GO TO 10 +* + RETURN +* +* End of DLASCL +* + END diff --git a/dep/lapack/dlaset.f b/dep/lapack/dlaset.f new file mode 100644 index 00000000..9648dd00 --- /dev/null +++ b/dep/lapack/dlaset.f @@ -0,0 +1,115 @@ + SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, M, N + DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DLASET initializes an m-by-n matrix A to BETA on the diagonal and +* ALPHA on the offdiagonals. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies the part of the matrix A to be set. +* = 'U': Upper triangular part is set; the strictly lower +* triangular part of A is not changed. +* = 'L': Lower triangular part is set; the strictly upper +* triangular part of A is not changed. +* Otherwise: All of the matrix A is set. +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* ALPHA (input) DOUBLE PRECISION +* The constant to which the offdiagonal elements are to be set. +* +* BETA (input) DOUBLE PRECISION +* The constant to which the diagonal elements are to be set. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On exit, the leading m-by-n submatrix of A is set as follows: +* +* if UPLO = 'U', A(i,j) = ALPHA, 1<=i<=j-1, 1<=j<=n, +* if UPLO = 'L', A(i,j) = ALPHA, j+1<=i<=m, 1<=j<=n, +* otherwise, A(i,j) = ALPHA, 1<=i<=m, 1<=j<=n, i.ne.j, +* +* and, for all UPLO, A(i,i) = BETA, 1<=i<=min(m,n). +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( LSAME( UPLO, 'U' ) ) THEN +* +* Set the strictly upper triangular or trapezoidal part of the +* array to ALPHA. +* + DO 20 J = 2, N + DO 10 I = 1, MIN( J-1, M ) + A( I, J ) = ALPHA + 10 CONTINUE + 20 CONTINUE +* + ELSE IF( LSAME( UPLO, 'L' ) ) THEN +* +* Set the strictly lower triangular or trapezoidal part of the +* array to ALPHA. +* + DO 40 J = 1, MIN( M, N ) + DO 30 I = J + 1, M + A( I, J ) = ALPHA + 30 CONTINUE + 40 CONTINUE +* + ELSE +* +* Set the leading m-by-n submatrix to ALPHA. +* + DO 60 J = 1, N + DO 50 I = 1, M + A( I, J ) = ALPHA + 50 CONTINUE + 60 CONTINUE + END IF +* +* Set the first min(M,N) diagonal elements to BETA. +* + DO 70 I = 1, MIN( M, N ) + A( I, I ) = BETA + 70 CONTINUE +* + RETURN +* +* End of DLASET +* + END diff --git a/dep/lapack/dlasq1.f b/dep/lapack/dlasq1.f new file mode 100644 index 00000000..53fd3ddd --- /dev/null +++ b/dep/lapack/dlasq1.f @@ -0,0 +1,154 @@ + SUBROUTINE DLASQ1( N, D, E, WORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* +* -- Contributed by Osni Marques of the Lawrence Berkeley National -- +* -- Laboratory and Beresford Parlett of the Univ. of California at -- +* -- Berkeley -- +* -- November 2008 -- +* +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DLASQ1 computes the singular values of a real N-by-N bidiagonal +* matrix with diagonal D and off-diagonal E. The singular values +* are computed to high relative accuracy, in the absence of +* denormalization, underflow and overflow. The algorithm was first +* presented in +* +* "Accurate singular values and differential qd algorithms" by K. V. +* Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, +* 1994, +* +* and the present implementation is described in "An implementation of +* the dqds Algorithm (Positive Case)", LAPACK Working Note. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of rows and columns in the matrix. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, D contains the diagonal elements of the +* bidiagonal matrix whose SVD is desired. On normal exit, +* D contains the singular values in decreasing order. +* +* E (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, elements E(1:N-1) contain the off-diagonal elements +* of the bidiagonal matrix whose SVD is desired. +* On exit, E is overwritten. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (4*N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: the algorithm failed +* = 1, a split was marked by a positive value in E +* = 2, current block of Z not diagonalized after 30*N +* iterations (in inner while loop) +* = 3, termination criterion of outer while loop not met +* (program created more than N unreduced blocks) +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I, IINFO + DOUBLE PRECISION EPS, SCALE, SAFMIN, SIGMN, SIGMX +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DLAS2, DLASCL, DLASQ2, DLASRT, XERBLA +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -2 + CALL XERBLA( 'DLASQ1', -INFO ) + RETURN + ELSE IF( N.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN + D( 1 ) = ABS( D( 1 ) ) + RETURN + ELSE IF( N.EQ.2 ) THEN + CALL DLAS2( D( 1 ), E( 1 ), D( 2 ), SIGMN, SIGMX ) + D( 1 ) = SIGMX + D( 2 ) = SIGMN + RETURN + END IF +* +* Estimate the largest singular value. +* + SIGMX = ZERO + DO 10 I = 1, N - 1 + D( I ) = ABS( D( I ) ) + SIGMX = MAX( SIGMX, ABS( E( I ) ) ) + 10 CONTINUE + D( N ) = ABS( D( N ) ) +* +* Early return if SIGMX is zero (matrix is already diagonal). +* + IF( SIGMX.EQ.ZERO ) THEN + CALL DLASRT( 'D', N, D, IINFO ) + RETURN + END IF +* + DO 20 I = 1, N + SIGMX = MAX( SIGMX, D( I ) ) + 20 CONTINUE +* +* Copy D and E into WORK (in the Z format) and scale (squaring the +* input data makes scaling by a power of the radix pointless). +* + EPS = DLAMCH( 'Precision' ) + SAFMIN = DLAMCH( 'Safe minimum' ) + SCALE = SQRT( EPS / SAFMIN ) + CALL DCOPY( N, D, 1, WORK( 1 ), 2 ) + CALL DCOPY( N-1, E, 1, WORK( 2 ), 2 ) + CALL DLASCL( 'G', 0, 0, SIGMX, SCALE, 2*N-1, 1, WORK, 2*N-1, + $ IINFO ) +* +* Compute the q's and e's. +* + DO 30 I = 1, 2*N - 1 + WORK( I ) = WORK( I )**2 + 30 CONTINUE + WORK( 2*N ) = ZERO +* + CALL DLASQ2( N, WORK, INFO ) +* + IF( INFO.EQ.0 ) THEN + DO 40 I = 1, N + D( I ) = SQRT( WORK( I ) ) + 40 CONTINUE + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, D, N, IINFO ) + END IF +* + RETURN +* +* End of DLASQ1 +* + END diff --git a/dep/lapack/dlasq2.f b/dep/lapack/dlasq2.f new file mode 100644 index 00000000..1fef65b1 --- /dev/null +++ b/dep/lapack/dlasq2.f @@ -0,0 +1,485 @@ + SUBROUTINE DLASQ2( N, Z, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* +* -- Contributed by Osni Marques of the Lawrence Berkeley National -- +* -- Laboratory and Beresford Parlett of the Univ. of California at -- +* -- Berkeley -- +* -- November 2008 -- +* +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* Purpose +* ======= +* +* DLASQ2 computes all the eigenvalues of the symmetric positive +* definite tridiagonal matrix associated with the qd array Z to high +* relative accuracy are computed to high relative accuracy, in the +* absence of denormalization, underflow and overflow. +* +* To see the relation of Z to the tridiagonal matrix, let L be a +* unit lower bidiagonal matrix with subdiagonals Z(2,4,6,,..) and +* let U be an upper bidiagonal matrix with 1's above and diagonal +* Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the +* symmetric tridiagonal to which it is similar. +* +* Note : DLASQ2 defines a logical variable, IEEE, which is true +* on machines which follow ieee-754 floating-point standard in their +* handling of infinities and NaNs, and false otherwise. This variable +* is passed to DLASQ3. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of rows and columns in the matrix. N >= 0. +* +* Z (input/output) DOUBLE PRECISION array, dimension ( 4*N ) +* On entry Z holds the qd array. On exit, entries 1 to N hold +* the eigenvalues in decreasing order, Z( 2*N+1 ) holds the +* trace, and Z( 2*N+2 ) holds the sum of the eigenvalues. If +* N > 2, then Z( 2*N+3 ) holds the iteration count, Z( 2*N+4 ) +* holds NDIVS/NIN^2, and Z( 2*N+5 ) holds the percentage of +* shifts that failed. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if the i-th argument is a scalar and had an illegal +* value, then INFO = -i, if the i-th argument is an +* array and the j-entry had an illegal value, then +* INFO = -(i*100+j) +* > 0: the algorithm failed +* = 1, a split was marked by a positive value in E +* = 2, current block of Z not diagonalized after 30*N +* iterations (in inner while loop) +* = 3, termination criterion of outer while loop not met +* (program created more than N unreduced blocks) +* +* Further Details +* =============== +* Local Variables: I0:N0 defines a current unreduced segment of Z. +* The shifts are accumulated in SIGMA. Iteration count is in ITER. +* Ping-pong is controlled by PP (alternates between 0 and 1). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CBIAS + PARAMETER ( CBIAS = 1.50D0 ) + DOUBLE PRECISION ZERO, HALF, ONE, TWO, FOUR, HUNDRD + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0, + $ TWO = 2.0D0, FOUR = 4.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL IEEE + INTEGER I0, I4, IINFO, IPN4, ITER, IWHILA, IWHILB, K, + $ KMIN, N0, NBIG, NDIV, NFAIL, PP, SPLT, TTYPE + DOUBLE PRECISION D, DEE, DEEMIN, DESIG, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, E, EMAX, EMIN, EPS, G, OLDEMN, QMAX, + $ QMIN, S, SAFMIN, SIGMA, T, TAU, TEMP, TOL, + $ TOL2, TRACE, ZMAX +* .. +* .. External Subroutines .. + EXTERNAL DLASQ3, DLASRT, XERBLA +* .. +* .. External Functions .. + INTEGER ILAENV + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH, ILAENV +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* (in case DLASQ2 is not called by DLASQ1) +* + INFO = 0 + EPS = DLAMCH( 'Precision' ) + SAFMIN = DLAMCH( 'Safe minimum' ) + TOL = EPS*HUNDRD + TOL2 = TOL**2 +* + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DLASQ2', 1 ) + RETURN + ELSE IF( N.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN +* +* 1-by-1 case. +* + IF( Z( 1 ).LT.ZERO ) THEN + INFO = -201 + CALL XERBLA( 'DLASQ2', 2 ) + END IF + RETURN + ELSE IF( N.EQ.2 ) THEN +* +* 2-by-2 case. +* + IF( Z( 2 ).LT.ZERO .OR. Z( 3 ).LT.ZERO ) THEN + INFO = -2 + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + ELSE IF( Z( 3 ).GT.Z( 1 ) ) THEN + D = Z( 3 ) + Z( 3 ) = Z( 1 ) + Z( 1 ) = D + END IF + Z( 5 ) = Z( 1 ) + Z( 2 ) + Z( 3 ) + IF( Z( 2 ).GT.Z( 3 )*TOL2 ) THEN + T = HALF*( ( Z( 1 )-Z( 3 ) )+Z( 2 ) ) + S = Z( 3 )*( Z( 2 ) / T ) + IF( S.LE.T ) THEN + S = Z( 3 )*( Z( 2 ) / ( T*( ONE+SQRT( ONE+S / T ) ) ) ) + ELSE + S = Z( 3 )*( Z( 2 ) / ( T+SQRT( T )*SQRT( T+S ) ) ) + END IF + T = Z( 1 ) + ( S+Z( 2 ) ) + Z( 3 ) = Z( 3 )*( Z( 1 ) / T ) + Z( 1 ) = T + END IF + Z( 2 ) = Z( 3 ) + Z( 6 ) = Z( 2 ) + Z( 1 ) + RETURN + END IF +* +* Check for negative data and compute sums of q's and e's. +* + Z( 2*N ) = ZERO + EMIN = Z( 2 ) + QMAX = ZERO + ZMAX = ZERO + D = ZERO + E = ZERO +* + DO 10 K = 1, 2*( N-1 ), 2 + IF( Z( K ).LT.ZERO ) THEN + INFO = -( 200+K ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + ELSE IF( Z( K+1 ).LT.ZERO ) THEN + INFO = -( 200+K+1 ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + END IF + D = D + Z( K ) + E = E + Z( K+1 ) + QMAX = MAX( QMAX, Z( K ) ) + EMIN = MIN( EMIN, Z( K+1 ) ) + ZMAX = MAX( QMAX, ZMAX, Z( K+1 ) ) + 10 CONTINUE + IF( Z( 2*N-1 ).LT.ZERO ) THEN + INFO = -( 200+2*N-1 ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + END IF + D = D + Z( 2*N-1 ) + QMAX = MAX( QMAX, Z( 2*N-1 ) ) + ZMAX = MAX( QMAX, ZMAX ) +* +* Check for diagonality. +* + IF( E.EQ.ZERO ) THEN + DO 20 K = 2, N + Z( K ) = Z( 2*K-1 ) + 20 CONTINUE + CALL DLASRT( 'D', N, Z, IINFO ) + Z( 2*N-1 ) = D + RETURN + END IF +* + TRACE = D + E +* +* Check for zero data. +* + IF( TRACE.EQ.ZERO ) THEN + Z( 2*N-1 ) = ZERO + RETURN + END IF +* +* Check whether the machine is IEEE conformable. +* + IEEE = ILAENV( 10, 'DLASQ2', 'N', 1, 2, 3, 4 ).EQ.1 .AND. + $ ILAENV( 11, 'DLASQ2', 'N', 1, 2, 3, 4 ).EQ.1 +* +* Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...). +* + DO 30 K = 2*N, 2, -2 + Z( 2*K ) = ZERO + Z( 2*K-1 ) = Z( K ) + Z( 2*K-2 ) = ZERO + Z( 2*K-3 ) = Z( K-1 ) + 30 CONTINUE +* + I0 = 1 + N0 = N +* +* Reverse the qd-array, if warranted. +* + IF( CBIAS*Z( 4*I0-3 ).LT.Z( 4*N0-3 ) ) THEN + IPN4 = 4*( I0+N0 ) + DO 40 I4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( I4-3 ) + Z( I4-3 ) = Z( IPN4-I4-3 ) + Z( IPN4-I4-3 ) = TEMP + TEMP = Z( I4-1 ) + Z( I4-1 ) = Z( IPN4-I4-5 ) + Z( IPN4-I4-5 ) = TEMP + 40 CONTINUE + END IF +* +* Initial split checking via dqd and Li's test. +* + PP = 0 +* + DO 80 K = 1, 2 +* + D = Z( 4*N0+PP-3 ) + DO 50 I4 = 4*( N0-1 ) + PP, 4*I0 + PP, -4 + IF( Z( I4-1 ).LE.TOL2*D ) THEN + Z( I4-1 ) = -ZERO + D = Z( I4-3 ) + ELSE + D = Z( I4-3 )*( D / ( D+Z( I4-1 ) ) ) + END IF + 50 CONTINUE +* +* dqd maps Z to ZZ plus Li's test. +* + EMIN = Z( 4*I0+PP+1 ) + D = Z( 4*I0+PP-3 ) + DO 60 I4 = 4*I0 + PP, 4*( N0-1 ) + PP, 4 + Z( I4-2*PP-2 ) = D + Z( I4-1 ) + IF( Z( I4-1 ).LE.TOL2*D ) THEN + Z( I4-1 ) = -ZERO + Z( I4-2*PP-2 ) = D + Z( I4-2*PP ) = ZERO + D = Z( I4+1 ) + ELSE IF( SAFMIN*Z( I4+1 ).LT.Z( I4-2*PP-2 ) .AND. + $ SAFMIN*Z( I4-2*PP-2 ).LT.Z( I4+1 ) ) THEN + TEMP = Z( I4+1 ) / Z( I4-2*PP-2 ) + Z( I4-2*PP ) = Z( I4-1 )*TEMP + D = D*TEMP + ELSE + Z( I4-2*PP ) = Z( I4+1 )*( Z( I4-1 ) / Z( I4-2*PP-2 ) ) + D = Z( I4+1 )*( D / Z( I4-2*PP-2 ) ) + END IF + EMIN = MIN( EMIN, Z( I4-2*PP ) ) + 60 CONTINUE + Z( 4*N0-PP-2 ) = D +* +* Now find qmax. +* + QMAX = Z( 4*I0-PP-2 ) + DO 70 I4 = 4*I0 - PP + 2, 4*N0 - PP - 2, 4 + QMAX = MAX( QMAX, Z( I4 ) ) + 70 CONTINUE +* +* Prepare for the next iteration on K. +* + PP = 1 - PP + 80 CONTINUE +* +* Initialise variables to pass to DLASQ3. +* + TTYPE = 0 + DMIN1 = ZERO + DMIN2 = ZERO + DN = ZERO + DN1 = ZERO + DN2 = ZERO + G = ZERO + TAU = ZERO +* + ITER = 2 + NFAIL = 0 + NDIV = 2*( N0-I0 ) +* + DO 160 IWHILA = 1, N + 1 + IF( N0.LT.1 ) + $ GO TO 170 +* +* While array unfinished do +* +* E(N0) holds the value of SIGMA when submatrix in I0:N0 +* splits from the rest of the array, but is negated. +* + DESIG = ZERO + IF( N0.EQ.N ) THEN + SIGMA = ZERO + ELSE + SIGMA = -Z( 4*N0-1 ) + END IF + IF( SIGMA.LT.ZERO ) THEN + INFO = 1 + RETURN + END IF +* +* Find last unreduced submatrix's top index I0, find QMAX and +* EMIN. Find Gershgorin-type bound if Q's much greater than E's. +* + EMAX = ZERO + IF( N0.GT.I0 ) THEN + EMIN = ABS( Z( 4*N0-5 ) ) + ELSE + EMIN = ZERO + END IF + QMIN = Z( 4*N0-3 ) + QMAX = QMIN + DO 90 I4 = 4*N0, 8, -4 + IF( Z( I4-5 ).LE.ZERO ) + $ GO TO 100 + IF( QMIN.GE.FOUR*EMAX ) THEN + QMIN = MIN( QMIN, Z( I4-3 ) ) + EMAX = MAX( EMAX, Z( I4-5 ) ) + END IF + QMAX = MAX( QMAX, Z( I4-7 )+Z( I4-5 ) ) + EMIN = MIN( EMIN, Z( I4-5 ) ) + 90 CONTINUE + I4 = 4 +* + 100 CONTINUE + I0 = I4 / 4 + PP = 0 +* + IF( N0-I0.GT.1 ) THEN + DEE = Z( 4*I0-3 ) + DEEMIN = DEE + KMIN = I0 + DO 110 I4 = 4*I0+1, 4*N0-3, 4 + DEE = Z( I4 )*( DEE /( DEE+Z( I4-2 ) ) ) + IF( DEE.LE.DEEMIN ) THEN + DEEMIN = DEE + KMIN = ( I4+3 )/4 + END IF + 110 CONTINUE + IF( (KMIN-I0)*2.LT.N0-KMIN .AND. + $ DEEMIN.LE.HALF*Z(4*N0-3) ) THEN + IPN4 = 4*( I0+N0 ) + PP = 2 + DO 120 I4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( I4-3 ) + Z( I4-3 ) = Z( IPN4-I4-3 ) + Z( IPN4-I4-3 ) = TEMP + TEMP = Z( I4-2 ) + Z( I4-2 ) = Z( IPN4-I4-2 ) + Z( IPN4-I4-2 ) = TEMP + TEMP = Z( I4-1 ) + Z( I4-1 ) = Z( IPN4-I4-5 ) + Z( IPN4-I4-5 ) = TEMP + TEMP = Z( I4 ) + Z( I4 ) = Z( IPN4-I4-4 ) + Z( IPN4-I4-4 ) = TEMP + 120 CONTINUE + END IF + END IF +* +* Put -(initial shift) into DMIN. +* + DMIN = -MAX( ZERO, QMIN-TWO*SQRT( QMIN )*SQRT( EMAX ) ) +* +* Now I0:N0 is unreduced. +* PP = 0 for ping, PP = 1 for pong. +* PP = 2 indicates that flipping was applied to the Z array and +* and that the tests for deflation upon entry in DLASQ3 +* should not be performed. +* + NBIG = 30*( N0-I0+1 ) + DO 140 IWHILB = 1, NBIG + IF( I0.GT.N0 ) + $ GO TO 150 +* +* While submatrix unfinished take a good dqds step. +* + CALL DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, + $ ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, + $ DN2, G, TAU ) +* + PP = 1 - PP +* +* When EMIN is very small check for splits. +* + IF( PP.EQ.0 .AND. N0-I0.GE.3 ) THEN + IF( Z( 4*N0 ).LE.TOL2*QMAX .OR. + $ Z( 4*N0-1 ).LE.TOL2*SIGMA ) THEN + SPLT = I0 - 1 + QMAX = Z( 4*I0-3 ) + EMIN = Z( 4*I0-1 ) + OLDEMN = Z( 4*I0 ) + DO 130 I4 = 4*I0, 4*( N0-3 ), 4 + IF( Z( I4 ).LE.TOL2*Z( I4-3 ) .OR. + $ Z( I4-1 ).LE.TOL2*SIGMA ) THEN + Z( I4-1 ) = -SIGMA + SPLT = I4 / 4 + QMAX = ZERO + EMIN = Z( I4+3 ) + OLDEMN = Z( I4+4 ) + ELSE + QMAX = MAX( QMAX, Z( I4+1 ) ) + EMIN = MIN( EMIN, Z( I4-1 ) ) + OLDEMN = MIN( OLDEMN, Z( I4 ) ) + END IF + 130 CONTINUE + Z( 4*N0-1 ) = EMIN + Z( 4*N0 ) = OLDEMN + I0 = SPLT + 1 + END IF + END IF +* + 140 CONTINUE +* + INFO = 2 + RETURN +* +* end IWHILB +* + 150 CONTINUE +* + 160 CONTINUE +* + INFO = 3 + RETURN +* +* end IWHILA +* + 170 CONTINUE +* +* Move q's to the front. +* + DO 180 K = 2, N + Z( K ) = Z( 4*K-3 ) + 180 CONTINUE +* +* Sort and compute sum of eigenvalues. +* + CALL DLASRT( 'D', N, Z, IINFO ) +* + E = ZERO + DO 190 K = N, 1, -1 + E = E + Z( K ) + 190 CONTINUE +* +* Store trace, sum(eigenvalues) and information on performance. +* + Z( 2*N+1 ) = TRACE + Z( 2*N+2 ) = E + Z( 2*N+3 ) = DBLE( ITER ) + Z( 2*N+4 ) = DBLE( NDIV ) / DBLE( N**2 ) + Z( 2*N+5 ) = HUNDRD*NFAIL / DBLE( ITER ) + RETURN +* +* End of DLASQ2 +* + END diff --git a/dep/lapack/dlasq3.f b/dep/lapack/dlasq3.f new file mode 100644 index 00000000..a39620ed --- /dev/null +++ b/dep/lapack/dlasq3.f @@ -0,0 +1,315 @@ + SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, + $ ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, + $ DN2, G, TAU ) +* +* -- LAPACK routine (version 3.2.2) -- +* +* -- Contributed by Osni Marques of the Lawrence Berkeley National -- +* -- Laboratory and Beresford Parlett of the Univ. of California at -- +* -- Berkeley -- +* -- June 2010 -- +* +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* +* .. Scalar Arguments .. + LOGICAL IEEE + INTEGER I0, ITER, N0, NDIV, NFAIL, PP + DOUBLE PRECISION DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, + $ QMAX, SIGMA, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* Purpose +* ======= +* +* DLASQ3 checks for deflation, computes a shift (TAU) and calls dqds. +* In case of failure it changes shifts, and tries again until output +* is positive. +* +* Arguments +* ========= +* +* I0 (input) INTEGER +* First index. +* +* N0 (input/output) INTEGER +* Last index. +* +* Z (input) DOUBLE PRECISION array, dimension ( 4*N ) +* Z holds the qd array. +* +* PP (input/output) INTEGER +* PP=0 for ping, PP=1 for pong. +* PP=2 indicates that flipping was applied to the Z array +* and that the initial tests for deflation should not be +* performed. +* +* DMIN (output) DOUBLE PRECISION +* Minimum value of d. +* +* SIGMA (output) DOUBLE PRECISION +* Sum of shifts used in current segment. +* +* DESIG (input/output) DOUBLE PRECISION +* Lower order part of SIGMA +* +* QMAX (input) DOUBLE PRECISION +* Maximum value of q. +* +* NFAIL (output) INTEGER +* Number of times shift was too big. +* +* ITER (output) INTEGER +* Number of iterations. +* +* NDIV (output) INTEGER +* Number of divisions. +* +* IEEE (input) LOGICAL +* Flag for IEEE or non IEEE arithmetic (passed to DLASQ5). +* +* TTYPE (input/output) INTEGER +* Shift type. +* +* DMIN1 (input/output) DOUBLE PRECISION +* +* DMIN2 (input/output) DOUBLE PRECISION +* +* DN (input/output) DOUBLE PRECISION +* +* DN1 (input/output) DOUBLE PRECISION +* +* DN2 (input/output) DOUBLE PRECISION +* +* G (input/output) DOUBLE PRECISION +* +* TAU (input/output) DOUBLE PRECISION +* +* These are passed as arguments in order to save their values +* between calls to DLASQ3. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CBIAS + PARAMETER ( CBIAS = 1.50D0 ) + DOUBLE PRECISION ZERO, QURTR, HALF, ONE, TWO, HUNDRD + PARAMETER ( ZERO = 0.0D0, QURTR = 0.250D0, HALF = 0.5D0, + $ ONE = 1.0D0, TWO = 2.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + INTEGER IPN4, J4, N0IN, NN, TTYPE + DOUBLE PRECISION EPS, S, T, TEMP, TOL, TOL2 +* .. +* .. External Subroutines .. + EXTERNAL DLASQ4, DLASQ5, DLASQ6 +* .. +* .. External Function .. + DOUBLE PRECISION DLAMCH + LOGICAL DISNAN + EXTERNAL DISNAN, DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + N0IN = N0 + EPS = DLAMCH( 'Precision' ) + TOL = EPS*HUNDRD + TOL2 = TOL**2 +* +* Check for deflation. +* + 10 CONTINUE +* + IF( N0.LT.I0 ) + $ RETURN + IF( N0.EQ.I0 ) + $ GO TO 20 + NN = 4*N0 + PP + IF( N0.EQ.( I0+1 ) ) + $ GO TO 40 +* +* Check whether E(N0-1) is negligible, 1 eigenvalue. +* + IF( Z( NN-5 ).GT.TOL2*( SIGMA+Z( NN-3 ) ) .AND. + $ Z( NN-2*PP-4 ).GT.TOL2*Z( NN-7 ) ) + $ GO TO 30 +* + 20 CONTINUE +* + Z( 4*N0-3 ) = Z( 4*N0+PP-3 ) + SIGMA + N0 = N0 - 1 + GO TO 10 +* +* Check whether E(N0-2) is negligible, 2 eigenvalues. +* + 30 CONTINUE +* + IF( Z( NN-9 ).GT.TOL2*SIGMA .AND. + $ Z( NN-2*PP-8 ).GT.TOL2*Z( NN-11 ) ) + $ GO TO 50 +* + 40 CONTINUE +* + IF( Z( NN-3 ).GT.Z( NN-7 ) ) THEN + S = Z( NN-3 ) + Z( NN-3 ) = Z( NN-7 ) + Z( NN-7 ) = S + END IF + IF( Z( NN-5 ).GT.Z( NN-3 )*TOL2 ) THEN + T = HALF*( ( Z( NN-7 )-Z( NN-3 ) )+Z( NN-5 ) ) + S = Z( NN-3 )*( Z( NN-5 ) / T ) + IF( S.LE.T ) THEN + S = Z( NN-3 )*( Z( NN-5 ) / + $ ( T*( ONE+SQRT( ONE+S / T ) ) ) ) + ELSE + S = Z( NN-3 )*( Z( NN-5 ) / ( T+SQRT( T )*SQRT( T+S ) ) ) + END IF + T = Z( NN-7 ) + ( S+Z( NN-5 ) ) + Z( NN-3 ) = Z( NN-3 )*( Z( NN-7 ) / T ) + Z( NN-7 ) = T + END IF + Z( 4*N0-7 ) = Z( NN-7 ) + SIGMA + Z( 4*N0-3 ) = Z( NN-3 ) + SIGMA + N0 = N0 - 2 + GO TO 10 +* + 50 CONTINUE + IF( PP.EQ.2 ) + $ PP = 0 +* +* Reverse the qd-array, if warranted. +* + IF( DMIN.LE.ZERO .OR. N0.LT.N0IN ) THEN + IF( CBIAS*Z( 4*I0+PP-3 ).LT.Z( 4*N0+PP-3 ) ) THEN + IPN4 = 4*( I0+N0 ) + DO 60 J4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( J4-3 ) + Z( J4-3 ) = Z( IPN4-J4-3 ) + Z( IPN4-J4-3 ) = TEMP + TEMP = Z( J4-2 ) + Z( J4-2 ) = Z( IPN4-J4-2 ) + Z( IPN4-J4-2 ) = TEMP + TEMP = Z( J4-1 ) + Z( J4-1 ) = Z( IPN4-J4-5 ) + Z( IPN4-J4-5 ) = TEMP + TEMP = Z( J4 ) + Z( J4 ) = Z( IPN4-J4-4 ) + Z( IPN4-J4-4 ) = TEMP + 60 CONTINUE + IF( N0-I0.LE.4 ) THEN + Z( 4*N0+PP-1 ) = Z( 4*I0+PP-1 ) + Z( 4*N0-PP ) = Z( 4*I0-PP ) + END IF + DMIN2 = MIN( DMIN2, Z( 4*N0+PP-1 ) ) + Z( 4*N0+PP-1 ) = MIN( Z( 4*N0+PP-1 ), Z( 4*I0+PP-1 ), + $ Z( 4*I0+PP+3 ) ) + Z( 4*N0-PP ) = MIN( Z( 4*N0-PP ), Z( 4*I0-PP ), + $ Z( 4*I0-PP+4 ) ) + QMAX = MAX( QMAX, Z( 4*I0+PP-3 ), Z( 4*I0+PP+1 ) ) + DMIN = -ZERO + END IF + END IF +* +* Choose a shift. +* + CALL DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, DN1, + $ DN2, TAU, TTYPE, G ) +* +* Call dqds until DMIN > 0. +* + 70 CONTINUE +* + CALL DLASQ5( I0, N0, Z, PP, TAU, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, IEEE ) +* + NDIV = NDIV + ( N0-I0+2 ) + ITER = ITER + 1 +* +* Check status. +* + IF( DMIN.GE.ZERO .AND. DMIN1.GT.ZERO ) THEN +* +* Success. +* + GO TO 90 +* + ELSE IF( DMIN.LT.ZERO .AND. DMIN1.GT.ZERO .AND. + $ Z( 4*( N0-1 )-PP ).LT.TOL*( SIGMA+DN1 ) .AND. + $ ABS( DN ).LT.TOL*SIGMA ) THEN +* +* Convergence hidden by negative DN. +* + Z( 4*( N0-1 )-PP+2 ) = ZERO + DMIN = ZERO + GO TO 90 + ELSE IF( DMIN.LT.ZERO ) THEN +* +* TAU too big. Select new TAU and try again. +* + NFAIL = NFAIL + 1 + IF( TTYPE.LT.-22 ) THEN +* +* Failed twice. Play it safe. +* + TAU = ZERO + ELSE IF( DMIN1.GT.ZERO ) THEN +* +* Late failure. Gives excellent shift. +* + TAU = ( TAU+DMIN )*( ONE-TWO*EPS ) + TTYPE = TTYPE - 11 + ELSE +* +* Early failure. Divide by 4. +* + TAU = QURTR*TAU + TTYPE = TTYPE - 12 + END IF + GO TO 70 + ELSE IF( DISNAN( DMIN ) ) THEN +* +* NaN. +* + IF( TAU.EQ.ZERO ) THEN + GO TO 80 + ELSE + TAU = ZERO + GO TO 70 + END IF + ELSE +* +* Possible underflow. Play it safe. +* + GO TO 80 + END IF +* +* Risk of underflow. +* + 80 CONTINUE + CALL DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, DN1, DN2 ) + NDIV = NDIV + ( N0-I0+2 ) + ITER = ITER + 1 + TAU = ZERO +* + 90 CONTINUE + IF( TAU.LT.SIGMA ) THEN + DESIG = DESIG + TAU + T = SIGMA + DESIG + DESIG = DESIG - ( T-SIGMA ) + ELSE + T = SIGMA + TAU + DESIG = SIGMA - ( T-TAU ) + DESIG + END IF + SIGMA = T +* + RETURN +* +* End of DLASQ3 +* + END diff --git a/dep/lapack/dlasq4.f b/dep/lapack/dlasq4.f new file mode 100644 index 00000000..de4a1fe3 --- /dev/null +++ b/dep/lapack/dlasq4.f @@ -0,0 +1,336 @@ + SUBROUTINE DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, TAU, TTYPE, G ) +* +* -- LAPACK routine (version 3.3.1) -- +* +* -- Contributed by Osni Marques of the Lawrence Berkeley National -- +* -- Laboratory and Beresford Parlett of the Univ. of California at -- +* -- Berkeley -- +* -- November 2008 -- +* +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* +* .. Scalar Arguments .. + INTEGER I0, N0, N0IN, PP, TTYPE + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* Purpose +* ======= +* +* DLASQ4 computes an approximation TAU to the smallest eigenvalue +* using values of d from the previous transform. +* +* Arguments +* ========= +* +* I0 (input) INTEGER +* First index. +* +* N0 (input) INTEGER +* Last index. +* +* Z (input) DOUBLE PRECISION array, dimension ( 4*N ) +* Z holds the qd array. +* +* PP (input) INTEGER +* PP=0 for ping, PP=1 for pong. +* +* NOIN (input) INTEGER +* The value of N0 at start of EIGTEST. +* +* DMIN (input) DOUBLE PRECISION +* Minimum value of d. +* +* DMIN1 (input) DOUBLE PRECISION +* Minimum value of d, excluding D( N0 ). +* +* DMIN2 (input) DOUBLE PRECISION +* Minimum value of d, excluding D( N0 ) and D( N0-1 ). +* +* DN (input) DOUBLE PRECISION +* d(N) +* +* DN1 (input) DOUBLE PRECISION +* d(N-1) +* +* DN2 (input) DOUBLE PRECISION +* d(N-2) +* +* TAU (output) DOUBLE PRECISION +* This is the shift. +* +* TTYPE (output) INTEGER +* Shift type. +* +* G (input/output) REAL +* G is passed as an argument in order to save its value between +* calls to DLASQ4. +* +* Further Details +* =============== +* CNST1 = 9/16 +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CNST1, CNST2, CNST3 + PARAMETER ( CNST1 = 0.5630D0, CNST2 = 1.010D0, + $ CNST3 = 1.050D0 ) + DOUBLE PRECISION QURTR, THIRD, HALF, ZERO, ONE, TWO, HUNDRD + PARAMETER ( QURTR = 0.250D0, THIRD = 0.3330D0, + $ HALF = 0.50D0, ZERO = 0.0D0, ONE = 1.0D0, + $ TWO = 2.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I4, NN, NP + DOUBLE PRECISION A2, B1, B2, GAM, GAP1, GAP2, S +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* A negative DMIN forces the shift to take that absolute value +* TTYPE records the type of shift. +* + IF( DMIN.LE.ZERO ) THEN + TAU = -DMIN + TTYPE = -1 + RETURN + END IF +* + NN = 4*N0 + PP + IF( N0IN.EQ.N0 ) THEN +* +* No eigenvalues deflated. +* + IF( DMIN.EQ.DN .OR. DMIN.EQ.DN1 ) THEN +* + B1 = SQRT( Z( NN-3 ) )*SQRT( Z( NN-5 ) ) + B2 = SQRT( Z( NN-7 ) )*SQRT( Z( NN-9 ) ) + A2 = Z( NN-7 ) + Z( NN-5 ) +* +* Cases 2 and 3. +* + IF( DMIN.EQ.DN .AND. DMIN1.EQ.DN1 ) THEN + GAP2 = DMIN2 - A2 - DMIN2*QURTR + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2 ) THEN + GAP1 = A2 - DN - ( B2 / GAP2 )*B2 + ELSE + GAP1 = A2 - DN - ( B1+B2 ) + END IF + IF( GAP1.GT.ZERO .AND. GAP1.GT.B1 ) THEN + S = MAX( DN-( B1 / GAP1 )*B1, HALF*DMIN ) + TTYPE = -2 + ELSE + S = ZERO + IF( DN.GT.B1 ) + $ S = DN - B1 + IF( A2.GT.( B1+B2 ) ) + $ S = MIN( S, A2-( B1+B2 ) ) + S = MAX( S, THIRD*DMIN ) + TTYPE = -3 + END IF + ELSE +* +* Case 4. +* + TTYPE = -4 + S = QURTR*DMIN + IF( DMIN.EQ.DN ) THEN + GAM = DN + A2 = ZERO + IF( Z( NN-5 ) .GT. Z( NN-7 ) ) + $ RETURN + B2 = Z( NN-5 ) / Z( NN-7 ) + NP = NN - 9 + ELSE + NP = NN - 2*PP + B2 = Z( NP-2 ) + GAM = DN1 + IF( Z( NP-4 ) .GT. Z( NP-2 ) ) + $ RETURN + A2 = Z( NP-4 ) / Z( NP-2 ) + IF( Z( NN-9 ) .GT. Z( NN-11 ) ) + $ RETURN + B2 = Z( NN-9 ) / Z( NN-11 ) + NP = NN - 13 + END IF +* +* Approximate contribution to norm squared from I < NN-1. +* + A2 = A2 + B2 + DO 10 I4 = NP, 4*I0 - 1 + PP, -4 + IF( B2.EQ.ZERO ) + $ GO TO 20 + B1 = B2 + IF( Z( I4 ) .GT. Z( I4-2 ) ) + $ RETURN + B2 = B2*( Z( I4 ) / Z( I4-2 ) ) + A2 = A2 + B2 + IF( HUNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 ) + $ GO TO 20 + 10 CONTINUE + 20 CONTINUE + A2 = CNST3*A2 +* +* Rayleigh quotient residual bound. +* + IF( A2.LT.CNST1 ) + $ S = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 ) + END IF + ELSE IF( DMIN.EQ.DN2 ) THEN +* +* Case 5. +* + TTYPE = -5 + S = QURTR*DMIN +* +* Compute contribution to norm squared from I > NN-2. +* + NP = NN - 2*PP + B1 = Z( NP-2 ) + B2 = Z( NP-6 ) + GAM = DN2 + IF( Z( NP-8 ).GT.B2 .OR. Z( NP-4 ).GT.B1 ) + $ RETURN + A2 = ( Z( NP-8 ) / B2 )*( ONE+Z( NP-4 ) / B1 ) +* +* Approximate contribution to norm squared from I < NN-2. +* + IF( N0-I0.GT.2 ) THEN + B2 = Z( NN-13 ) / Z( NN-15 ) + A2 = A2 + B2 + DO 30 I4 = NN - 17, 4*I0 - 1 + PP, -4 + IF( B2.EQ.ZERO ) + $ GO TO 40 + B1 = B2 + IF( Z( I4 ) .GT. Z( I4-2 ) ) + $ RETURN + B2 = B2*( Z( I4 ) / Z( I4-2 ) ) + A2 = A2 + B2 + IF( HUNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 ) + $ GO TO 40 + 30 CONTINUE + 40 CONTINUE + A2 = CNST3*A2 + END IF +* + IF( A2.LT.CNST1 ) + $ S = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 ) + ELSE +* +* Case 6, no information to guide us. +* + IF( TTYPE.EQ.-6 ) THEN + G = G + THIRD*( ONE-G ) + ELSE IF( TTYPE.EQ.-18 ) THEN + G = QURTR*THIRD + ELSE + G = QURTR + END IF + S = G*DMIN + TTYPE = -6 + END IF +* + ELSE IF( N0IN.EQ.( N0+1 ) ) THEN +* +* One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. +* + IF( DMIN1.EQ.DN1 .AND. DMIN2.EQ.DN2 ) THEN +* +* Cases 7 and 8. +* + TTYPE = -7 + S = THIRD*DMIN1 + IF( Z( NN-5 ).GT.Z( NN-7 ) ) + $ RETURN + B1 = Z( NN-5 ) / Z( NN-7 ) + B2 = B1 + IF( B2.EQ.ZERO ) + $ GO TO 60 + DO 50 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4 + A2 = B1 + IF( Z( I4 ).GT.Z( I4-2 ) ) + $ RETURN + B1 = B1*( Z( I4 ) / Z( I4-2 ) ) + B2 = B2 + B1 + IF( HUNDRD*MAX( B1, A2 ).LT.B2 ) + $ GO TO 60 + 50 CONTINUE + 60 CONTINUE + B2 = SQRT( CNST3*B2 ) + A2 = DMIN1 / ( ONE+B2**2 ) + GAP2 = HALF*DMIN2 - A2 + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THEN + S = MAX( S, A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ) ) + ELSE + S = MAX( S, A2*( ONE-CNST2*B2 ) ) + TTYPE = -8 + END IF + ELSE +* +* Case 9. +* + S = QURTR*DMIN1 + IF( DMIN1.EQ.DN1 ) + $ S = HALF*DMIN1 + TTYPE = -9 + END IF +* + ELSE IF( N0IN.EQ.( N0+2 ) ) THEN +* +* Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. +* +* Cases 10 and 11. +* + IF( DMIN2.EQ.DN2 .AND. TWO*Z( NN-5 ).LT.Z( NN-7 ) ) THEN + TTYPE = -10 + S = THIRD*DMIN2 + IF( Z( NN-5 ).GT.Z( NN-7 ) ) + $ RETURN + B1 = Z( NN-5 ) / Z( NN-7 ) + B2 = B1 + IF( B2.EQ.ZERO ) + $ GO TO 80 + DO 70 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4 + IF( Z( I4 ).GT.Z( I4-2 ) ) + $ RETURN + B1 = B1*( Z( I4 ) / Z( I4-2 ) ) + B2 = B2 + B1 + IF( HUNDRD*B1.LT.B2 ) + $ GO TO 80 + 70 CONTINUE + 80 CONTINUE + B2 = SQRT( CNST3*B2 ) + A2 = DMIN2 / ( ONE+B2**2 ) + GAP2 = Z( NN-7 ) + Z( NN-9 ) - + $ SQRT( Z( NN-11 ) )*SQRT( Z( NN-9 ) ) - A2 + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THEN + S = MAX( S, A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ) ) + ELSE + S = MAX( S, A2*( ONE-CNST2*B2 ) ) + END IF + ELSE + S = QURTR*DMIN2 + TTYPE = -11 + END IF + ELSE IF( N0IN.GT.( N0+2 ) ) THEN +* +* Case 12, more than two eigenvalues deflated. No information. +* + S = ZERO + TTYPE = -12 + END IF +* + TAU = S + RETURN +* +* End of DLASQ4 +* + END diff --git a/dep/lapack/dlasq5.f b/dep/lapack/dlasq5.f new file mode 100644 index 00000000..294a4819 --- /dev/null +++ b/dep/lapack/dlasq5.f @@ -0,0 +1,201 @@ + SUBROUTINE DLASQ5( I0, N0, Z, PP, TAU, DMIN, DMIN1, DMIN2, DN, + $ DNM1, DNM2, IEEE ) +* +* -- LAPACK routine (version 3.2) -- +* +* -- Contributed by Osni Marques of the Lawrence Berkeley National -- +* -- Laboratory and Beresford Parlett of the Univ. of California at -- +* -- Berkeley -- +* -- November 2008 -- +* +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* +* .. Scalar Arguments .. + LOGICAL IEEE + INTEGER I0, N0, PP + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* Purpose +* ======= +* +* DLASQ5 computes one dqds transform in ping-pong form, one +* version for IEEE machines another for non IEEE machines. +* +* Arguments +* ========= +* +* I0 (input) INTEGER +* First index. +* +* N0 (input) INTEGER +* Last index. +* +* Z (input) DOUBLE PRECISION array, dimension ( 4*N ) +* Z holds the qd array. EMIN is stored in Z(4*N0) to avoid +* an extra argument. +* +* PP (input) INTEGER +* PP=0 for ping, PP=1 for pong. +* +* TAU (input) DOUBLE PRECISION +* This is the shift. +* +* DMIN (output) DOUBLE PRECISION +* Minimum value of d. +* +* DMIN1 (output) DOUBLE PRECISION +* Minimum value of d, excluding D( N0 ). +* +* DMIN2 (output) DOUBLE PRECISION +* Minimum value of d, excluding D( N0 ) and D( N0-1 ). +* +* DN (output) DOUBLE PRECISION +* d(N0), the last value of d. +* +* DNM1 (output) DOUBLE PRECISION +* d(N0-1). +* +* DNM2 (output) DOUBLE PRECISION +* d(N0-2). +* +* IEEE (input) LOGICAL +* Flag for IEEE or non IEEE arithmetic. +* +* ===================================================================== +* +* .. Parameter .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER J4, J4P2 + DOUBLE PRECISION D, EMIN, TEMP +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( ( N0-I0-1 ).LE.0 ) + $ RETURN +* + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) - TAU + DMIN = D + DMIN1 = -Z( J4 ) +* + IF( IEEE ) THEN +* +* Code for IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 10 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + TEMP = Z( J4+1 ) / Z( J4-2 ) + D = D*TEMP - TAU + DMIN = MIN( DMIN, D ) + Z( J4 ) = Z( J4-1 )*TEMP + EMIN = MIN( Z( J4 ), EMIN ) + 10 CONTINUE + ELSE + DO 20 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + TEMP = Z( J4+2 ) / Z( J4-3 ) + D = D*TEMP - TAU + DMIN = MIN( DMIN, D ) + Z( J4-1 ) = Z( J4 )*TEMP + EMIN = MIN( Z( J4-1 ), EMIN ) + 20 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DN ) +* + ELSE +* +* Code for non IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 30 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 30 CONTINUE + ELSE + DO 40 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) - TAU + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 40 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( DNM2.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( DNM1.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DN ) +* + END IF +* + Z( J4+2 ) = DN + Z( 4*N0-PP ) = EMIN + RETURN +* +* End of DLASQ5 +* + END diff --git a/dep/lapack/dlasq6.f b/dep/lapack/dlasq6.f new file mode 100644 index 00000000..2be20317 --- /dev/null +++ b/dep/lapack/dlasq6.f @@ -0,0 +1,181 @@ + SUBROUTINE DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, + $ DNM1, DNM2 ) +* +* -- LAPACK routine (version 3.2) -- +* +* -- Contributed by Osni Marques of the Lawrence Berkeley National -- +* -- Laboratory and Beresford Parlett of the Univ. of California at -- +* -- Berkeley -- +* -- November 2008 -- +* +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* +* .. Scalar Arguments .. + INTEGER I0, N0, PP + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2 +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* Purpose +* ======= +* +* DLASQ6 computes one dqd (shift equal to zero) transform in +* ping-pong form, with protection against underflow and overflow. +* +* Arguments +* ========= +* +* I0 (input) INTEGER +* First index. +* +* N0 (input) INTEGER +* Last index. +* +* Z (input) DOUBLE PRECISION array, dimension ( 4*N ) +* Z holds the qd array. EMIN is stored in Z(4*N0) to avoid +* an extra argument. +* +* PP (input) INTEGER +* PP=0 for ping, PP=1 for pong. +* +* DMIN (output) DOUBLE PRECISION +* Minimum value of d. +* +* DMIN1 (output) DOUBLE PRECISION +* Minimum value of d, excluding D( N0 ). +* +* DMIN2 (output) DOUBLE PRECISION +* Minimum value of d, excluding D( N0 ) and D( N0-1 ). +* +* DN (output) DOUBLE PRECISION +* d(N0), the last value of d. +* +* DNM1 (output) DOUBLE PRECISION +* d(N0-1). +* +* DNM2 (output) DOUBLE PRECISION +* d(N0-2). +* +* ===================================================================== +* +* .. Parameter .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER J4, J4P2 + DOUBLE PRECISION D, EMIN, SAFMIN, TEMP +* .. +* .. External Function .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( ( N0-I0-1 ).LE.0 ) + $ RETURN +* + SAFMIN = DLAMCH( 'Safe minimum' ) + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) + DMIN = D +* + IF( PP.EQ.0 ) THEN + DO 10 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + D = Z( J4+1 ) + DMIN = D + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4+1 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4+1 ) ) THEN + TEMP = Z( J4+1 ) / Z( J4-2 ) + Z( J4 ) = Z( J4-1 )*TEMP + D = D*TEMP + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 10 CONTINUE + ELSE + DO 20 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( Z( J4-3 ).EQ.ZERO ) THEN + Z( J4-1 ) = ZERO + D = Z( J4+2 ) + DMIN = D + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4+2 ).LT.Z( J4-3 ) .AND. + $ SAFMIN*Z( J4-3 ).LT.Z( J4+2 ) ) THEN + TEMP = Z( J4+2 ) / Z( J4-3 ) + Z( J4-1 ) = Z( J4 )*TEMP + D = D*TEMP + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 20 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + DNM1 = Z( J4P2+2 ) + DMIN = DNM1 + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4P2+2 ) ) THEN + TEMP = Z( J4P2+2 ) / Z( J4-2 ) + Z( J4 ) = Z( J4P2 )*TEMP + DNM1 = DNM2*TEMP + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + DN = Z( J4P2+2 ) + DMIN = DN + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4P2+2 ) ) THEN + TEMP = Z( J4P2+2 ) / Z( J4-2 ) + Z( J4 ) = Z( J4P2 )*TEMP + DN = DNM1*TEMP + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, DN ) +* + Z( J4+2 ) = DN + Z( 4*N0-PP ) = EMIN + RETURN +* +* End of DLASQ6 +* + END diff --git a/dep/lapack/dlasr.f b/dep/lapack/dlasr.f new file mode 100644 index 00000000..55ab2e37 --- /dev/null +++ b/dep/lapack/dlasr.f @@ -0,0 +1,362 @@ + SUBROUTINE DLASR( SIDE, PIVOT, DIRECT, M, N, C, S, A, LDA ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER DIRECT, PIVOT, SIDE + INTEGER LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( * ), S( * ) +* .. +* +* Purpose +* ======= +* +* DLASR applies a sequence of plane rotations to a real matrix A, +* from either the left or the right. +* +* When SIDE = 'L', the transformation takes the form +* +* A := P*A +* +* and when SIDE = 'R', the transformation takes the form +* +* A := A*P**T +* +* where P is an orthogonal matrix consisting of a sequence of z plane +* rotations, with z = M when SIDE = 'L' and z = N when SIDE = 'R', +* and P**T is the transpose of P. +* +* When DIRECT = 'F' (Forward sequence), then +* +* P = P(z-1) * ... * P(2) * P(1) +* +* and when DIRECT = 'B' (Backward sequence), then +* +* P = P(1) * P(2) * ... * P(z-1) +* +* where P(k) is a plane rotation matrix defined by the 2-by-2 rotation +* +* R(k) = ( c(k) s(k) ) +* = ( -s(k) c(k) ). +* +* When PIVOT = 'V' (Variable pivot), the rotation is performed +* for the plane (k,k+1), i.e., P(k) has the form +* +* P(k) = ( 1 ) +* ( ... ) +* ( 1 ) +* ( c(k) s(k) ) +* ( -s(k) c(k) ) +* ( 1 ) +* ( ... ) +* ( 1 ) +* +* where R(k) appears as a rank-2 modification to the identity matrix in +* rows and columns k and k+1. +* +* When PIVOT = 'T' (Top pivot), the rotation is performed for the +* plane (1,k+1), so P(k) has the form +* +* P(k) = ( c(k) s(k) ) +* ( 1 ) +* ( ... ) +* ( 1 ) +* ( -s(k) c(k) ) +* ( 1 ) +* ( ... ) +* ( 1 ) +* +* where R(k) appears in rows and columns 1 and k+1. +* +* Similarly, when PIVOT = 'B' (Bottom pivot), the rotation is +* performed for the plane (k,z), giving P(k) the form +* +* P(k) = ( 1 ) +* ( ... ) +* ( 1 ) +* ( c(k) s(k) ) +* ( 1 ) +* ( ... ) +* ( 1 ) +* ( -s(k) c(k) ) +* +* where R(k) appears in rows and columns k and z. The rotations are +* performed without ever forming P(k) explicitly. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* Specifies whether the plane rotation matrix P is applied to +* A on the left or the right. +* = 'L': Left, compute A := P*A +* = 'R': Right, compute A:= A*P**T +* +* PIVOT (input) CHARACTER*1 +* Specifies the plane for which P(k) is a plane rotation +* matrix. +* = 'V': Variable pivot, the plane (k,k+1) +* = 'T': Top pivot, the plane (1,k+1) +* = 'B': Bottom pivot, the plane (k,z) +* +* DIRECT (input) CHARACTER*1 +* Specifies whether P is a forward or backward sequence of +* plane rotations. +* = 'F': Forward, P = P(z-1)*...*P(2)*P(1) +* = 'B': Backward, P = P(1)*P(2)*...*P(z-1) +* +* M (input) INTEGER +* The number of rows of the matrix A. If m <= 1, an immediate +* return is effected. +* +* N (input) INTEGER +* The number of columns of the matrix A. If n <= 1, an +* immediate return is effected. +* +* C (input) DOUBLE PRECISION array, dimension +* (M-1) if SIDE = 'L' +* (N-1) if SIDE = 'R' +* The cosines c(k) of the plane rotations. +* +* S (input) DOUBLE PRECISION array, dimension +* (M-1) if SIDE = 'L' +* (N-1) if SIDE = 'R' +* The sines s(k) of the plane rotations. The 2-by-2 plane +* rotation part of the matrix P(k), R(k), has the form +* R(k) = ( c(k) s(k) ) +* ( -s(k) c(k) ). +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* The M-by-N matrix A. On exit, A is overwritten by P*A if +* SIDE = 'R' or by A*P**T if SIDE = 'L'. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, INFO, J + DOUBLE PRECISION CTEMP, STEMP, TEMP +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + IF( .NOT.( LSAME( SIDE, 'L' ) .OR. LSAME( SIDE, 'R' ) ) ) THEN + INFO = 1 + ELSE IF( .NOT.( LSAME( PIVOT, 'V' ) .OR. LSAME( PIVOT, + $ 'T' ) .OR. LSAME( PIVOT, 'B' ) ) ) THEN + INFO = 2 + ELSE IF( .NOT.( LSAME( DIRECT, 'F' ) .OR. LSAME( DIRECT, 'B' ) ) ) + $ THEN + INFO = 3 + ELSE IF( M.LT.0 ) THEN + INFO = 4 + ELSE IF( N.LT.0 ) THEN + INFO = 5 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = 9 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASR ', INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) ) + $ RETURN + IF( LSAME( SIDE, 'L' ) ) THEN +* +* Form P * A +* + IF( LSAME( PIVOT, 'V' ) ) THEN + IF( LSAME( DIRECT, 'F' ) ) THEN + DO 20 J = 1, M - 1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 10 I = 1, N + TEMP = A( J+1, I ) + A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I ) + A( J, I ) = STEMP*TEMP + CTEMP*A( J, I ) + 10 CONTINUE + END IF + 20 CONTINUE + ELSE IF( LSAME( DIRECT, 'B' ) ) THEN + DO 40 J = M - 1, 1, -1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 30 I = 1, N + TEMP = A( J+1, I ) + A( J+1, I ) = CTEMP*TEMP - STEMP*A( J, I ) + A( J, I ) = STEMP*TEMP + CTEMP*A( J, I ) + 30 CONTINUE + END IF + 40 CONTINUE + END IF + ELSE IF( LSAME( PIVOT, 'T' ) ) THEN + IF( LSAME( DIRECT, 'F' ) ) THEN + DO 60 J = 2, M + CTEMP = C( J-1 ) + STEMP = S( J-1 ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 50 I = 1, N + TEMP = A( J, I ) + A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I ) + A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I ) + 50 CONTINUE + END IF + 60 CONTINUE + ELSE IF( LSAME( DIRECT, 'B' ) ) THEN + DO 80 J = M, 2, -1 + CTEMP = C( J-1 ) + STEMP = S( J-1 ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 70 I = 1, N + TEMP = A( J, I ) + A( J, I ) = CTEMP*TEMP - STEMP*A( 1, I ) + A( 1, I ) = STEMP*TEMP + CTEMP*A( 1, I ) + 70 CONTINUE + END IF + 80 CONTINUE + END IF + ELSE IF( LSAME( PIVOT, 'B' ) ) THEN + IF( LSAME( DIRECT, 'F' ) ) THEN + DO 100 J = 1, M - 1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 90 I = 1, N + TEMP = A( J, I ) + A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMP + A( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP + 90 CONTINUE + END IF + 100 CONTINUE + ELSE IF( LSAME( DIRECT, 'B' ) ) THEN + DO 120 J = M - 1, 1, -1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 110 I = 1, N + TEMP = A( J, I ) + A( J, I ) = STEMP*A( M, I ) + CTEMP*TEMP + A( M, I ) = CTEMP*A( M, I ) - STEMP*TEMP + 110 CONTINUE + END IF + 120 CONTINUE + END IF + END IF + ELSE IF( LSAME( SIDE, 'R' ) ) THEN +* +* Form A * P**T +* + IF( LSAME( PIVOT, 'V' ) ) THEN + IF( LSAME( DIRECT, 'F' ) ) THEN + DO 140 J = 1, N - 1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 130 I = 1, M + TEMP = A( I, J+1 ) + A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J ) + A( I, J ) = STEMP*TEMP + CTEMP*A( I, J ) + 130 CONTINUE + END IF + 140 CONTINUE + ELSE IF( LSAME( DIRECT, 'B' ) ) THEN + DO 160 J = N - 1, 1, -1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 150 I = 1, M + TEMP = A( I, J+1 ) + A( I, J+1 ) = CTEMP*TEMP - STEMP*A( I, J ) + A( I, J ) = STEMP*TEMP + CTEMP*A( I, J ) + 150 CONTINUE + END IF + 160 CONTINUE + END IF + ELSE IF( LSAME( PIVOT, 'T' ) ) THEN + IF( LSAME( DIRECT, 'F' ) ) THEN + DO 180 J = 2, N + CTEMP = C( J-1 ) + STEMP = S( J-1 ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 170 I = 1, M + TEMP = A( I, J ) + A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 ) + A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 ) + 170 CONTINUE + END IF + 180 CONTINUE + ELSE IF( LSAME( DIRECT, 'B' ) ) THEN + DO 200 J = N, 2, -1 + CTEMP = C( J-1 ) + STEMP = S( J-1 ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 190 I = 1, M + TEMP = A( I, J ) + A( I, J ) = CTEMP*TEMP - STEMP*A( I, 1 ) + A( I, 1 ) = STEMP*TEMP + CTEMP*A( I, 1 ) + 190 CONTINUE + END IF + 200 CONTINUE + END IF + ELSE IF( LSAME( PIVOT, 'B' ) ) THEN + IF( LSAME( DIRECT, 'F' ) ) THEN + DO 220 J = 1, N - 1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 210 I = 1, M + TEMP = A( I, J ) + A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMP + A( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP + 210 CONTINUE + END IF + 220 CONTINUE + ELSE IF( LSAME( DIRECT, 'B' ) ) THEN + DO 240 J = N - 1, 1, -1 + CTEMP = C( J ) + STEMP = S( J ) + IF( ( CTEMP.NE.ONE ) .OR. ( STEMP.NE.ZERO ) ) THEN + DO 230 I = 1, M + TEMP = A( I, J ) + A( I, J ) = STEMP*A( I, N ) + CTEMP*TEMP + A( I, N ) = CTEMP*A( I, N ) - STEMP*TEMP + 230 CONTINUE + END IF + 240 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DLASR +* + END diff --git a/dep/lapack/dlasrt.f b/dep/lapack/dlasrt.f new file mode 100644 index 00000000..90eda0cd --- /dev/null +++ b/dep/lapack/dlasrt.f @@ -0,0 +1,244 @@ + SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) +* .. +* +* Purpose +* ======= +* +* Sort the numbers in D in increasing order (if ID = 'I') or +* in decreasing order (if ID = 'D' ). +* +* Use Quick Sort, reverting to Insertion sort on arrays of +* size <= 20. Dimension of STACK limits N to about 2**32. +* +* Arguments +* ========= +* +* ID (input) CHARACTER*1 +* = 'I': sort D in increasing order; +* = 'D': sort D in decreasing order. +* +* N (input) INTEGER +* The length of the array D. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the array to be sorted. +* On exit, D has been sorted into increasing order +* (D(1) <= ... <= D(N) ) or into decreasing order +* (D(1) >= ... >= D(N) ), depending on ID. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT + DOUBLE PRECISION D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASRT', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 + RETURN +* +* End of DLASRT +* + END diff --git a/dep/lapack/dlassq.f b/dep/lapack/dlassq.f new file mode 100644 index 00000000..51cce918 --- /dev/null +++ b/dep/lapack/dlassq.f @@ -0,0 +1,89 @@ + SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INCX, N + DOUBLE PRECISION SCALE, SUMSQ +* .. +* .. Array Arguments .. + DOUBLE PRECISION X( * ) +* .. +* +* Purpose +* ======= +* +* DLASSQ returns the values scl and smsq such that +* +* ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq, +* +* where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is +* assumed to be non-negative and scl returns the value +* +* scl = max( scale, abs( x( i ) ) ). +* +* scale and sumsq must be supplied in SCALE and SUMSQ and +* scl and smsq are overwritten on SCALE and SUMSQ respectively. +* +* The routine makes only one pass through the vector x. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of elements to be used from the vector X. +* +* X (input) DOUBLE PRECISION array, dimension (N) +* The vector for which a scaled sum of squares is computed. +* x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n. +* +* INCX (input) INTEGER +* The increment between successive values of the vector X. +* INCX > 0. +* +* SCALE (input/output) DOUBLE PRECISION +* On entry, the value scale in the equation above. +* On exit, SCALE is overwritten with scl , the scaling factor +* for the sum of squares. +* +* SUMSQ (input/output) DOUBLE PRECISION +* On entry, the value sumsq in the equation above. +* On exit, SUMSQ is overwritten with smsq , the basic sum of +* squares from which scl has been factored out. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER IX + DOUBLE PRECISION ABSXI +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. +* + IF( N.GT.0 ) THEN + DO 10 IX = 1, 1 + ( N-1 )*INCX, INCX + IF( X( IX ).NE.ZERO ) THEN + ABSXI = ABS( X( IX ) ) + IF( SCALE.LT.ABSXI ) THEN + SUMSQ = 1 + SUMSQ*( SCALE / ABSXI )**2 + SCALE = ABSXI + ELSE + SUMSQ = SUMSQ + ( ABSXI / SCALE )**2 + END IF + END IF + 10 CONTINUE + END IF + RETURN +* +* End of DLASSQ +* + END diff --git a/dep/lapack/dlasv2.f b/dep/lapack/dlasv2.f new file mode 100644 index 00000000..ca725340 --- /dev/null +++ b/dep/lapack/dlasv2.f @@ -0,0 +1,250 @@ + SUBROUTINE DLASV2( F, G, H, SSMIN, SSMAX, SNR, CSR, SNL, CSL ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + DOUBLE PRECISION CSL, CSR, F, G, H, SNL, SNR, SSMAX, SSMIN +* .. +* +* Purpose +* ======= +* +* DLASV2 computes the singular value decomposition of a 2-by-2 +* triangular matrix +* [ F G ] +* [ 0 H ]. +* On return, abs(SSMAX) is the larger singular value, abs(SSMIN) is the +* smaller singular value, and (CSL,SNL) and (CSR,SNR) are the left and +* right singular vectors for abs(SSMAX), giving the decomposition +* +* [ CSL SNL ] [ F G ] [ CSR -SNR ] = [ SSMAX 0 ] +* [-SNL CSL ] [ 0 H ] [ SNR CSR ] [ 0 SSMIN ]. +* +* Arguments +* ========= +* +* F (input) DOUBLE PRECISION +* The (1,1) element of the 2-by-2 matrix. +* +* G (input) DOUBLE PRECISION +* The (1,2) element of the 2-by-2 matrix. +* +* H (input) DOUBLE PRECISION +* The (2,2) element of the 2-by-2 matrix. +* +* SSMIN (output) DOUBLE PRECISION +* abs(SSMIN) is the smaller singular value. +* +* SSMAX (output) DOUBLE PRECISION +* abs(SSMAX) is the larger singular value. +* +* SNL (output) DOUBLE PRECISION +* CSL (output) DOUBLE PRECISION +* The vector (CSL, SNL) is a unit left singular vector for the +* singular value abs(SSMAX). +* +* SNR (output) DOUBLE PRECISION +* CSR (output) DOUBLE PRECISION +* The vector (CSR, SNR) is a unit right singular vector for the +* singular value abs(SSMAX). +* +* Further Details +* =============== +* +* Any input parameter may be aliased with any output parameter. +* +* Barring over/underflow and assuming a guard digit in subtraction, all +* output quantities are correct to within a few units in the last +* place (ulps). +* +* In IEEE arithmetic, the code works correctly if one matrix element is +* infinite. +* +* Overflow will not occur unless the largest singular value itself +* overflows or is within a few ulps of overflow. (On machines with +* partial overflow, like the Cray, overflow may occur if the largest +* singular value is within a factor of 2 of overflow.) +* +* Underflow is harmless if underflow is gradual. Otherwise, results +* may correspond to a matrix modified by perturbations of size near +* the underflow threshold. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION HALF + PARAMETER ( HALF = 0.5D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) + DOUBLE PRECISION FOUR + PARAMETER ( FOUR = 4.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL GASMAL, SWAP + INTEGER PMAX + DOUBLE PRECISION A, CLT, CRT, D, FA, FT, GA, GT, HA, HT, L, M, + $ MM, R, S, SLT, SRT, T, TEMP, TSIGN, TT +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN, SQRT +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Executable Statements .. +* + FT = F + FA = ABS( FT ) + HT = H + HA = ABS( H ) +* +* PMAX points to the maximum absolute element of matrix +* PMAX = 1 if F largest in absolute values +* PMAX = 2 if G largest in absolute values +* PMAX = 3 if H largest in absolute values +* + PMAX = 1 + SWAP = ( HA.GT.FA ) + IF( SWAP ) THEN + PMAX = 3 + TEMP = FT + FT = HT + HT = TEMP + TEMP = FA + FA = HA + HA = TEMP +* +* Now FA .ge. HA +* + END IF + GT = G + GA = ABS( GT ) + IF( GA.EQ.ZERO ) THEN +* +* Diagonal matrix +* + SSMIN = HA + SSMAX = FA + CLT = ONE + CRT = ONE + SLT = ZERO + SRT = ZERO + ELSE + GASMAL = .TRUE. + IF( GA.GT.FA ) THEN + PMAX = 2 + IF( ( FA / GA ).LT.DLAMCH( 'EPS' ) ) THEN +* +* Case of very large GA +* + GASMAL = .FALSE. + SSMAX = GA + IF( HA.GT.ONE ) THEN + SSMIN = FA / ( GA / HA ) + ELSE + SSMIN = ( FA / GA )*HA + END IF + CLT = ONE + SLT = HT / GT + SRT = ONE + CRT = FT / GT + END IF + END IF + IF( GASMAL ) THEN +* +* Normal case +* + D = FA - HA + IF( D.EQ.FA ) THEN +* +* Copes with infinite F or H +* + L = ONE + ELSE + L = D / FA + END IF +* +* Note that 0 .le. L .le. 1 +* + M = GT / FT +* +* Note that abs(M) .le. 1/macheps +* + T = TWO - L +* +* Note that T .ge. 1 +* + MM = M*M + TT = T*T + S = SQRT( TT+MM ) +* +* Note that 1 .le. S .le. 1 + 1/macheps +* + IF( L.EQ.ZERO ) THEN + R = ABS( M ) + ELSE + R = SQRT( L*L+MM ) + END IF +* +* Note that 0 .le. R .le. 1 + 1/macheps +* + A = HALF*( S+R ) +* +* Note that 1 .le. A .le. 1 + abs(M) +* + SSMIN = HA / A + SSMAX = FA*A + IF( MM.EQ.ZERO ) THEN +* +* Note that M is very tiny +* + IF( L.EQ.ZERO ) THEN + T = SIGN( TWO, FT )*SIGN( ONE, GT ) + ELSE + T = GT / SIGN( D, FT ) + M / T + END IF + ELSE + T = ( M / ( S+T )+M / ( R+L ) )*( ONE+A ) + END IF + L = SQRT( T*T+FOUR ) + CRT = TWO / L + SRT = T / L + CLT = ( CRT+SRT*M ) / A + SLT = ( HT / FT )*SRT / A + END IF + END IF + IF( SWAP ) THEN + CSL = SRT + SNL = CRT + CSR = SLT + SNR = CLT + ELSE + CSL = CLT + SNL = SLT + CSR = CRT + SNR = SRT + END IF +* +* Correct signs of SSMAX and SSMIN +* + IF( PMAX.EQ.1 ) + $ TSIGN = SIGN( ONE, CSR )*SIGN( ONE, CSL )*SIGN( ONE, F ) + IF( PMAX.EQ.2 ) + $ TSIGN = SIGN( ONE, SNR )*SIGN( ONE, CSL )*SIGN( ONE, G ) + IF( PMAX.EQ.3 ) + $ TSIGN = SIGN( ONE, SNR )*SIGN( ONE, SNL )*SIGN( ONE, H ) + SSMAX = SIGN( SSMAX, TSIGN ) + SSMIN = SIGN( SSMIN, TSIGN*SIGN( ONE, F )*SIGN( ONE, H ) ) + RETURN +* +* End of DLASV2 +* + END diff --git a/dep/lapack/dlaswp.f b/dep/lapack/dlaswp.f new file mode 100644 index 00000000..84115898 --- /dev/null +++ b/dep/lapack/dlaswp.f @@ -0,0 +1,98 @@ + SUBROUTINE DLASWP( N, A, LDA, K1, K2, IPIV, INCX ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + INTEGER INCX, K1, K2, LDA, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DLASWP performs a series of row interchanges on the matrix A. +* One row interchange is initiated for each of rows K1 through K2 of A. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of columns of the matrix A. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the matrix of column dimension N to which the row +* interchanges will be applied. +* On exit, the permuted matrix. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* +* K1 (input) INTEGER +* The first element of IPIV for which a row interchange will +* be done. +* +* K2 (input) INTEGER +* The last element of IPIV for which a row interchange will +* be done. +* +* IPIV (input) INTEGER array, dimension (M*abs(INCX)) +* The vector of pivot indices. Only the elements in positions +* K1 through K2 of IPIV are accessed. +* IPIV(K) = L implies rows K and L are to be interchanged. +* +* INCX (input) INTEGER +* The increment between successive values of IPIV. If IPIV +* is negative, the pivots are applied in reverse order. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, IP, IX +* .. +* .. External Subroutines .. + EXTERNAL DSWAP +* .. +* .. Executable Statements .. +* +* Interchange row I with row IPIV(I) for each of rows K1 through K2. +* + IF( INCX.EQ.0 ) + $ RETURN + IF( INCX.GT.0 ) THEN + IX = K1 + ELSE + IX = 1 + ( 1-K2 )*INCX + END IF + IF( INCX.EQ.1 ) THEN + DO 10 I = K1, K2 + IP = IPIV( I ) + IF( IP.NE.I ) + $ CALL DSWAP( N, A( I, 1 ), LDA, A( IP, 1 ), LDA ) + 10 CONTINUE + ELSE IF( INCX.GT.1 ) THEN + DO 20 I = K1, K2 + IP = IPIV( IX ) + IF( IP.NE.I ) + $ CALL DSWAP( N, A( I, 1 ), LDA, A( IP, 1 ), LDA ) + IX = IX + INCX + 20 CONTINUE + ELSE IF( INCX.LT.0 ) THEN + DO 30 I = K2, K1, -1 + IP = IPIV( IX ) + IF( IP.NE.I ) + $ CALL DSWAP( N, A( I, 1 ), LDA, A( IP, 1 ), LDA ) + IX = IX + INCX + 30 CONTINUE + END IF +* + RETURN +* +* End of DLASWP +* + END diff --git a/dep/lapack/dlasy2.f b/dep/lapack/dlasy2.f new file mode 100644 index 00000000..9fbb88df --- /dev/null +++ b/dep/lapack/dlasy2.f @@ -0,0 +1,382 @@ + SUBROUTINE DLASY2( LTRANL, LTRANR, ISGN, N1, N2, TL, LDTL, TR, + $ LDTR, B, LDB, SCALE, X, LDX, XNORM, INFO ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + LOGICAL LTRANL, LTRANR + INTEGER INFO, ISGN, LDB, LDTL, LDTR, LDX, N1, N2 + DOUBLE PRECISION SCALE, XNORM +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), TL( LDTL, * ), TR( LDTR, * ), + $ X( LDX, * ) +* .. +* +* Purpose +* ======= +* +* DLASY2 solves for the N1 by N2 matrix X, 1 <= N1,N2 <= 2, in +* +* op(TL)*X + ISGN*X*op(TR) = SCALE*B, +* +* where TL is N1 by N1, TR is N2 by N2, B is N1 by N2, and ISGN = 1 or +* -1. op(T) = T or T', where T' denotes the transpose of T. +* +* Arguments +* ========= +* +* LTRANL (input) LOGICAL +* On entry, LTRANL specifies the op(TL): +* = .FALSE., op(TL) = TL, +* = .TRUE., op(TL) = TL'. +* +* LTRANR (input) LOGICAL +* On entry, LTRANR specifies the op(TR): +* = .FALSE., op(TR) = TR, +* = .TRUE., op(TR) = TR'. +* +* ISGN (input) INTEGER +* On entry, ISGN specifies the sign of the equation +* as described before. ISGN may only be 1 or -1. +* +* N1 (input) INTEGER +* On entry, N1 specifies the order of matrix TL. +* N1 may only be 0, 1 or 2. +* +* N2 (input) INTEGER +* On entry, N2 specifies the order of matrix TR. +* N2 may only be 0, 1 or 2. +* +* TL (input) DOUBLE PRECISION array, dimension (LDTL,2) +* On entry, TL contains an N1 by N1 matrix. +* +* LDTL (input) INTEGER +* The leading dimension of the matrix TL. LDTL >= max(1,N1). +* +* TR (input) DOUBLE PRECISION array, dimension (LDTR,2) +* On entry, TR contains an N2 by N2 matrix. +* +* LDTR (input) INTEGER +* The leading dimension of the matrix TR. LDTR >= max(1,N2). +* +* B (input) DOUBLE PRECISION array, dimension (LDB,2) +* On entry, the N1 by N2 matrix B contains the right-hand +* side of the equation. +* +* LDB (input) INTEGER +* The leading dimension of the matrix B. LDB >= max(1,N1). +* +* SCALE (output) DOUBLE PRECISION +* On exit, SCALE contains the scale factor. SCALE is chosen +* less than or equal to 1 to prevent the solution overflowing. +* +* X (output) DOUBLE PRECISION array, dimension (LDX,2) +* On exit, X contains the N1 by N2 solution. +* +* LDX (input) INTEGER +* The leading dimension of the matrix X. LDX >= max(1,N1). +* +* XNORM (output) DOUBLE PRECISION +* On exit, XNORM is the infinity-norm of the solution. +* +* INFO (output) INTEGER +* On exit, INFO is set to +* 0: successful exit. +* 1: TL and TR have too close eigenvalues, so TL or +* TR is perturbed to get a nonsingular equation. +* NOTE: In the interests of speed, this routine does not +* check the inputs for errors. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) + DOUBLE PRECISION TWO, HALF, EIGHT + PARAMETER ( TWO = 2.0D+0, HALF = 0.5D+0, EIGHT = 8.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL BSWAP, XSWAP + INTEGER I, IP, IPIV, IPSV, J, JP, JPSV, K + DOUBLE PRECISION BET, EPS, GAM, L21, SGN, SMIN, SMLNUM, TAU1, + $ TEMP, U11, U12, U22, XMAX +* .. +* .. Local Arrays .. + LOGICAL BSWPIV( 4 ), XSWPIV( 4 ) + INTEGER JPIV( 4 ), LOCL21( 4 ), LOCU12( 4 ), + $ LOCU22( 4 ) + DOUBLE PRECISION BTMP( 4 ), T16( 4, 4 ), TMP( 4 ), X2( 2 ) +* .. +* .. External Functions .. + INTEGER IDAMAX + DOUBLE PRECISION DLAMCH + EXTERNAL IDAMAX, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DSWAP +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX +* .. +* .. Data statements .. + DATA LOCU12 / 3, 4, 1, 2 / , LOCL21 / 2, 1, 4, 3 / , + $ LOCU22 / 4, 3, 2, 1 / + DATA XSWPIV / .FALSE., .FALSE., .TRUE., .TRUE. / + DATA BSWPIV / .FALSE., .TRUE., .FALSE., .TRUE. / +* .. +* .. Executable Statements .. +* +* Do not check the input parameters for errors +* + INFO = 0 +* +* Quick return if possible +* + IF( N1.EQ.0 .OR. N2.EQ.0 ) + $ RETURN +* +* Set constants to control overflow +* + EPS = DLAMCH( 'P' ) + SMLNUM = DLAMCH( 'S' ) / EPS + SGN = ISGN +* + K = N1 + N1 + N2 - 2 + GO TO ( 10, 20, 30, 50 )K +* +* 1 by 1: TL11*X + SGN*X*TR11 = B11 +* + 10 CONTINUE + TAU1 = TL( 1, 1 ) + SGN*TR( 1, 1 ) + BET = ABS( TAU1 ) + IF( BET.LE.SMLNUM ) THEN + TAU1 = SMLNUM + BET = SMLNUM + INFO = 1 + END IF +* + SCALE = ONE + GAM = ABS( B( 1, 1 ) ) + IF( SMLNUM*GAM.GT.BET ) + $ SCALE = ONE / GAM +* + X( 1, 1 ) = ( B( 1, 1 )*SCALE ) / TAU1 + XNORM = ABS( X( 1, 1 ) ) + RETURN +* +* 1 by 2: +* TL11*[X11 X12] + ISGN*[X11 X12]*op[TR11 TR12] = [B11 B12] +* [TR21 TR22] +* + 20 CONTINUE +* + SMIN = MAX( EPS*MAX( ABS( TL( 1, 1 ) ), ABS( TR( 1, 1 ) ), + $ ABS( TR( 1, 2 ) ), ABS( TR( 2, 1 ) ), ABS( TR( 2, 2 ) ) ), + $ SMLNUM ) + TMP( 1 ) = TL( 1, 1 ) + SGN*TR( 1, 1 ) + TMP( 4 ) = TL( 1, 1 ) + SGN*TR( 2, 2 ) + IF( LTRANR ) THEN + TMP( 2 ) = SGN*TR( 2, 1 ) + TMP( 3 ) = SGN*TR( 1, 2 ) + ELSE + TMP( 2 ) = SGN*TR( 1, 2 ) + TMP( 3 ) = SGN*TR( 2, 1 ) + END IF + BTMP( 1 ) = B( 1, 1 ) + BTMP( 2 ) = B( 1, 2 ) + GO TO 40 +* +* 2 by 1: +* op[TL11 TL12]*[X11] + ISGN* [X11]*TR11 = [B11] +* [TL21 TL22] [X21] [X21] [B21] +* + 30 CONTINUE + SMIN = MAX( EPS*MAX( ABS( TR( 1, 1 ) ), ABS( TL( 1, 1 ) ), + $ ABS( TL( 1, 2 ) ), ABS( TL( 2, 1 ) ), ABS( TL( 2, 2 ) ) ), + $ SMLNUM ) + TMP( 1 ) = TL( 1, 1 ) + SGN*TR( 1, 1 ) + TMP( 4 ) = TL( 2, 2 ) + SGN*TR( 1, 1 ) + IF( LTRANL ) THEN + TMP( 2 ) = TL( 1, 2 ) + TMP( 3 ) = TL( 2, 1 ) + ELSE + TMP( 2 ) = TL( 2, 1 ) + TMP( 3 ) = TL( 1, 2 ) + END IF + BTMP( 1 ) = B( 1, 1 ) + BTMP( 2 ) = B( 2, 1 ) + 40 CONTINUE +* +* Solve 2 by 2 system using complete pivoting. +* Set pivots less than SMIN to SMIN. +* + IPIV = IDAMAX( 4, TMP, 1 ) + U11 = TMP( IPIV ) + IF( ABS( U11 ).LE.SMIN ) THEN + INFO = 1 + U11 = SMIN + END IF + U12 = TMP( LOCU12( IPIV ) ) + L21 = TMP( LOCL21( IPIV ) ) / U11 + U22 = TMP( LOCU22( IPIV ) ) - U12*L21 + XSWAP = XSWPIV( IPIV ) + BSWAP = BSWPIV( IPIV ) + IF( ABS( U22 ).LE.SMIN ) THEN + INFO = 1 + U22 = SMIN + END IF + IF( BSWAP ) THEN + TEMP = BTMP( 2 ) + BTMP( 2 ) = BTMP( 1 ) - L21*TEMP + BTMP( 1 ) = TEMP + ELSE + BTMP( 2 ) = BTMP( 2 ) - L21*BTMP( 1 ) + END IF + SCALE = ONE + IF( ( TWO*SMLNUM )*ABS( BTMP( 2 ) ).GT.ABS( U22 ) .OR. + $ ( TWO*SMLNUM )*ABS( BTMP( 1 ) ).GT.ABS( U11 ) ) THEN + SCALE = HALF / MAX( ABS( BTMP( 1 ) ), ABS( BTMP( 2 ) ) ) + BTMP( 1 ) = BTMP( 1 )*SCALE + BTMP( 2 ) = BTMP( 2 )*SCALE + END IF + X2( 2 ) = BTMP( 2 ) / U22 + X2( 1 ) = BTMP( 1 ) / U11 - ( U12 / U11 )*X2( 2 ) + IF( XSWAP ) THEN + TEMP = X2( 2 ) + X2( 2 ) = X2( 1 ) + X2( 1 ) = TEMP + END IF + X( 1, 1 ) = X2( 1 ) + IF( N1.EQ.1 ) THEN + X( 1, 2 ) = X2( 2 ) + XNORM = ABS( X( 1, 1 ) ) + ABS( X( 1, 2 ) ) + ELSE + X( 2, 1 ) = X2( 2 ) + XNORM = MAX( ABS( X( 1, 1 ) ), ABS( X( 2, 1 ) ) ) + END IF + RETURN +* +* 2 by 2: +* op[TL11 TL12]*[X11 X12] +ISGN* [X11 X12]*op[TR11 TR12] = [B11 B12] +* [TL21 TL22] [X21 X22] [X21 X22] [TR21 TR22] [B21 B22] +* +* Solve equivalent 4 by 4 system using complete pivoting. +* Set pivots less than SMIN to SMIN. +* + 50 CONTINUE + SMIN = MAX( ABS( TR( 1, 1 ) ), ABS( TR( 1, 2 ) ), + $ ABS( TR( 2, 1 ) ), ABS( TR( 2, 2 ) ) ) + SMIN = MAX( SMIN, ABS( TL( 1, 1 ) ), ABS( TL( 1, 2 ) ), + $ ABS( TL( 2, 1 ) ), ABS( TL( 2, 2 ) ) ) + SMIN = MAX( EPS*SMIN, SMLNUM ) + BTMP( 1 ) = ZERO + CALL DCOPY( 16, BTMP, 0, T16, 1 ) + T16( 1, 1 ) = TL( 1, 1 ) + SGN*TR( 1, 1 ) + T16( 2, 2 ) = TL( 2, 2 ) + SGN*TR( 1, 1 ) + T16( 3, 3 ) = TL( 1, 1 ) + SGN*TR( 2, 2 ) + T16( 4, 4 ) = TL( 2, 2 ) + SGN*TR( 2, 2 ) + IF( LTRANL ) THEN + T16( 1, 2 ) = TL( 2, 1 ) + T16( 2, 1 ) = TL( 1, 2 ) + T16( 3, 4 ) = TL( 2, 1 ) + T16( 4, 3 ) = TL( 1, 2 ) + ELSE + T16( 1, 2 ) = TL( 1, 2 ) + T16( 2, 1 ) = TL( 2, 1 ) + T16( 3, 4 ) = TL( 1, 2 ) + T16( 4, 3 ) = TL( 2, 1 ) + END IF + IF( LTRANR ) THEN + T16( 1, 3 ) = SGN*TR( 1, 2 ) + T16( 2, 4 ) = SGN*TR( 1, 2 ) + T16( 3, 1 ) = SGN*TR( 2, 1 ) + T16( 4, 2 ) = SGN*TR( 2, 1 ) + ELSE + T16( 1, 3 ) = SGN*TR( 2, 1 ) + T16( 2, 4 ) = SGN*TR( 2, 1 ) + T16( 3, 1 ) = SGN*TR( 1, 2 ) + T16( 4, 2 ) = SGN*TR( 1, 2 ) + END IF + BTMP( 1 ) = B( 1, 1 ) + BTMP( 2 ) = B( 2, 1 ) + BTMP( 3 ) = B( 1, 2 ) + BTMP( 4 ) = B( 2, 2 ) +* +* Perform elimination +* + DO 100 I = 1, 3 + XMAX = ZERO + DO 70 IP = I, 4 + DO 60 JP = I, 4 + IF( ABS( T16( IP, JP ) ).GE.XMAX ) THEN + XMAX = ABS( T16( IP, JP ) ) + IPSV = IP + JPSV = JP + END IF + 60 CONTINUE + 70 CONTINUE + IF( IPSV.NE.I ) THEN + CALL DSWAP( 4, T16( IPSV, 1 ), 4, T16( I, 1 ), 4 ) + TEMP = BTMP( I ) + BTMP( I ) = BTMP( IPSV ) + BTMP( IPSV ) = TEMP + END IF + IF( JPSV.NE.I ) + $ CALL DSWAP( 4, T16( 1, JPSV ), 1, T16( 1, I ), 1 ) + JPIV( I ) = JPSV + IF( ABS( T16( I, I ) ).LT.SMIN ) THEN + INFO = 1 + T16( I, I ) = SMIN + END IF + DO 90 J = I + 1, 4 + T16( J, I ) = T16( J, I ) / T16( I, I ) + BTMP( J ) = BTMP( J ) - T16( J, I )*BTMP( I ) + DO 80 K = I + 1, 4 + T16( J, K ) = T16( J, K ) - T16( J, I )*T16( I, K ) + 80 CONTINUE + 90 CONTINUE + 100 CONTINUE + IF( ABS( T16( 4, 4 ) ).LT.SMIN ) + $ T16( 4, 4 ) = SMIN + SCALE = ONE + IF( ( EIGHT*SMLNUM )*ABS( BTMP( 1 ) ).GT.ABS( T16( 1, 1 ) ) .OR. + $ ( EIGHT*SMLNUM )*ABS( BTMP( 2 ) ).GT.ABS( T16( 2, 2 ) ) .OR. + $ ( EIGHT*SMLNUM )*ABS( BTMP( 3 ) ).GT.ABS( T16( 3, 3 ) ) .OR. + $ ( EIGHT*SMLNUM )*ABS( BTMP( 4 ) ).GT.ABS( T16( 4, 4 ) ) ) THEN + SCALE = ( ONE / EIGHT ) / MAX( ABS( BTMP( 1 ) ), + $ ABS( BTMP( 2 ) ), ABS( BTMP( 3 ) ), ABS( BTMP( 4 ) ) ) + BTMP( 1 ) = BTMP( 1 )*SCALE + BTMP( 2 ) = BTMP( 2 )*SCALE + BTMP( 3 ) = BTMP( 3 )*SCALE + BTMP( 4 ) = BTMP( 4 )*SCALE + END IF + DO 120 I = 1, 4 + K = 5 - I + TEMP = ONE / T16( K, K ) + TMP( K ) = BTMP( K )*TEMP + DO 110 J = K + 1, 4 + TMP( K ) = TMP( K ) - ( TEMP*T16( K, J ) )*TMP( J ) + 110 CONTINUE + 120 CONTINUE + DO 130 I = 1, 3 + IF( JPIV( 4-I ).NE.4-I ) THEN + TEMP = TMP( 4-I ) + TMP( 4-I ) = TMP( JPIV( 4-I ) ) + TMP( JPIV( 4-I ) ) = TEMP + END IF + 130 CONTINUE + X( 1, 1 ) = TMP( 1 ) + X( 2, 1 ) = TMP( 2 ) + X( 1, 2 ) = TMP( 3 ) + X( 2, 2 ) = TMP( 4 ) + XNORM = MAX( ABS( TMP( 1 ) )+ABS( TMP( 3 ) ), + $ ABS( TMP( 2 ) )+ABS( TMP( 4 ) ) ) + RETURN +* +* End of DLASY2 +* + END diff --git a/dep/lapack/dlatrd.f b/dep/lapack/dlatrd.f new file mode 100644 index 00000000..27bf9b98 --- /dev/null +++ b/dep/lapack/dlatrd.f @@ -0,0 +1,258 @@ + SUBROUTINE DLATRD( UPLO, N, NB, A, LDA, E, TAU, W, LDW ) +* +* -- LAPACK auxiliary routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, LDW, N, NB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), E( * ), TAU( * ), W( LDW, * ) +* .. +* +* Purpose +* ======= +* +* DLATRD reduces NB rows and columns of a real symmetric matrix A to +* symmetric tridiagonal form by an orthogonal similarity +* transformation Q' * A * Q, and returns the matrices V and W which are +* needed to apply the transformation to the unreduced part of A. +* +* If UPLO = 'U', DLATRD reduces the last NB rows and columns of a +* matrix, of which the upper triangle is supplied; +* if UPLO = 'L', DLATRD reduces the first NB rows and columns of a +* matrix, of which the lower triangle is supplied. +* +* This is an auxiliary routine called by DSYTRD. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* symmetric matrix A is stored: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the matrix A. +* +* NB (input) INTEGER +* The number of rows and columns to be reduced. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the symmetric matrix A. If UPLO = 'U', the leading +* n-by-n upper triangular part of A contains the upper +* triangular part of the matrix A, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading n-by-n lower triangular part of A contains the lower +* triangular part of the matrix A, and the strictly upper +* triangular part of A is not referenced. +* On exit: +* if UPLO = 'U', the last NB columns have been reduced to +* tridiagonal form, with the diagonal elements overwriting +* the diagonal elements of A; the elements above the diagonal +* with the array TAU, represent the orthogonal matrix Q as a +* product of elementary reflectors; +* if UPLO = 'L', the first NB columns have been reduced to +* tridiagonal form, with the diagonal elements overwriting +* the diagonal elements of A; the elements below the diagonal +* with the array TAU, represent the orthogonal matrix Q as a +* product of elementary reflectors. +* See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= (1,N). +* +* E (output) DOUBLE PRECISION array, dimension (N-1) +* If UPLO = 'U', E(n-nb:n-1) contains the superdiagonal +* elements of the last NB columns of the reduced matrix; +* if UPLO = 'L', E(1:nb) contains the subdiagonal elements of +* the first NB columns of the reduced matrix. +* +* TAU (output) DOUBLE PRECISION array, dimension (N-1) +* The scalar factors of the elementary reflectors, stored in +* TAU(n-nb:n-1) if UPLO = 'U', and in TAU(1:nb) if UPLO = 'L'. +* See Further Details. +* +* W (output) DOUBLE PRECISION array, dimension (LDW,NB) +* The n-by-nb matrix W required to update the unreduced part +* of A. +* +* LDW (input) INTEGER +* The leading dimension of the array W. LDW >= max(1,N). +* +* Further Details +* =============== +* +* If UPLO = 'U', the matrix Q is represented as a product of elementary +* reflectors +* +* Q = H(n) H(n-1) . . . H(n-nb+1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(i:n) = 0 and v(i-1) = 1; v(1:i-1) is stored on exit in A(1:i-1,i), +* and tau in TAU(i-1). +* +* If UPLO = 'L', the matrix Q is represented as a product of elementary +* reflectors +* +* Q = H(1) H(2) . . . H(nb). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(1:i) = 0 and v(i+1) = 1; v(i+1:n) is stored on exit in A(i+1:n,i), +* and tau in TAU(i). +* +* The elements of the vectors v together form the n-by-nb matrix V +* which is needed, with W, to apply the transformation to the unreduced +* part of the matrix, using a symmetric rank-2k update of the form: +* A := A - V*W' - W*V'. +* +* The contents of A on exit are illustrated by the following examples +* with n = 5 and nb = 2: +* +* if UPLO = 'U': if UPLO = 'L': +* +* ( a a a v4 v5 ) ( d ) +* ( a a v4 v5 ) ( 1 d ) +* ( a 1 v5 ) ( v1 1 a ) +* ( d 1 ) ( v1 v2 a a ) +* ( d ) ( v1 v2 a a a ) +* +* where d denotes a diagonal element of the reduced matrix, a denotes +* an element of the original matrix that is unchanged, and vi denotes +* an element of the vector defining H(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, HALF + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, HALF = 0.5D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, IW + DOUBLE PRECISION ALPHA +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DGEMV, DLARFG, DSCAL, DSYMV +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DDOT + EXTERNAL LSAME, DDOT +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.LE.0 ) + $ RETURN +* + IF( LSAME( UPLO, 'U' ) ) THEN +* +* Reduce last NB columns of upper triangle +* + DO 10 I = N, N - NB + 1, -1 + IW = I - N + NB + IF( I.LT.N ) THEN +* +* Update A(1:i,i) +* + CALL DGEMV( 'No transpose', I, N-I, -ONE, A( 1, I+1 ), + $ LDA, W( I, IW+1 ), LDW, ONE, A( 1, I ), 1 ) + CALL DGEMV( 'No transpose', I, N-I, -ONE, W( 1, IW+1 ), + $ LDW, A( I, I+1 ), LDA, ONE, A( 1, I ), 1 ) + END IF + IF( I.GT.1 ) THEN +* +* Generate elementary reflector H(i) to annihilate +* A(1:i-2,i) +* + CALL DLARFG( I-1, A( I-1, I ), A( 1, I ), 1, TAU( I-1 ) ) + E( I-1 ) = A( I-1, I ) + A( I-1, I ) = ONE +* +* Compute W(1:i-1,i) +* + CALL DSYMV( 'Upper', I-1, ONE, A, LDA, A( 1, I ), 1, + $ ZERO, W( 1, IW ), 1 ) + IF( I.LT.N ) THEN + CALL DGEMV( 'Transpose', I-1, N-I, ONE, W( 1, IW+1 ), + $ LDW, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 ) + CALL DGEMV( 'No transpose', I-1, N-I, -ONE, + $ A( 1, I+1 ), LDA, W( I+1, IW ), 1, ONE, + $ W( 1, IW ), 1 ) + CALL DGEMV( 'Transpose', I-1, N-I, ONE, A( 1, I+1 ), + $ LDA, A( 1, I ), 1, ZERO, W( I+1, IW ), 1 ) + CALL DGEMV( 'No transpose', I-1, N-I, -ONE, + $ W( 1, IW+1 ), LDW, W( I+1, IW ), 1, ONE, + $ W( 1, IW ), 1 ) + END IF + CALL DSCAL( I-1, TAU( I-1 ), W( 1, IW ), 1 ) + ALPHA = -HALF*TAU( I-1 )*DDOT( I-1, W( 1, IW ), 1, + $ A( 1, I ), 1 ) + CALL DAXPY( I-1, ALPHA, A( 1, I ), 1, W( 1, IW ), 1 ) + END IF +* + 10 CONTINUE + ELSE +* +* Reduce first NB columns of lower triangle +* + DO 20 I = 1, NB +* +* Update A(i:n,i) +* + CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, A( I, 1 ), + $ LDA, W( I, 1 ), LDW, ONE, A( I, I ), 1 ) + CALL DGEMV( 'No transpose', N-I+1, I-1, -ONE, W( I, 1 ), + $ LDW, A( I, 1 ), LDA, ONE, A( I, I ), 1 ) + IF( I.LT.N ) THEN +* +* Generate elementary reflector H(i) to annihilate +* A(i+2:n,i) +* + CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1, + $ TAU( I ) ) + E( I ) = A( I+1, I ) + A( I+1, I ) = ONE +* +* Compute W(i+1:n,i) +* + CALL DSYMV( 'Lower', N-I, ONE, A( I+1, I+1 ), LDA, + $ A( I+1, I ), 1, ZERO, W( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-I, I-1, ONE, W( I+1, 1 ), LDW, + $ A( I+1, I ), 1, ZERO, W( 1, I ), 1 ) + CALL DGEMV( 'No transpose', N-I, I-1, -ONE, A( I+1, 1 ), + $ LDA, W( 1, I ), 1, ONE, W( I+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-I, I-1, ONE, A( I+1, 1 ), LDA, + $ A( I+1, I ), 1, ZERO, W( 1, I ), 1 ) + CALL DGEMV( 'No transpose', N-I, I-1, -ONE, W( I+1, 1 ), + $ LDW, W( 1, I ), 1, ONE, W( I+1, I ), 1 ) + CALL DSCAL( N-I, TAU( I ), W( I+1, I ), 1 ) + ALPHA = -HALF*TAU( I )*DDOT( N-I, W( I+1, I ), 1, + $ A( I+1, I ), 1 ) + CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, W( I+1, I ), 1 ) + END IF +* + 20 CONTINUE + END IF +* + RETURN +* +* End of DLATRD +* + END diff --git a/dep/lapack/dlauu2.f b/dep/lapack/dlauu2.f new file mode 100644 index 00000000..e800acb2 --- /dev/null +++ b/dep/lapack/dlauu2.f @@ -0,0 +1,135 @@ + SUBROUTINE DLAUU2( UPLO, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DLAUU2 computes the product U * U' or L' * L, where the triangular +* factor U or L is stored in the upper or lower triangular part of +* the array A. +* +* If UPLO = 'U' or 'u' then the upper triangle of the result is stored, +* overwriting the factor U in A. +* If UPLO = 'L' or 'l' then the lower triangle of the result is stored, +* overwriting the factor L in A. +* +* This is the unblocked form of the algorithm, calling Level 2 BLAS. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the triangular factor stored in the array A +* is upper or lower triangular: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the triangular factor U or L. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the triangular factor U or L. +* On exit, if UPLO = 'U', the upper triangle of A is +* overwritten with the upper triangle of the product U * U'; +* if UPLO = 'L', the lower triangle of A is overwritten with +* the lower triangle of the product L' * L. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER I + DOUBLE PRECISION AII +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DDOT + EXTERNAL LSAME, DDOT +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DSCAL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLAUU2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + IF( UPPER ) THEN +* +* Compute the product U * U'. +* + DO 10 I = 1, N + AII = A( I, I ) + IF( I.LT.N ) THEN + A( I, I ) = DDOT( N-I+1, A( I, I ), LDA, A( I, I ), LDA ) + CALL DGEMV( 'No transpose', I-1, N-I, ONE, A( 1, I+1 ), + $ LDA, A( I, I+1 ), LDA, AII, A( 1, I ), 1 ) + ELSE + CALL DSCAL( I, AII, A( 1, I ), 1 ) + END IF + 10 CONTINUE +* + ELSE +* +* Compute the product L' * L. +* + DO 20 I = 1, N + AII = A( I, I ) + IF( I.LT.N ) THEN + A( I, I ) = DDOT( N-I+1, A( I, I ), 1, A( I, I ), 1 ) + CALL DGEMV( 'Transpose', N-I, I-1, ONE, A( I+1, 1 ), LDA, + $ A( I+1, I ), 1, AII, A( I, 1 ), LDA ) + ELSE + CALL DSCAL( I, AII, A( I, 1 ), LDA ) + END IF + 20 CONTINUE + END IF +* + RETURN +* +* End of DLAUU2 +* + END diff --git a/dep/lapack/dlauum.f b/dep/lapack/dlauum.f new file mode 100644 index 00000000..ea93f9a2 --- /dev/null +++ b/dep/lapack/dlauum.f @@ -0,0 +1,155 @@ + SUBROUTINE DLAUUM( UPLO, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DLAUUM computes the product U * U' or L' * L, where the triangular +* factor U or L is stored in the upper or lower triangular part of +* the array A. +* +* If UPLO = 'U' or 'u' then the upper triangle of the result is stored, +* overwriting the factor U in A. +* If UPLO = 'L' or 'l' then the lower triangle of the result is stored, +* overwriting the factor L in A. +* +* This is the blocked form of the algorithm, calling Level 3 BLAS. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the triangular factor stored in the array A +* is upper or lower triangular: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the triangular factor U or L. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the triangular factor U or L. +* On exit, if UPLO = 'U', the upper triangle of A is +* overwritten with the upper triangle of the product U * U'; +* if UPLO = 'L', the lower triangle of A is overwritten with +* the lower triangle of the product L' * L. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER I, IB, NB +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DLAUU2, DSYRK, DTRMM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLAUUM', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment. +* + NB = ILAENV( 1, 'DLAUUM', UPLO, N, -1, -1, -1 ) +* + IF( NB.LE.1 .OR. NB.GE.N ) THEN +* +* Use unblocked code +* + CALL DLAUU2( UPLO, N, A, LDA, INFO ) + ELSE +* +* Use blocked code +* + IF( UPPER ) THEN +* +* Compute the product U * U'. +* + DO 10 I = 1, N, NB + IB = MIN( NB, N-I+1 ) + CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Non-unit', + $ I-1, IB, ONE, A( I, I ), LDA, A( 1, I ), + $ LDA ) + CALL DLAUU2( 'Upper', IB, A( I, I ), LDA, INFO ) + IF( I+IB.LE.N ) THEN + CALL DGEMM( 'No transpose', 'Transpose', I-1, IB, + $ N-I-IB+1, ONE, A( 1, I+IB ), LDA, + $ A( I, I+IB ), LDA, ONE, A( 1, I ), LDA ) + CALL DSYRK( 'Upper', 'No transpose', IB, N-I-IB+1, + $ ONE, A( I, I+IB ), LDA, ONE, A( I, I ), + $ LDA ) + END IF + 10 CONTINUE + ELSE +* +* Compute the product L' * L. +* + DO 20 I = 1, N, NB + IB = MIN( NB, N-I+1 ) + CALL DTRMM( 'Left', 'Lower', 'Transpose', 'Non-unit', IB, + $ I-1, ONE, A( I, I ), LDA, A( I, 1 ), LDA ) + CALL DLAUU2( 'Lower', IB, A( I, I ), LDA, INFO ) + IF( I+IB.LE.N ) THEN + CALL DGEMM( 'Transpose', 'No transpose', IB, I-1, + $ N-I-IB+1, ONE, A( I+IB, I ), LDA, + $ A( I+IB, 1 ), LDA, ONE, A( I, 1 ), LDA ) + CALL DSYRK( 'Lower', 'Transpose', IB, N-I-IB+1, ONE, + $ A( I+IB, I ), LDA, ONE, A( I, I ), LDA ) + END IF + 20 CONTINUE + END IF + END IF +* + RETURN +* +* End of DLAUUM +* + END diff --git a/dep/lapack/dorg2l.f b/dep/lapack/dorg2l.f new file mode 100644 index 00000000..a20965fd --- /dev/null +++ b/dep/lapack/dorg2l.f @@ -0,0 +1,127 @@ + SUBROUTINE DORG2L( M, N, K, A, LDA, TAU, WORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, K, LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORG2L generates an m by n real matrix Q with orthonormal columns, +* which is defined as the last n columns of a product of k elementary +* reflectors of order m +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGEQLF. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix Q. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q. M >= N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines the +* matrix Q. N >= K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the (n-k+i)-th column must contain the vector which +* defines the elementary reflector H(i), for i = 1,2,...,k, as +* returned by DGEQLF in the last k columns of its array +* argument A. +* On exit, the m by n matrix Q. +* +* LDA (input) INTEGER +* The first dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQLF. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument has an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, II, J, L +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DSCAL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 .OR. N.GT.M ) THEN + INFO = -2 + ELSE IF( K.LT.0 .OR. K.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORG2L', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.0 ) + $ RETURN +* +* Initialise columns 1:n-k to columns of the unit matrix +* + DO 20 J = 1, N - K + DO 10 L = 1, M + A( L, J ) = ZERO + 10 CONTINUE + A( M-N+J, J ) = ONE + 20 CONTINUE +* + DO 40 I = 1, K + II = N - K + I +* +* Apply H(i) to A(1:m-k+i,1:n-k+i) from the left +* + A( M-N+II, II ) = ONE + CALL DLARF( 'Left', M-N+II, II-1, A( 1, II ), 1, TAU( I ), A, + $ LDA, WORK ) + CALL DSCAL( M-N+II-1, -TAU( I ), A( 1, II ), 1 ) + A( M-N+II, II ) = ONE - TAU( I ) +* +* Set A(m-k+i+1:m,n-k+i) to zero +* + DO 30 L = M - N + II + 1, M + A( L, II ) = ZERO + 30 CONTINUE + 40 CONTINUE + RETURN +* +* End of DORG2L +* + END diff --git a/dep/lapack/dorg2r.f b/dep/lapack/dorg2r.f new file mode 100644 index 00000000..14a543ef --- /dev/null +++ b/dep/lapack/dorg2r.f @@ -0,0 +1,130 @@ + SUBROUTINE DORG2R( M, N, K, A, LDA, TAU, WORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, K, LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORG2R generates an m by n real matrix Q with orthonormal columns, +* which is defined as the first n columns of a product of k elementary +* reflectors of order m +* +* Q = H(1) H(2) . . . H(k) +* +* as returned by DGEQRF. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix Q. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q. M >= N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines the +* matrix Q. N >= K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the i-th column must contain the vector which +* defines the elementary reflector H(i), for i = 1,2,...,k, as +* returned by DGEQRF in the first k columns of its array +* argument A. +* On exit, the m-by-n matrix Q. +* +* LDA (input) INTEGER +* The first dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQRF. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument has an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J, L +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DSCAL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 .OR. N.GT.M ) THEN + INFO = -2 + ELSE IF( K.LT.0 .OR. K.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORG2R', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.0 ) + $ RETURN +* +* Initialise columns k+1:n to columns of the unit matrix +* + DO 20 J = K + 1, N + DO 10 L = 1, M + A( L, J ) = ZERO + 10 CONTINUE + A( J, J ) = ONE + 20 CONTINUE +* + DO 40 I = K, 1, -1 +* +* Apply H(i) to A(i:m,i:n) from the left +* + IF( I.LT.N ) THEN + A( I, I ) = ONE + CALL DLARF( 'Left', M-I+1, N-I, A( I, I ), 1, TAU( I ), + $ A( I, I+1 ), LDA, WORK ) + END IF + IF( I.LT.M ) + $ CALL DSCAL( M-I, -TAU( I ), A( I+1, I ), 1 ) + A( I, I ) = ONE - TAU( I ) +* +* Set A(1:i-1,i) to zero +* + DO 30 L = 1, I - 1 + A( L, I ) = ZERO + 30 CONTINUE + 40 CONTINUE + RETURN +* +* End of DORG2R +* + END diff --git a/dep/lapack/dorgbr.f b/dep/lapack/dorgbr.f new file mode 100644 index 00000000..2bb421a4 --- /dev/null +++ b/dep/lapack/dorgbr.f @@ -0,0 +1,245 @@ + SUBROUTINE DORGBR( VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER VECT + INTEGER INFO, K, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGBR generates one of the real orthogonal matrices Q or P**T +* determined by DGEBRD when reducing a real matrix A to bidiagonal +* form: A = Q * B * P**T. Q and P**T are defined as products of +* elementary reflectors H(i) or G(i) respectively. +* +* If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q +* is of order M: +* if m >= k, Q = H(1) H(2) . . . H(k) and DORGBR returns the first n +* columns of Q, where m >= n >= k; +* if m < k, Q = H(1) H(2) . . . H(m-1) and DORGBR returns Q as an +* M-by-M matrix. +* +* If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**T +* is of order N: +* if k < n, P**T = G(k) . . . G(2) G(1) and DORGBR returns the first m +* rows of P**T, where n >= m >= k; +* if k >= n, P**T = G(n-1) . . . G(2) G(1) and DORGBR returns P**T as +* an N-by-N matrix. +* +* Arguments +* ========= +* +* VECT (input) CHARACTER*1 +* Specifies whether the matrix Q or the matrix P**T is +* required, as defined in the transformation applied by DGEBRD: +* = 'Q': generate Q; +* = 'P': generate P**T. +* +* M (input) INTEGER +* The number of rows of the matrix Q or P**T to be returned. +* M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q or P**T to be returned. +* N >= 0. +* If VECT = 'Q', M >= N >= min(M,K); +* if VECT = 'P', N >= M >= min(N,K). +* +* K (input) INTEGER +* If VECT = 'Q', the number of columns in the original M-by-K +* matrix reduced by DGEBRD. +* If VECT = 'P', the number of rows in the original K-by-N +* matrix reduced by DGEBRD. +* K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the vectors which define the elementary reflectors, +* as returned by DGEBRD. +* On exit, the M-by-N matrix Q or P**T. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension +* (min(M,K)) if VECT = 'Q' +* (min(N,K)) if VECT = 'P' +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i) or G(i), which determines Q or P**T, as +* returned by DGEBRD in its array argument TAUQ or TAUP. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,min(M,N)). +* For optimum performance LWORK >= min(M,N)*NB, where NB +* is the optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY, WANTQ + INTEGER I, IINFO, J, LWKOPT, MN, NB +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DORGLQ, DORGQR, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + WANTQ = LSAME( VECT, 'Q' ) + MN = MIN( M, N ) + LQUERY = ( LWORK.EQ.-1 ) + IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'P' ) ) THEN + INFO = -1 + ELSE IF( M.LT.0 ) THEN + INFO = -2 + ELSE IF( N.LT.0 .OR. ( WANTQ .AND. ( N.GT.M .OR. N.LT.MIN( M, + $ K ) ) ) .OR. ( .NOT.WANTQ .AND. ( M.GT.N .OR. M.LT. + $ MIN( N, K ) ) ) ) THEN + INFO = -3 + ELSE IF( K.LT.0 ) THEN + INFO = -4 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -6 + ELSE IF( LWORK.LT.MAX( 1, MN ) .AND. .NOT.LQUERY ) THEN + INFO = -9 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( WANTQ ) THEN + NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 ) + ELSE + NB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 ) + END IF + LWKOPT = MAX( 1, MN )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGBR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + IF( WANTQ ) THEN +* +* Form Q, determined by a call to DGEBRD to reduce an m-by-k +* matrix +* + IF( M.GE.K ) THEN +* +* If m >= k, assume m >= n >= k +* + CALL DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, IINFO ) +* + ELSE +* +* If m < k, assume m = n +* +* Shift the vectors which define the elementary reflectors one +* column to the right, and set the first row and column of Q +* to those of the unit matrix +* + DO 20 J = M, 2, -1 + A( 1, J ) = ZERO + DO 10 I = J + 1, M + A( I, J ) = A( I, J-1 ) + 10 CONTINUE + 20 CONTINUE + A( 1, 1 ) = ONE + DO 30 I = 2, M + A( I, 1 ) = ZERO + 30 CONTINUE + IF( M.GT.1 ) THEN +* +* Form Q(2:m,2:m) +* + CALL DORGQR( M-1, M-1, M-1, A( 2, 2 ), LDA, TAU, WORK, + $ LWORK, IINFO ) + END IF + END IF + ELSE +* +* Form P**T, determined by a call to DGEBRD to reduce a k-by-n +* matrix +* + IF( K.LT.N ) THEN +* +* If k < n, assume k <= m <= n +* + CALL DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, IINFO ) +* + ELSE +* +* If k >= n, assume m = n +* +* Shift the vectors which define the elementary reflectors one +* row downward, and set the first row and column of P**T to +* those of the unit matrix +* + A( 1, 1 ) = ONE + DO 40 I = 2, N + A( I, 1 ) = ZERO + 40 CONTINUE + DO 60 J = 2, N + DO 50 I = J - 1, 2, -1 + A( I, J ) = A( I-1, J ) + 50 CONTINUE + A( 1, J ) = ZERO + 60 CONTINUE + IF( N.GT.1 ) THEN +* +* Form P**T(2:n,2:n) +* + CALL DORGLQ( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK, + $ LWORK, IINFO ) + END IF + END IF + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORGBR +* + END diff --git a/dep/lapack/dorghr.f b/dep/lapack/dorghr.f new file mode 100644 index 00000000..41c11280 --- /dev/null +++ b/dep/lapack/dorghr.f @@ -0,0 +1,164 @@ + SUBROUTINE DORGHR( N, ILO, IHI, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, INFO, LDA, LWORK, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGHR generates a real orthogonal matrix Q which is defined as the +* product of IHI-ILO elementary reflectors of order N, as returned by +* DGEHRD: +* +* Q = H(ilo) H(ilo+1) . . . H(ihi-1). +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix Q. N >= 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* ILO and IHI must have the same values as in the previous call +* of DGEHRD. Q is equal to the unit matrix except in the +* submatrix Q(ilo+1:ihi,ilo+1:ihi). +* 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the vectors which define the elementary reflectors, +* as returned by DGEHRD. +* On exit, the N-by-N orthogonal matrix Q. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* TAU (input) DOUBLE PRECISION array, dimension (N-1) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEHRD. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= IHI-ILO. +* For optimum performance LWORK >= (IHI-ILO)*NB, where NB is +* the optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IINFO, J, LWKOPT, NB, NH +* .. +* .. External Subroutines .. + EXTERNAL DORGQR, XERBLA +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + NH = IHI - ILO + LQUERY = ( LWORK.EQ.-1 ) + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, N ) ) THEN + INFO = -2 + ELSE IF( IHI.LT.MIN( ILO, N ) .OR. IHI.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LWORK.LT.MAX( 1, NH ) .AND. .NOT.LQUERY ) THEN + INFO = -8 + END IF +* + IF( INFO.EQ.0 ) THEN + NB = ILAENV( 1, 'DORGQR', ' ', NH, NH, NH, -1 ) + LWKOPT = MAX( 1, NH )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGHR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* +* Shift the vectors which define the elementary reflectors one +* column to the right, and set the first ilo and the last n-ihi +* rows and columns to those of the unit matrix +* + DO 40 J = IHI, ILO + 1, -1 + DO 10 I = 1, J - 1 + A( I, J ) = ZERO + 10 CONTINUE + DO 20 I = J + 1, IHI + A( I, J ) = A( I, J-1 ) + 20 CONTINUE + DO 30 I = IHI + 1, N + A( I, J ) = ZERO + 30 CONTINUE + 40 CONTINUE + DO 60 J = 1, ILO + DO 50 I = 1, N + A( I, J ) = ZERO + 50 CONTINUE + A( J, J ) = ONE + 60 CONTINUE + DO 80 J = IHI + 1, N + DO 70 I = 1, N + A( I, J ) = ZERO + 70 CONTINUE + A( J, J ) = ONE + 80 CONTINUE +* + IF( NH.GT.0 ) THEN +* +* Generate Q(ilo+1:ihi,ilo+1:ihi) +* + CALL DORGQR( NH, NH, NH, A( ILO+1, ILO+1 ), LDA, TAU( ILO ), + $ WORK, LWORK, IINFO ) + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORGHR +* + END diff --git a/dep/lapack/dorgl2.f b/dep/lapack/dorgl2.f new file mode 100644 index 00000000..eac97a3e --- /dev/null +++ b/dep/lapack/dorgl2.f @@ -0,0 +1,134 @@ + SUBROUTINE DORGL2( M, N, K, A, LDA, TAU, WORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, K, LDA, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGL2 generates an m by n real matrix Q with orthonormal rows, +* which is defined as the first m rows of a product of k elementary +* reflectors of order n +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGELQF. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix Q. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q. N >= M. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines the +* matrix Q. M >= K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the i-th row must contain the vector which defines +* the elementary reflector H(i), for i = 1,2,...,k, as returned +* by DGELQF in the first k rows of its array argument A. +* On exit, the m-by-n matrix Q. +* +* LDA (input) INTEGER +* The first dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGELQF. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (M) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument has an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J, L +* .. +* .. External Subroutines .. + EXTERNAL DLARF, DSCAL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.M ) THEN + INFO = -2 + ELSE IF( K.LT.0 .OR. K.GT.M ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGL2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.LE.0 ) + $ RETURN +* + IF( K.LT.M ) THEN +* +* Initialise rows k+1:m to rows of the unit matrix +* + DO 20 J = 1, N + DO 10 L = K + 1, M + A( L, J ) = ZERO + 10 CONTINUE + IF( J.GT.K .AND. J.LE.M ) + $ A( J, J ) = ONE + 20 CONTINUE + END IF +* + DO 40 I = K, 1, -1 +* +* Apply H(i) to A(i:m,i:n) from the right +* + IF( I.LT.N ) THEN + IF( I.LT.M ) THEN + A( I, I ) = ONE + CALL DLARF( 'Right', M-I, N-I+1, A( I, I ), LDA, + $ TAU( I ), A( I+1, I ), LDA, WORK ) + END IF + CALL DSCAL( N-I, -TAU( I ), A( I, I+1 ), LDA ) + END IF + A( I, I ) = ONE - TAU( I ) +* +* Set A(i,1:i-1) to zero +* + DO 30 L = 1, I - 1 + A( I, L ) = ZERO + 30 CONTINUE + 40 CONTINUE + RETURN +* +* End of DORGL2 +* + END diff --git a/dep/lapack/dorglq.f b/dep/lapack/dorglq.f new file mode 100644 index 00000000..bab4269f --- /dev/null +++ b/dep/lapack/dorglq.f @@ -0,0 +1,216 @@ + SUBROUTINE DORGLQ( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + INTEGER INFO, K, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGLQ generates an M-by-N real matrix Q with orthonormal rows, +* which is defined as the first M rows of a product of K elementary +* reflectors of order N +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGELQF. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix Q. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q. N >= M. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines the +* matrix Q. M >= K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the i-th row must contain the vector which defines +* the elementary reflector H(i), for i = 1,2,...,k, as returned +* by DGELQF in the first k rows of its array argument A. +* On exit, the M-by-N matrix Q. +* +* LDA (input) INTEGER +* The first dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGELQF. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,M). +* For optimum performance LWORK >= M*NB, where NB is +* the optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument has an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK, + $ LWKOPT, NB, NBMIN, NX +* .. +* .. External Subroutines .. + EXTERNAL DLARFB, DLARFT, DORGL2, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + NB = ILAENV( 1, 'DORGLQ', ' ', M, N, K, -1 ) + LWKOPT = MAX( 1, M )*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.M ) THEN + INFO = -2 + ELSE IF( K.LT.0 .OR. K.GT.M ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -5 + ELSE IF( LWORK.LT.MAX( 1, M ) .AND. .NOT.LQUERY ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGLQ', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.LE.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NBMIN = 2 + NX = 0 + IWS = M + IF( NB.GT.1 .AND. NB.LT.K ) THEN +* +* Determine when to cross over from blocked to unblocked code. +* + NX = MAX( 0, ILAENV( 3, 'DORGLQ', ' ', M, N, K, -1 ) ) + IF( NX.LT.K ) THEN +* +* Determine if workspace is large enough for blocked code. +* + LDWORK = M + IWS = LDWORK*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: reduce NB and +* determine the minimum value of NB. +* + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DORGLQ', ' ', M, N, K, -1 ) ) + END IF + END IF + END IF +* + IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN +* +* Use blocked code after the last block. +* The first kk rows are handled by the block method. +* + KI = ( ( K-NX-1 ) / NB )*NB + KK = MIN( K, KI+NB ) +* +* Set A(kk+1:m,1:kk) to zero. +* + DO 20 J = 1, KK + DO 10 I = KK + 1, M + A( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + KK = 0 + END IF +* +* Use unblocked code for the last or only block. +* + IF( KK.LT.M ) + $ CALL DORGL2( M-KK, N-KK, K-KK, A( KK+1, KK+1 ), LDA, + $ TAU( KK+1 ), WORK, IINFO ) +* + IF( KK.GT.0 ) THEN +* +* Use blocked code +* + DO 50 I = KI + 1, 1, -NB + IB = MIN( NB, K-I+1 ) + IF( I+IB.LE.M ) THEN +* +* Form the triangular factor of the block reflector +* H = H(i) H(i+1) . . . H(i+ib-1) +* + CALL DLARFT( 'Forward', 'Rowwise', N-I+1, IB, A( I, I ), + $ LDA, TAU( I ), WORK, LDWORK ) +* +* Apply H**T to A(i+ib:m,i:n) from the right +* + CALL DLARFB( 'Right', 'Transpose', 'Forward', 'Rowwise', + $ M-I-IB+1, N-I+1, IB, A( I, I ), LDA, WORK, + $ LDWORK, A( I+IB, I ), LDA, WORK( IB+1 ), + $ LDWORK ) + END IF +* +* Apply H**T to columns i:n of current block +* + CALL DORGL2( IB, N-I+1, IB, A( I, I ), LDA, TAU( I ), WORK, + $ IINFO ) +* +* Set columns 1:i-1 of current block to zero +* + DO 40 J = 1, I - 1 + DO 30 L = I, I + IB - 1 + A( L, J ) = ZERO + 30 CONTINUE + 40 CONTINUE + 50 CONTINUE + END IF +* + WORK( 1 ) = IWS + RETURN +* +* End of DORGLQ +* + END diff --git a/dep/lapack/dorgql.f b/dep/lapack/dorgql.f new file mode 100644 index 00000000..1c4896e9 --- /dev/null +++ b/dep/lapack/dorgql.f @@ -0,0 +1,222 @@ + SUBROUTINE DORGQL( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, K, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGQL generates an M-by-N real matrix Q with orthonormal columns, +* which is defined as the last N columns of a product of K elementary +* reflectors of order M +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGEQLF. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix Q. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q. M >= N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines the +* matrix Q. N >= K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the (n-k+i)-th column must contain the vector which +* defines the elementary reflector H(i), for i = 1,2,...,k, as +* returned by DGEQLF in the last k columns of its array +* argument A. +* On exit, the M-by-N matrix Q. +* +* LDA (input) INTEGER +* The first dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQLF. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,N). +* For optimum performance LWORK >= N*NB, where NB is the +* optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument has an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IB, IINFO, IWS, J, KK, L, LDWORK, LWKOPT, + $ NB, NBMIN, NX +* .. +* .. External Subroutines .. + EXTERNAL DLARFB, DLARFT, DORG2L, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LQUERY = ( LWORK.EQ.-1 ) + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 .OR. N.GT.M ) THEN + INFO = -2 + ELSE IF( K.LT.0 .OR. K.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -5 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( N.EQ.0 ) THEN + LWKOPT = 1 + ELSE + NB = ILAENV( 1, 'DORGQL', ' ', M, N, K, -1 ) + LWKOPT = N*NB + END IF + WORK( 1 ) = LWKOPT +* + IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -8 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGQL', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.0 ) THEN + RETURN + END IF +* + NBMIN = 2 + NX = 0 + IWS = N + IF( NB.GT.1 .AND. NB.LT.K ) THEN +* +* Determine when to cross over from blocked to unblocked code. +* + NX = MAX( 0, ILAENV( 3, 'DORGQL', ' ', M, N, K, -1 ) ) + IF( NX.LT.K ) THEN +* +* Determine if workspace is large enough for blocked code. +* + LDWORK = N + IWS = LDWORK*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: reduce NB and +* determine the minimum value of NB. +* + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DORGQL', ' ', M, N, K, -1 ) ) + END IF + END IF + END IF +* + IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN +* +* Use blocked code after the first block. +* The last kk columns are handled by the block method. +* + KK = MIN( K, ( ( K-NX+NB-1 ) / NB )*NB ) +* +* Set A(m-kk+1:m,1:n-kk) to zero. +* + DO 20 J = 1, N - KK + DO 10 I = M - KK + 1, M + A( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + KK = 0 + END IF +* +* Use unblocked code for the first or only block. +* + CALL DORG2L( M-KK, N-KK, K-KK, A, LDA, TAU, WORK, IINFO ) +* + IF( KK.GT.0 ) THEN +* +* Use blocked code +* + DO 50 I = K - KK + 1, K, NB + IB = MIN( NB, K-I+1 ) + IF( N-K+I.GT.1 ) THEN +* +* Form the triangular factor of the block reflector +* H = H(i+ib-1) . . . H(i+1) H(i) +* + CALL DLARFT( 'Backward', 'Columnwise', M-K+I+IB-1, IB, + $ A( 1, N-K+I ), LDA, TAU( I ), WORK, LDWORK ) +* +* Apply H to A(1:m-k+i+ib-1,1:n-k+i-1) from the left +* + CALL DLARFB( 'Left', 'No transpose', 'Backward', + $ 'Columnwise', M-K+I+IB-1, N-K+I-1, IB, + $ A( 1, N-K+I ), LDA, WORK, LDWORK, A, LDA, + $ WORK( IB+1 ), LDWORK ) + END IF +* +* Apply H to rows 1:m-k+i+ib-1 of current block +* + CALL DORG2L( M-K+I+IB-1, IB, IB, A( 1, N-K+I ), LDA, + $ TAU( I ), WORK, IINFO ) +* +* Set rows m-k+i+ib:m of current block to zero +* + DO 40 J = N - K + I, N - K + I + IB - 1 + DO 30 L = M - K + I + IB, M + A( L, J ) = ZERO + 30 CONTINUE + 40 CONTINUE + 50 CONTINUE + END IF +* + WORK( 1 ) = IWS + RETURN +* +* End of DORGQL +* + END diff --git a/dep/lapack/dorgqr.f b/dep/lapack/dorgqr.f new file mode 100644 index 00000000..a080f0dc --- /dev/null +++ b/dep/lapack/dorgqr.f @@ -0,0 +1,217 @@ + SUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, K, LDA, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGQR generates an M-by-N real matrix Q with orthonormal columns, +* which is defined as the first N columns of a product of K elementary +* reflectors of order M +* +* Q = H(1) H(2) . . . H(k) +* +* as returned by DGEQRF. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix Q. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix Q. M >= N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines the +* matrix Q. N >= K >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the i-th column must contain the vector which +* defines the elementary reflector H(i), for i = 1,2,...,k, as +* returned by DGEQRF in the first k columns of its array +* argument A. +* On exit, the M-by-N matrix Q. +* +* LDA (input) INTEGER +* The first dimension of the array A. LDA >= max(1,M). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQRF. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,N). +* For optimum performance LWORK >= N*NB, where NB is the +* optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument has an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IB, IINFO, IWS, J, KI, KK, L, LDWORK, + $ LWKOPT, NB, NBMIN, NX +* .. +* .. External Subroutines .. + EXTERNAL DLARFB, DLARFT, DORG2R, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + NB = ILAENV( 1, 'DORGQR', ' ', M, N, K, -1 ) + LWKOPT = MAX( 1, N )*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 .OR. N.GT.M ) THEN + INFO = -2 + ELSE IF( K.LT.0 .OR. K.GT.N ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -5 + ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGQR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NBMIN = 2 + NX = 0 + IWS = N + IF( NB.GT.1 .AND. NB.LT.K ) THEN +* +* Determine when to cross over from blocked to unblocked code. +* + NX = MAX( 0, ILAENV( 3, 'DORGQR', ' ', M, N, K, -1 ) ) + IF( NX.LT.K ) THEN +* +* Determine if workspace is large enough for blocked code. +* + LDWORK = N + IWS = LDWORK*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: reduce NB and +* determine the minimum value of NB. +* + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DORGQR', ' ', M, N, K, -1 ) ) + END IF + END IF + END IF +* + IF( NB.GE.NBMIN .AND. NB.LT.K .AND. NX.LT.K ) THEN +* +* Use blocked code after the last block. +* The first kk columns are handled by the block method. +* + KI = ( ( K-NX-1 ) / NB )*NB + KK = MIN( K, KI+NB ) +* +* Set A(1:kk,kk+1:n) to zero. +* + DO 20 J = KK + 1, N + DO 10 I = 1, KK + A( I, J ) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + KK = 0 + END IF +* +* Use unblocked code for the last or only block. +* + IF( KK.LT.N ) + $ CALL DORG2R( M-KK, N-KK, K-KK, A( KK+1, KK+1 ), LDA, + $ TAU( KK+1 ), WORK, IINFO ) +* + IF( KK.GT.0 ) THEN +* +* Use blocked code +* + DO 50 I = KI + 1, 1, -NB + IB = MIN( NB, K-I+1 ) + IF( I+IB.LE.N ) THEN +* +* Form the triangular factor of the block reflector +* H = H(i) H(i+1) . . . H(i+ib-1) +* + CALL DLARFT( 'Forward', 'Columnwise', M-I+1, IB, + $ A( I, I ), LDA, TAU( I ), WORK, LDWORK ) +* +* Apply H to A(i:m,i+ib:n) from the left +* + CALL DLARFB( 'Left', 'No transpose', 'Forward', + $ 'Columnwise', M-I+1, N-I-IB+1, IB, + $ A( I, I ), LDA, WORK, LDWORK, A( I, I+IB ), + $ LDA, WORK( IB+1 ), LDWORK ) + END IF +* +* Apply H to rows i:m of current block +* + CALL DORG2R( M-I+1, IB, IB, A( I, I ), LDA, TAU( I ), WORK, + $ IINFO ) +* +* Set rows 1:i-1 of current block to zero +* + DO 40 J = I, I + IB - 1 + DO 30 L = 1, I - 1 + A( L, J ) = ZERO + 30 CONTINUE + 40 CONTINUE + 50 CONTINUE + END IF +* + WORK( 1 ) = IWS + RETURN +* +* End of DORGQR +* + END diff --git a/dep/lapack/dorgtr.f b/dep/lapack/dorgtr.f new file mode 100644 index 00000000..4c72d031 --- /dev/null +++ b/dep/lapack/dorgtr.f @@ -0,0 +1,183 @@ + SUBROUTINE DORGTR( UPLO, N, A, LDA, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, LWORK, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORGTR generates a real orthogonal matrix Q which is defined as the +* product of n-1 elementary reflectors of order N, as returned by +* DSYTRD: +* +* if UPLO = 'U', Q = H(n-1) . . . H(2) H(1), +* +* if UPLO = 'L', Q = H(1) H(2) . . . H(n-1). +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A contains elementary reflectors +* from DSYTRD; +* = 'L': Lower triangle of A contains elementary reflectors +* from DSYTRD. +* +* N (input) INTEGER +* The order of the matrix Q. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the vectors which define the elementary reflectors, +* as returned by DSYTRD. +* On exit, the N-by-N orthogonal matrix Q. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* TAU (input) DOUBLE PRECISION array, dimension (N-1) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DSYTRD. +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,N-1). +* For optimum performance LWORK >= (N-1)*NB, where NB is +* the optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY, UPPER + INTEGER I, IINFO, J, LWKOPT, NB +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DORGQL, DORGQR, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LQUERY = ( LWORK.EQ.-1 ) + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( LWORK.LT.MAX( 1, N-1 ) .AND. .NOT.LQUERY ) THEN + INFO = -7 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( UPPER ) THEN + NB = ILAENV( 1, 'DORGQL', ' ', N-1, N-1, N-1, -1 ) + ELSE + NB = ILAENV( 1, 'DORGQR', ' ', N-1, N-1, N-1, -1 ) + END IF + LWKOPT = MAX( 1, N-1 )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORGTR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + IF( UPPER ) THEN +* +* Q was determined by a call to DSYTRD with UPLO = 'U' +* +* Shift the vectors which define the elementary reflectors one +* column to the left, and set the last row and column of Q to +* those of the unit matrix +* + DO 20 J = 1, N - 1 + DO 10 I = 1, J - 1 + A( I, J ) = A( I, J+1 ) + 10 CONTINUE + A( N, J ) = ZERO + 20 CONTINUE + DO 30 I = 1, N - 1 + A( I, N ) = ZERO + 30 CONTINUE + A( N, N ) = ONE +* +* Generate Q(1:n-1,1:n-1) +* + CALL DORGQL( N-1, N-1, N-1, A, LDA, TAU, WORK, LWORK, IINFO ) +* + ELSE +* +* Q was determined by a call to DSYTRD with UPLO = 'L'. +* +* Shift the vectors which define the elementary reflectors one +* column to the right, and set the first row and column of Q to +* those of the unit matrix +* + DO 50 J = N, 2, -1 + A( 1, J ) = ZERO + DO 40 I = J + 1, N + A( I, J ) = A( I, J-1 ) + 40 CONTINUE + 50 CONTINUE + A( 1, 1 ) = ONE + DO 60 I = 2, N + A( I, 1 ) = ZERO + 60 CONTINUE + IF( N.GT.1 ) THEN +* +* Generate Q(2:n,2:n) +* + CALL DORGQR( N-1, N-1, N-1, A( 2, 2 ), LDA, TAU, WORK, + $ LWORK, IINFO ) + END IF + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORGTR +* + END diff --git a/dep/lapack/dorm2l.f b/dep/lapack/dorm2l.f new file mode 100644 index 00000000..27120075 --- /dev/null +++ b/dep/lapack/dorm2l.f @@ -0,0 +1,193 @@ + SUBROUTINE DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER INFO, K, LDA, LDC, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORM2L overwrites the general real m by n matrix C with +* +* Q * C if SIDE = 'L' and TRANS = 'N', or +* +* Q'* C if SIDE = 'L' and TRANS = 'T', or +* +* C * Q if SIDE = 'R' and TRANS = 'N', or +* +* C * Q' if SIDE = 'R' and TRANS = 'T', +* +* where Q is a real orthogonal matrix defined as the product of k +* elementary reflectors +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGEQLF. Q is of order m if SIDE = 'L' and of order n +* if SIDE = 'R'. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q' from the Left +* = 'R': apply Q or Q' from the Right +* +* TRANS (input) CHARACTER*1 +* = 'N': apply Q (No transpose) +* = 'T': apply Q' (Transpose) +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines +* the matrix Q. +* If SIDE = 'L', M >= K >= 0; +* if SIDE = 'R', N >= K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,K) +* The i-th column must contain the vector which defines the +* elementary reflector H(i), for i = 1,2,...,k, as returned by +* DGEQLF in the last k columns of its array argument A. +* A is modified by the routine but restored on exit. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* If SIDE = 'L', LDA >= max(1,M); +* if SIDE = 'R', LDA >= max(1,N). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQLF. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the m by n matrix C. +* On exit, C is overwritten by Q*C or Q'*C or C*Q' or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace) DOUBLE PRECISION array, dimension +* (N) if SIDE = 'L', +* (M) if SIDE = 'R' +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LEFT, NOTRAN + INTEGER I, I1, I2, I3, MI, NI, NQ + DOUBLE PRECISION AII +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLARF, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) +* +* NQ is the order of Q +* + IF( LEFT ) THEN + NQ = M + ELSE + NQ = N + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORM2L', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) + $ RETURN +* + IF( ( LEFT .AND. NOTRAN ) .OR. ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) + $ THEN + I1 = 1 + I2 = K + I3 = 1 + ELSE + I1 = K + I2 = 1 + I3 = -1 + END IF +* + IF( LEFT ) THEN + NI = N + ELSE + MI = M + END IF +* + DO 10 I = I1, I2, I3 + IF( LEFT ) THEN +* +* H(i) is applied to C(1:m-k+i,1:n) +* + MI = M - K + I + ELSE +* +* H(i) is applied to C(1:m,1:n-k+i) +* + NI = N - K + I + END IF +* +* Apply H(i) +* + AII = A( NQ-K+I, I ) + A( NQ-K+I, I ) = ONE + CALL DLARF( SIDE, MI, NI, A( 1, I ), 1, TAU( I ), C, LDC, + $ WORK ) + A( NQ-K+I, I ) = AII + 10 CONTINUE + RETURN +* +* End of DORM2L +* + END diff --git a/dep/lapack/dorm2r.f b/dep/lapack/dorm2r.f new file mode 100644 index 00000000..2dab71a7 --- /dev/null +++ b/dep/lapack/dorm2r.f @@ -0,0 +1,198 @@ + SUBROUTINE DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER INFO, K, LDA, LDC, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORM2R overwrites the general real m by n matrix C with +* +* Q * C if SIDE = 'L' and TRANS = 'N', or +* +* Q**T* C if SIDE = 'L' and TRANS = 'T', or +* +* C * Q if SIDE = 'R' and TRANS = 'N', or +* +* C * Q**T if SIDE = 'R' and TRANS = 'T', +* +* where Q is a real orthogonal matrix defined as the product of k +* elementary reflectors +* +* Q = H(1) H(2) . . . H(k) +* +* as returned by DGEQRF. Q is of order m if SIDE = 'L' and of order n +* if SIDE = 'R'. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left +* = 'R': apply Q or Q**T from the Right +* +* TRANS (input) CHARACTER*1 +* = 'N': apply Q (No transpose) +* = 'T': apply Q**T (Transpose) +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines +* the matrix Q. +* If SIDE = 'L', M >= K >= 0; +* if SIDE = 'R', N >= K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,K) +* The i-th column must contain the vector which defines the +* elementary reflector H(i), for i = 1,2,...,k, as returned by +* DGEQRF in the first k columns of its array argument A. +* A is modified by the routine but restored on exit. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* If SIDE = 'L', LDA >= max(1,M); +* if SIDE = 'R', LDA >= max(1,N). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQRF. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the m by n matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace) DOUBLE PRECISION array, dimension +* (N) if SIDE = 'L', +* (M) if SIDE = 'R' +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LEFT, NOTRAN + INTEGER I, I1, I2, I3, IC, JC, MI, NI, NQ + DOUBLE PRECISION AII +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLARF, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) +* +* NQ is the order of Q +* + IF( LEFT ) THEN + NQ = M + ELSE + NQ = N + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORM2R', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) + $ RETURN +* + IF( ( LEFT .AND. .NOT.NOTRAN ) .OR. ( .NOT.LEFT .AND. NOTRAN ) ) + $ THEN + I1 = 1 + I2 = K + I3 = 1 + ELSE + I1 = K + I2 = 1 + I3 = -1 + END IF +* + IF( LEFT ) THEN + NI = N + JC = 1 + ELSE + MI = M + IC = 1 + END IF +* + DO 10 I = I1, I2, I3 + IF( LEFT ) THEN +* +* H(i) is applied to C(i:m,1:n) +* + MI = M - I + 1 + IC = I + ELSE +* +* H(i) is applied to C(1:m,i:n) +* + NI = N - I + 1 + JC = I + END IF +* +* Apply H(i) +* + AII = A( I, I ) + A( I, I ) = ONE + CALL DLARF( SIDE, MI, NI, A( I, I ), 1, TAU( I ), C( IC, JC ), + $ LDC, WORK ) + A( I, I ) = AII + 10 CONTINUE + RETURN +* +* End of DORM2R +* + END diff --git a/dep/lapack/dormbr.f b/dep/lapack/dormbr.f new file mode 100644 index 00000000..aefc2f92 --- /dev/null +++ b/dep/lapack/dormbr.f @@ -0,0 +1,282 @@ + SUBROUTINE DORMBR( VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, + $ LDC, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS, VECT + INTEGER INFO, K, LDA, LDC, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* If VECT = 'Q', DORMBR overwrites the general real M-by-N matrix C +* with +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': Q * C C * Q +* TRANS = 'T': Q**T * C C * Q**T +* +* If VECT = 'P', DORMBR overwrites the general real M-by-N matrix C +* with +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': P * C C * P +* TRANS = 'T': P**T * C C * P**T +* +* Here Q and P**T are the orthogonal matrices determined by DGEBRD when +* reducing a real matrix A to bidiagonal form: A = Q * B * P**T. Q and +* P**T are defined as products of elementary reflectors H(i) and G(i) +* respectively. +* +* Let nq = m if SIDE = 'L' and nq = n if SIDE = 'R'. Thus nq is the +* order of the orthogonal matrix Q or P**T that is applied. +* +* If VECT = 'Q', A is assumed to have been an NQ-by-K matrix: +* if nq >= k, Q = H(1) H(2) . . . H(k); +* if nq < k, Q = H(1) H(2) . . . H(nq-1). +* +* If VECT = 'P', A is assumed to have been a K-by-NQ matrix: +* if k < nq, P = G(1) G(2) . . . G(k); +* if k >= nq, P = G(1) G(2) . . . G(nq-1). +* +* Arguments +* ========= +* +* VECT (input) CHARACTER*1 +* = 'Q': apply Q or Q**T; +* = 'P': apply P or P**T. +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q, Q**T, P or P**T from the Left; +* = 'R': apply Q, Q**T, P or P**T from the Right. +* +* TRANS (input) CHARACTER*1 +* = 'N': No transpose, apply Q or P; +* = 'T': Transpose, apply Q**T or P**T. +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* If VECT = 'Q', the number of columns in the original +* matrix reduced by DGEBRD. +* If VECT = 'P', the number of rows in the original +* matrix reduced by DGEBRD. +* K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension +* (LDA,min(nq,K)) if VECT = 'Q' +* (LDA,nq) if VECT = 'P' +* The vectors which define the elementary reflectors H(i) and +* G(i), whose products determine the matrices Q and P, as +* returned by DGEBRD. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* If VECT = 'Q', LDA >= max(1,nq); +* if VECT = 'P', LDA >= max(1,min(nq,K)). +* +* TAU (input) DOUBLE PRECISION array, dimension (min(nq,K)) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i) or G(i) which determines Q or P, as returned +* by DGEBRD in the array argument TAUQ or TAUP. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q +* or P*C or P**T*C or C*P or C*P**T. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If SIDE = 'L', LWORK >= max(1,N); +* if SIDE = 'R', LWORK >= max(1,M). +* For optimum performance LWORK >= N*NB if SIDE = 'L', and +* LWORK >= M*NB if SIDE = 'R', where NB is the optimal +* blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL APPLYQ, LEFT, LQUERY, NOTRAN + CHARACTER TRANST + INTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DORMLQ, DORMQR, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + APPLYQ = LSAME( VECT, 'Q' ) + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) + LQUERY = ( LWORK.EQ.-1 ) +* +* NQ is the order of Q or P and NW is the minimum dimension of WORK +* + IF( LEFT ) THEN + NQ = M + NW = N + ELSE + NQ = N + NW = M + END IF + IF( .NOT.APPLYQ .AND. .NOT.LSAME( VECT, 'P' ) ) THEN + INFO = -1 + ELSE IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -2 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -3 + ELSE IF( M.LT.0 ) THEN + INFO = -4 + ELSE IF( N.LT.0 ) THEN + INFO = -5 + ELSE IF( K.LT.0 ) THEN + INFO = -6 + ELSE IF( ( APPLYQ .AND. LDA.LT.MAX( 1, NQ ) ) .OR. + $ ( .NOT.APPLYQ .AND. LDA.LT.MAX( 1, MIN( NQ, K ) ) ) ) + $ THEN + INFO = -8 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -11 + ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THEN + INFO = -13 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( APPLYQ ) THEN + IF( LEFT ) THEN + NB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M-1, N, M-1, + $ -1 ) + ELSE + NB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N-1, N-1, + $ -1 ) + END IF + ELSE + IF( LEFT ) THEN + NB = ILAENV( 1, 'DORMLQ', SIDE // TRANS, M-1, N, M-1, + $ -1 ) + ELSE + NB = ILAENV( 1, 'DORMLQ', SIDE // TRANS, M, N-1, N-1, + $ -1 ) + END IF + END IF + LWKOPT = MAX( 1, NW )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORMBR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + WORK( 1 ) = 1 + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* + IF( APPLYQ ) THEN +* +* Apply Q +* + IF( NQ.GE.K ) THEN +* +* Q was determined by a call to DGEBRD with nq >= k +* + CALL DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, LWORK, IINFO ) + ELSE IF( NQ.GT.1 ) THEN +* +* Q was determined by a call to DGEBRD with nq < k +* + IF( LEFT ) THEN + MI = M - 1 + NI = N + I1 = 2 + I2 = 1 + ELSE + MI = M + NI = N - 1 + I1 = 1 + I2 = 2 + END IF + CALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU, + $ C( I1, I2 ), LDC, WORK, LWORK, IINFO ) + END IF + ELSE +* +* Apply P +* + IF( NOTRAN ) THEN + TRANST = 'T' + ELSE + TRANST = 'N' + END IF + IF( NQ.GT.K ) THEN +* +* P was determined by a call to DGEBRD with nq > k +* + CALL DORMLQ( SIDE, TRANST, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, LWORK, IINFO ) + ELSE IF( NQ.GT.1 ) THEN +* +* P was determined by a call to DGEBRD with nq <= k +* + IF( LEFT ) THEN + MI = M - 1 + NI = N + I1 = 2 + I2 = 1 + ELSE + MI = M + NI = N - 1 + I1 = 1 + I2 = 2 + END IF + CALL DORMLQ( SIDE, TRANST, MI, NI, NQ-1, A( 1, 2 ), LDA, + $ TAU, C( I1, I2 ), LDC, WORK, LWORK, IINFO ) + END IF + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORMBR +* + END diff --git a/dep/lapack/dormhr.f b/dep/lapack/dormhr.f new file mode 100644 index 00000000..c649d6ad --- /dev/null +++ b/dep/lapack/dormhr.f @@ -0,0 +1,202 @@ + SUBROUTINE DORMHR( SIDE, TRANS, M, N, ILO, IHI, A, LDA, TAU, C, + $ LDC, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER IHI, ILO, INFO, LDA, LDC, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORMHR overwrites the general real M-by-N matrix C with +* +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': Q * C C * Q +* TRANS = 'T': Q**T * C C * Q**T +* +* where Q is a real orthogonal matrix of order nq, with nq = m if +* SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of +* IHI-ILO elementary reflectors, as returned by DGEHRD: +* +* Q = H(ilo) H(ilo+1) . . . H(ihi-1). +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left; +* = 'R': apply Q or Q**T from the Right. +* +* TRANS (input) CHARACTER*1 +* = 'N': No transpose, apply Q; +* = 'T': Transpose, apply Q**T. +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* ILO (input) INTEGER +* IHI (input) INTEGER +* ILO and IHI must have the same values as in the previous call +* of DGEHRD. Q is equal to the unit matrix except in the +* submatrix Q(ilo+1:ihi,ilo+1:ihi). +* If SIDE = 'L', then 1 <= ILO <= IHI <= M, if M > 0, and +* ILO = 1 and IHI = 0, if M = 0; +* if SIDE = 'R', then 1 <= ILO <= IHI <= N, if N > 0, and +* ILO = 1 and IHI = 0, if N = 0. +* +* A (input) DOUBLE PRECISION array, dimension +* (LDA,M) if SIDE = 'L' +* (LDA,N) if SIDE = 'R' +* The vectors which define the elementary reflectors, as +* returned by DGEHRD. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'. +* +* TAU (input) DOUBLE PRECISION array, dimension +* (M-1) if SIDE = 'L' +* (N-1) if SIDE = 'R' +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEHRD. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If SIDE = 'L', LWORK >= max(1,N); +* if SIDE = 'R', LWORK >= max(1,M). +* For optimum performance LWORK >= N*NB if SIDE = 'L', and +* LWORK >= M*NB if SIDE = 'R', where NB is the optimal +* blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL LEFT, LQUERY + INTEGER I1, I2, IINFO, LWKOPT, MI, NB, NH, NI, NQ, NW +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DORMQR, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + NH = IHI - ILO + LEFT = LSAME( SIDE, 'L' ) + LQUERY = ( LWORK.EQ.-1 ) +* +* NQ is the order of Q and NW is the minimum dimension of WORK +* + IF( LEFT ) THEN + NQ = M + NW = N + ELSE + NQ = N + NW = M + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'T' ) ) + $ THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( ILO.LT.1 .OR. ILO.GT.MAX( 1, NQ ) ) THEN + INFO = -5 + ELSE IF( IHI.LT.MIN( ILO, NQ ) .OR. IHI.GT.NQ ) THEN + INFO = -6 + ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN + INFO = -8 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -11 + ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THEN + INFO = -13 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( LEFT ) THEN + NB = ILAENV( 1, 'DORMQR', SIDE // TRANS, NH, N, NH, -1 ) + ELSE + NB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, NH, NH, -1 ) + END IF + LWKOPT = MAX( 1, NW )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORMHR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. NH.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + IF( LEFT ) THEN + MI = NH + NI = N + I1 = ILO + 1 + I2 = 1 + ELSE + MI = M + NI = NH + I1 = 1 + I2 = ILO + 1 + END IF +* + CALL DORMQR( SIDE, TRANS, MI, NI, NH, A( ILO+1, ILO ), LDA, + $ TAU( ILO ), C( I1, I2 ), LDC, WORK, LWORK, IINFO ) +* + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORMHR +* + END diff --git a/dep/lapack/dorml2.f b/dep/lapack/dorml2.f new file mode 100644 index 00000000..d2b0a907 --- /dev/null +++ b/dep/lapack/dorml2.f @@ -0,0 +1,198 @@ + SUBROUTINE DORML2( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER INFO, K, LDA, LDC, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORML2 overwrites the general real m by n matrix C with +* +* Q * C if SIDE = 'L' and TRANS = 'N', or +* +* Q**T* C if SIDE = 'L' and TRANS = 'T', or +* +* C * Q if SIDE = 'R' and TRANS = 'N', or +* +* C * Q**T if SIDE = 'R' and TRANS = 'T', +* +* where Q is a real orthogonal matrix defined as the product of k +* elementary reflectors +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGELQF. Q is of order m if SIDE = 'L' and of order n +* if SIDE = 'R'. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left +* = 'R': apply Q or Q**T from the Right +* +* TRANS (input) CHARACTER*1 +* = 'N': apply Q (No transpose) +* = 'T': apply Q**T (Transpose) +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines +* the matrix Q. +* If SIDE = 'L', M >= K >= 0; +* if SIDE = 'R', N >= K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension +* (LDA,M) if SIDE = 'L', +* (LDA,N) if SIDE = 'R' +* The i-th row must contain the vector which defines the +* elementary reflector H(i), for i = 1,2,...,k, as returned by +* DGELQF in the first k rows of its array argument A. +* A is modified by the routine but restored on exit. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,K). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGELQF. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the m by n matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace) DOUBLE PRECISION array, dimension +* (N) if SIDE = 'L', +* (M) if SIDE = 'R' +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LEFT, NOTRAN + INTEGER I, I1, I2, I3, IC, JC, MI, NI, NQ + DOUBLE PRECISION AII +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLARF, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) +* +* NQ is the order of Q +* + IF( LEFT ) THEN + NQ = M + ELSE + NQ = N + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, K ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORML2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) + $ RETURN +* + IF( ( LEFT .AND. NOTRAN ) .OR. ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) + $ THEN + I1 = 1 + I2 = K + I3 = 1 + ELSE + I1 = K + I2 = 1 + I3 = -1 + END IF +* + IF( LEFT ) THEN + NI = N + JC = 1 + ELSE + MI = M + IC = 1 + END IF +* + DO 10 I = I1, I2, I3 + IF( LEFT ) THEN +* +* H(i) is applied to C(i:m,1:n) +* + MI = M - I + 1 + IC = I + ELSE +* +* H(i) is applied to C(1:m,i:n) +* + NI = N - I + 1 + JC = I + END IF +* +* Apply H(i) +* + AII = A( I, I ) + A( I, I ) = ONE + CALL DLARF( SIDE, MI, NI, A( I, I ), LDA, TAU( I ), + $ C( IC, JC ), LDC, WORK ) + A( I, I ) = AII + 10 CONTINUE + RETURN +* +* End of DORML2 +* + END diff --git a/dep/lapack/dormlq.f b/dep/lapack/dormlq.f new file mode 100644 index 00000000..f81e86a8 --- /dev/null +++ b/dep/lapack/dormlq.f @@ -0,0 +1,268 @@ + SUBROUTINE DORMLQ( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER INFO, K, LDA, LDC, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORMLQ overwrites the general real M-by-N matrix C with +* +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': Q * C C * Q +* TRANS = 'T': Q**T * C C * Q**T +* +* where Q is a real orthogonal matrix defined as the product of k +* elementary reflectors +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGELQF. Q is of order M if SIDE = 'L' and of order N +* if SIDE = 'R'. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left; +* = 'R': apply Q or Q**T from the Right. +* +* TRANS (input) CHARACTER*1 +* = 'N': No transpose, apply Q; +* = 'T': Transpose, apply Q**T. +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines +* the matrix Q. +* If SIDE = 'L', M >= K >= 0; +* if SIDE = 'R', N >= K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension +* (LDA,M) if SIDE = 'L', +* (LDA,N) if SIDE = 'R' +* The i-th row must contain the vector which defines the +* elementary reflector H(i), for i = 1,2,...,k, as returned by +* DGELQF in the first k rows of its array argument A. +* A is modified by the routine but restored on exit. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,K). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGELQF. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If SIDE = 'L', LWORK >= max(1,N); +* if SIDE = 'R', LWORK >= max(1,M). +* For optimum performance LWORK >= N*NB if SIDE = 'L', and +* LWORK >= M*NB if SIDE = 'R', where NB is the optimal +* blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + INTEGER NBMAX, LDT + PARAMETER ( NBMAX = 64, LDT = NBMAX+1 ) +* .. +* .. Local Scalars .. + LOGICAL LEFT, LQUERY, NOTRAN + CHARACTER TRANST + INTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK, + $ LWKOPT, MI, NB, NBMIN, NI, NQ, NW +* .. +* .. Local Arrays .. + DOUBLE PRECISION T( LDT, NBMAX ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DLARFB, DLARFT, DORML2, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) + LQUERY = ( LWORK.EQ.-1 ) +* +* NQ is the order of Q and NW is the minimum dimension of WORK +* + IF( LEFT ) THEN + NQ = M + NW = N + ELSE + NQ = N + NW = M + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, K ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THEN + INFO = -12 + END IF +* + IF( INFO.EQ.0 ) THEN +* +* Determine the block size. NB may be at most NBMAX, where NBMAX +* is used to define the local array T. +* + NB = MIN( NBMAX, ILAENV( 1, 'DORMLQ', SIDE // TRANS, M, N, K, + $ -1 ) ) + LWKOPT = MAX( 1, NW )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORMLQ', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NBMIN = 2 + LDWORK = NW + IF( NB.GT.1 .AND. NB.LT.K ) THEN + IWS = NW*NB + IF( LWORK.LT.IWS ) THEN + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DORMLQ', SIDE // TRANS, M, N, K, + $ -1 ) ) + END IF + ELSE + IWS = NW + END IF +* + IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN +* +* Use unblocked code +* + CALL DORML2( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, + $ IINFO ) + ELSE +* +* Use blocked code +* + IF( ( LEFT .AND. NOTRAN ) .OR. + $ ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) THEN + I1 = 1 + I2 = K + I3 = NB + ELSE + I1 = ( ( K-1 ) / NB )*NB + 1 + I2 = 1 + I3 = -NB + END IF +* + IF( LEFT ) THEN + NI = N + JC = 1 + ELSE + MI = M + IC = 1 + END IF +* + IF( NOTRAN ) THEN + TRANST = 'T' + ELSE + TRANST = 'N' + END IF +* + DO 10 I = I1, I2, I3 + IB = MIN( NB, K-I+1 ) +* +* Form the triangular factor of the block reflector +* H = H(i) H(i+1) . . . H(i+ib-1) +* + CALL DLARFT( 'Forward', 'Rowwise', NQ-I+1, IB, A( I, I ), + $ LDA, TAU( I ), T, LDT ) + IF( LEFT ) THEN +* +* H or H**T is applied to C(i:m,1:n) +* + MI = M - I + 1 + IC = I + ELSE +* +* H or H**T is applied to C(1:m,i:n) +* + NI = N - I + 1 + JC = I + END IF +* +* Apply H or H**T +* + CALL DLARFB( SIDE, TRANST, 'Forward', 'Rowwise', MI, NI, IB, + $ A( I, I ), LDA, T, LDT, C( IC, JC ), LDC, WORK, + $ LDWORK ) + 10 CONTINUE + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORMLQ +* + END diff --git a/dep/lapack/dormql.f b/dep/lapack/dormql.f new file mode 100644 index 00000000..f3370f10 --- /dev/null +++ b/dep/lapack/dormql.f @@ -0,0 +1,261 @@ + SUBROUTINE DORMQL( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER INFO, K, LDA, LDC, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORMQL overwrites the general real M-by-N matrix C with +* +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': Q * C C * Q +* TRANS = 'T': Q**T * C C * Q**T +* +* where Q is a real orthogonal matrix defined as the product of k +* elementary reflectors +* +* Q = H(k) . . . H(2) H(1) +* +* as returned by DGEQLF. Q is of order M if SIDE = 'L' and of order N +* if SIDE = 'R'. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left; +* = 'R': apply Q or Q**T from the Right. +* +* TRANS (input) CHARACTER*1 +* = 'N': No transpose, apply Q; +* = 'T': Transpose, apply Q**T. +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines +* the matrix Q. +* If SIDE = 'L', M >= K >= 0; +* if SIDE = 'R', N >= K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,K) +* The i-th column must contain the vector which defines the +* elementary reflector H(i), for i = 1,2,...,k, as returned by +* DGEQLF in the last k columns of its array argument A. +* A is modified by the routine but restored on exit. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* If SIDE = 'L', LDA >= max(1,M); +* if SIDE = 'R', LDA >= max(1,N). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQLF. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If SIDE = 'L', LWORK >= max(1,N); +* if SIDE = 'R', LWORK >= max(1,M). +* For optimum performance LWORK >= N*NB if SIDE = 'L', and +* LWORK >= M*NB if SIDE = 'R', where NB is the optimal +* blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + INTEGER NBMAX, LDT + PARAMETER ( NBMAX = 64, LDT = NBMAX+1 ) +* .. +* .. Local Scalars .. + LOGICAL LEFT, LQUERY, NOTRAN + INTEGER I, I1, I2, I3, IB, IINFO, IWS, LDWORK, LWKOPT, + $ MI, NB, NBMIN, NI, NQ, NW +* .. +* .. Local Arrays .. + DOUBLE PRECISION T( LDT, NBMAX ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DLARFB, DLARFT, DORM2L, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) + LQUERY = ( LWORK.EQ.-1 ) +* +* NQ is the order of Q and NW is the minimum dimension of WORK +* + IF( LEFT ) THEN + NQ = M + NW = MAX( 1, N ) + ELSE + NQ = N + NW = MAX( 1, M ) + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( M.EQ.0 .OR. N.EQ.0 ) THEN + LWKOPT = 1 + ELSE +* +* Determine the block size. NB may be at most NBMAX, where +* NBMAX is used to define the local array T. +* + NB = MIN( NBMAX, ILAENV( 1, 'DORMQL', SIDE // TRANS, M, N, + $ K, -1 ) ) + LWKOPT = NW*NB + END IF + WORK( 1 ) = LWKOPT +* + IF( LWORK.LT.NW .AND. .NOT.LQUERY ) THEN + INFO = -12 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORMQL', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) THEN + RETURN + END IF +* + NBMIN = 2 + LDWORK = NW + IF( NB.GT.1 .AND. NB.LT.K ) THEN + IWS = NW*NB + IF( LWORK.LT.IWS ) THEN + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DORMQL', SIDE // TRANS, M, N, K, + $ -1 ) ) + END IF + ELSE + IWS = NW + END IF +* + IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN +* +* Use unblocked code +* + CALL DORM2L( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, + $ IINFO ) + ELSE +* +* Use blocked code +* + IF( ( LEFT .AND. NOTRAN ) .OR. + $ ( .NOT.LEFT .AND. .NOT.NOTRAN ) ) THEN + I1 = 1 + I2 = K + I3 = NB + ELSE + I1 = ( ( K-1 ) / NB )*NB + 1 + I2 = 1 + I3 = -NB + END IF +* + IF( LEFT ) THEN + NI = N + ELSE + MI = M + END IF +* + DO 10 I = I1, I2, I3 + IB = MIN( NB, K-I+1 ) +* +* Form the triangular factor of the block reflector +* H = H(i+ib-1) . . . H(i+1) H(i) +* + CALL DLARFT( 'Backward', 'Columnwise', NQ-K+I+IB-1, IB, + $ A( 1, I ), LDA, TAU( I ), T, LDT ) + IF( LEFT ) THEN +* +* H or H' is applied to C(1:m-k+i+ib-1,1:n) +* + MI = M - K + I + IB - 1 + ELSE +* +* H or H' is applied to C(1:m,1:n-k+i+ib-1) +* + NI = N - K + I + IB - 1 + END IF +* +* Apply H or H' +* + CALL DLARFB( SIDE, TRANS, 'Backward', 'Columnwise', MI, NI, + $ IB, A( 1, I ), LDA, T, LDT, C, LDC, WORK, + $ LDWORK ) + 10 CONTINUE + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORMQL +* + END diff --git a/dep/lapack/dormqr.f b/dep/lapack/dormqr.f new file mode 100644 index 00000000..2ada955b --- /dev/null +++ b/dep/lapack/dormqr.f @@ -0,0 +1,261 @@ + SUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, + $ WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS + INTEGER INFO, K, LDA, LDC, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORMQR overwrites the general real M-by-N matrix C with +* +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': Q * C C * Q +* TRANS = 'T': Q**T * C C * Q**T +* +* where Q is a real orthogonal matrix defined as the product of k +* elementary reflectors +* +* Q = H(1) H(2) . . . H(k) +* +* as returned by DGEQRF. Q is of order M if SIDE = 'L' and of order N +* if SIDE = 'R'. +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left; +* = 'R': apply Q or Q**T from the Right. +* +* TRANS (input) CHARACTER*1 +* = 'N': No transpose, apply Q; +* = 'T': Transpose, apply Q**T. +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* K (input) INTEGER +* The number of elementary reflectors whose product defines +* the matrix Q. +* If SIDE = 'L', M >= K >= 0; +* if SIDE = 'R', N >= K >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,K) +* The i-th column must contain the vector which defines the +* elementary reflector H(i), for i = 1,2,...,k, as returned by +* DGEQRF in the first k columns of its array argument A. +* A is modified by the routine but restored on exit. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* If SIDE = 'L', LDA >= max(1,M); +* if SIDE = 'R', LDA >= max(1,N). +* +* TAU (input) DOUBLE PRECISION array, dimension (K) +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DGEQRF. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If SIDE = 'L', LWORK >= max(1,N); +* if SIDE = 'R', LWORK >= max(1,M). +* For optimum performance LWORK >= N*NB if SIDE = 'L', and +* LWORK >= M*NB if SIDE = 'R', where NB is the optimal +* blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + INTEGER NBMAX, LDT + PARAMETER ( NBMAX = 64, LDT = NBMAX+1 ) +* .. +* .. Local Scalars .. + LOGICAL LEFT, LQUERY, NOTRAN + INTEGER I, I1, I2, I3, IB, IC, IINFO, IWS, JC, LDWORK, + $ LWKOPT, MI, NB, NBMIN, NI, NQ, NW +* .. +* .. Local Arrays .. + DOUBLE PRECISION T( LDT, NBMAX ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DLARFB, DLARFT, DORM2R, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + NOTRAN = LSAME( TRANS, 'N' ) + LQUERY = ( LWORK.EQ.-1 ) +* +* NQ is the order of Q and NW is the minimum dimension of WORK +* + IF( LEFT ) THEN + NQ = M + NW = N + ELSE + NQ = N + NW = M + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN + INFO = -2 + ELSE IF( M.LT.0 ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( K.LT.0 .OR. K.GT.NQ ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THEN + INFO = -12 + END IF +* + IF( INFO.EQ.0 ) THEN +* +* Determine the block size. NB may be at most NBMAX, where NBMAX +* is used to define the local array T. +* + NB = MIN( NBMAX, ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N, K, + $ -1 ) ) + LWKOPT = MAX( 1, NW )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORMQR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. K.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NBMIN = 2 + LDWORK = NW + IF( NB.GT.1 .AND. NB.LT.K ) THEN + IWS = NW*NB + IF( LWORK.LT.IWS ) THEN + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'DORMQR', SIDE // TRANS, M, N, K, + $ -1 ) ) + END IF + ELSE + IWS = NW + END IF +* + IF( NB.LT.NBMIN .OR. NB.GE.K ) THEN +* +* Use unblocked code +* + CALL DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, + $ IINFO ) + ELSE +* +* Use blocked code +* + IF( ( LEFT .AND. .NOT.NOTRAN ) .OR. + $ ( .NOT.LEFT .AND. NOTRAN ) ) THEN + I1 = 1 + I2 = K + I3 = NB + ELSE + I1 = ( ( K-1 ) / NB )*NB + 1 + I2 = 1 + I3 = -NB + END IF +* + IF( LEFT ) THEN + NI = N + JC = 1 + ELSE + MI = M + IC = 1 + END IF +* + DO 10 I = I1, I2, I3 + IB = MIN( NB, K-I+1 ) +* +* Form the triangular factor of the block reflector +* H = H(i) H(i+1) . . . H(i+ib-1) +* + CALL DLARFT( 'Forward', 'Columnwise', NQ-I+1, IB, A( I, I ), + $ LDA, TAU( I ), T, LDT ) + IF( LEFT ) THEN +* +* H or H**T is applied to C(i:m,1:n) +* + MI = M - I + 1 + IC = I + ELSE +* +* H or H**T is applied to C(1:m,i:n) +* + NI = N - I + 1 + JC = I + END IF +* +* Apply H or H**T +* + CALL DLARFB( SIDE, TRANS, 'Forward', 'Columnwise', MI, NI, + $ IB, A( I, I ), LDA, T, LDT, C( IC, JC ), LDC, + $ WORK, LDWORK ) + 10 CONTINUE + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORMQR +* + END diff --git a/dep/lapack/dormtr.f b/dep/lapack/dormtr.f new file mode 100644 index 00000000..3fe9db0d --- /dev/null +++ b/dep/lapack/dormtr.f @@ -0,0 +1,222 @@ + SUBROUTINE DORMTR( SIDE, UPLO, TRANS, M, N, A, LDA, TAU, C, LDC, + $ WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER SIDE, TRANS, UPLO + INTEGER INFO, LDA, LDC, LWORK, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DORMTR overwrites the general real M-by-N matrix C with +* +* SIDE = 'L' SIDE = 'R' +* TRANS = 'N': Q * C C * Q +* TRANS = 'T': Q**T * C C * Q**T +* +* where Q is a real orthogonal matrix of order nq, with nq = m if +* SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of +* nq-1 elementary reflectors, as returned by DSYTRD: +* +* if UPLO = 'U', Q = H(nq-1) . . . H(2) H(1); +* +* if UPLO = 'L', Q = H(1) H(2) . . . H(nq-1). +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'L': apply Q or Q**T from the Left; +* = 'R': apply Q or Q**T from the Right. +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A contains elementary reflectors +* from DSYTRD; +* = 'L': Lower triangle of A contains elementary reflectors +* from DSYTRD. +* +* TRANS (input) CHARACTER*1 +* = 'N': No transpose, apply Q; +* = 'T': Transpose, apply Q**T. +* +* M (input) INTEGER +* The number of rows of the matrix C. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix C. N >= 0. +* +* A (input) DOUBLE PRECISION array, dimension +* (LDA,M) if SIDE = 'L' +* (LDA,N) if SIDE = 'R' +* The vectors which define the elementary reflectors, as +* returned by DSYTRD. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* LDA >= max(1,M) if SIDE = 'L'; LDA >= max(1,N) if SIDE = 'R'. +* +* TAU (input) DOUBLE PRECISION array, dimension +* (M-1) if SIDE = 'L' +* (N-1) if SIDE = 'R' +* TAU(i) must contain the scalar factor of the elementary +* reflector H(i), as returned by DSYTRD. +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N matrix C. +* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If SIDE = 'L', LWORK >= max(1,N); +* if SIDE = 'R', LWORK >= max(1,M). +* For optimum performance LWORK >= N*NB if SIDE = 'L', and +* LWORK >= M*NB if SIDE = 'R', where NB is the optimal +* blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + LOGICAL LEFT, LQUERY, UPPER + INTEGER I1, I2, IINFO, LWKOPT, MI, NB, NI, NQ, NW +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DORMQL, DORMQR, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 + LEFT = LSAME( SIDE, 'L' ) + UPPER = LSAME( UPLO, 'U' ) + LQUERY = ( LWORK.EQ.-1 ) +* +* NQ is the order of Q and NW is the minimum dimension of WORK +* + IF( LEFT ) THEN + NQ = M + NW = N + ELSE + NQ = N + NW = M + END IF + IF( .NOT.LEFT .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN + INFO = -1 + ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -2 + ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT.LSAME( TRANS, 'T' ) ) + $ THEN + INFO = -3 + ELSE IF( M.LT.0 ) THEN + INFO = -4 + ELSE IF( N.LT.0 ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, NQ ) ) THEN + INFO = -7 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -10 + ELSE IF( LWORK.LT.MAX( 1, NW ) .AND. .NOT.LQUERY ) THEN + INFO = -12 + END IF +* + IF( INFO.EQ.0 ) THEN + IF( UPPER ) THEN + IF( LEFT ) THEN + NB = ILAENV( 1, 'DORMQL', SIDE // TRANS, M-1, N, M-1, + $ -1 ) + ELSE + NB = ILAENV( 1, 'DORMQL', SIDE // TRANS, M, N-1, N-1, + $ -1 ) + END IF + ELSE + IF( LEFT ) THEN + NB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M-1, N, M-1, + $ -1 ) + ELSE + NB = ILAENV( 1, 'DORMQR', SIDE // TRANS, M, N-1, N-1, + $ -1 ) + END IF + END IF + LWKOPT = MAX( 1, NW )*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DORMTR', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 .OR. NQ.EQ.1 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + IF( LEFT ) THEN + MI = M - 1 + NI = N + ELSE + MI = M + NI = N - 1 + END IF +* + IF( UPPER ) THEN +* +* Q was determined by a call to DSYTRD with UPLO = 'U' +* + CALL DORMQL( SIDE, TRANS, MI, NI, NQ-1, A( 1, 2 ), LDA, TAU, C, + $ LDC, WORK, LWORK, IINFO ) + ELSE +* +* Q was determined by a call to DSYTRD with UPLO = 'L' +* + IF( LEFT ) THEN + I1 = 2 + I2 = 1 + ELSE + I1 = 1 + I2 = 2 + END IF + CALL DORMQR( SIDE, TRANS, MI, NI, NQ-1, A( 2, 1 ), LDA, TAU, + $ C( I1, I2 ), LDC, WORK, LWORK, IINFO ) + END IF + WORK( 1 ) = LWKOPT + RETURN +* +* End of DORMTR +* + END diff --git a/dep/lapack/dposv.f b/dep/lapack/dposv.f new file mode 100644 index 00000000..0bcf4764 --- /dev/null +++ b/dep/lapack/dposv.f @@ -0,0 +1,193 @@ +*> \brief DPOSV computes the solution to system of linear equations A * X = B for PO matrices +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DPOSV + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER UPLO +* INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DPOSV computes the solution to a real system of linear equations +*> A * X = B, +*> where A is an N-by-N symmetric positive definite matrix and X and B +*> are N-by-NRHS matrices. +*> +*> The Cholesky decomposition is used to factor A as +*> A = U**T* U, if UPLO = 'U', or +*> A = L * L**T, if UPLO = 'L', +*> where U is an upper triangular matrix and L is a lower triangular +*> matrix. The factored form of A is then used to solve the system of +*> equations A * X = B. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> = 'U': Upper triangle of A is stored; +*> = 'L': Lower triangle of A is stored. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of linear equations, i.e., the order of the +*> matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in] NRHS +*> \verbatim +*> NRHS is INTEGER +*> The number of right hand sides, i.e., the number of columns +*> of the matrix B. NRHS >= 0. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> On entry, the symmetric matrix A. If UPLO = 'U', the leading +*> N-by-N upper triangular part of A contains the upper +*> triangular part of the matrix A, and the strictly lower +*> triangular part of A is not referenced. If UPLO = 'L', the +*> leading N-by-N lower triangular part of A contains the lower +*> triangular part of the matrix A, and the strictly upper +*> triangular part of A is not referenced. +*> +*> On exit, if INFO = 0, the factor U or L from the Cholesky +*> factorization A = U**T*U or A = L*L**T. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,N). +*> \endverbatim +*> +*> \param[in,out] B +*> \verbatim +*> B is DOUBLE PRECISION array, dimension (LDB,NRHS) +*> On entry, the N-by-NRHS right hand side matrix B. +*> On exit, if INFO = 0, the N-by-NRHS solution matrix X. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> The leading dimension of the array B. LDB >= max(1,N). +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> > 0: if INFO = i, the leading minor of order i of A is not +*> positive definite, so the factorization could not be +*> completed, and the solution has not been computed. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup doublePOsolve +* +* ===================================================================== + SUBROUTINE DPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) +* +* -- LAPACK driver routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DPOTRF, DPOTRS, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPOSV ', -INFO ) + RETURN + END IF +* +* Compute the Cholesky factorization A = U**T*U or A = L*L**T. +* + CALL DPOTRF( UPLO, N, A, LDA, INFO ) + IF( INFO.EQ.0 ) THEN +* +* Solve the system A*X = B, overwriting B with X. +* + CALL DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) +* + END IF + RETURN +* +* End of DPOSV +* + END diff --git a/dep/lapack/dpotf2.f b/dep/lapack/dpotf2.f new file mode 100644 index 00000000..b7d65e91 --- /dev/null +++ b/dep/lapack/dpotf2.f @@ -0,0 +1,167 @@ + SUBROUTINE DPOTF2( UPLO, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DPOTF2 computes the Cholesky factorization of a real symmetric +* positive definite matrix A. +* +* The factorization has the form +* A = U' * U , if UPLO = 'U', or +* A = L * L', if UPLO = 'L', +* where U is an upper triangular matrix and L is lower triangular. +* +* This is the unblocked version of the algorithm, calling Level 2 BLAS. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* symmetric matrix A is stored. +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the symmetric matrix A. If UPLO = 'U', the leading +* n by n upper triangular part of A contains the upper +* triangular part of the matrix A, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading n by n lower triangular part of A contains the lower +* triangular part of the matrix A, and the strictly upper +* triangular part of A is not referenced. +* +* On exit, if INFO = 0, the factor U or L from the Cholesky +* factorization A = U'*U or A = L*L'. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, the leading minor of order k is not +* positive definite, and the factorization could not be +* completed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER J + DOUBLE PRECISION AJJ +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DDOT + EXTERNAL LSAME, DDOT +* .. +* .. External Subroutines .. + EXTERNAL DGEMV, DSCAL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPOTF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + IF( UPPER ) THEN +* +* Compute the Cholesky factorization A = U'*U. +* + DO 10 J = 1, N +* +* Compute U(J,J) and test for non-positive-definiteness. +* + AJJ = A( J, J ) - DDOT( J-1, A( 1, J ), 1, A( 1, J ), 1 ) + IF( AJJ.LE.ZERO ) THEN + A( J, J ) = AJJ + GO TO 30 + END IF + AJJ = SQRT( AJJ ) + A( J, J ) = AJJ +* +* Compute elements J+1:N of row J. +* + IF( J.LT.N ) THEN + CALL DGEMV( 'Transpose', J-1, N-J, -ONE, A( 1, J+1 ), + $ LDA, A( 1, J ), 1, ONE, A( J, J+1 ), LDA ) + CALL DSCAL( N-J, ONE / AJJ, A( J, J+1 ), LDA ) + END IF + 10 CONTINUE + ELSE +* +* Compute the Cholesky factorization A = L*L'. +* + DO 20 J = 1, N +* +* Compute L(J,J) and test for non-positive-definiteness. +* + AJJ = A( J, J ) - DDOT( J-1, A( J, 1 ), LDA, A( J, 1 ), + $ LDA ) + IF( AJJ.LE.ZERO ) THEN + A( J, J ) = AJJ + GO TO 30 + END IF + AJJ = SQRT( AJJ ) + A( J, J ) = AJJ +* +* Compute elements J+1:N of column J. +* + IF( J.LT.N ) THEN + CALL DGEMV( 'No transpose', N-J, J-1, -ONE, A( J+1, 1 ), + $ LDA, A( J, 1 ), LDA, ONE, A( J+1, J ), 1 ) + CALL DSCAL( N-J, ONE / AJJ, A( J+1, J ), 1 ) + END IF + 20 CONTINUE + END IF + GO TO 40 +* + 30 CONTINUE + INFO = J +* + 40 CONTINUE + RETURN +* +* End of DPOTF2 +* + END diff --git a/dep/lapack/dpotrf.f b/dep/lapack/dpotrf.f new file mode 100644 index 00000000..8449df6d --- /dev/null +++ b/dep/lapack/dpotrf.f @@ -0,0 +1,183 @@ + SUBROUTINE DPOTRF( UPLO, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DPOTRF computes the Cholesky factorization of a real symmetric +* positive definite matrix A. +* +* The factorization has the form +* A = U**T * U, if UPLO = 'U', or +* A = L * L**T, if UPLO = 'L', +* where U is an upper triangular matrix and L is lower triangular. +* +* This is the block version of the algorithm, calling Level 3 BLAS. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the symmetric matrix A. If UPLO = 'U', the leading +* N-by-N upper triangular part of A contains the upper +* triangular part of the matrix A, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading N-by-N lower triangular part of A contains the lower +* triangular part of the matrix A, and the strictly upper +* triangular part of A is not referenced. +* +* On exit, if INFO = 0, the factor U or L from the Cholesky +* factorization A = U**T*U or A = L*L**T. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the leading minor of order i is not +* positive definite, and the factorization could not be +* completed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER J, JB, NB +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DPOTF2, DSYRK, DTRSM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPOTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment. +* + NB = ILAENV( 1, 'DPOTRF', UPLO, N, -1, -1, -1 ) + IF( NB.LE.1 .OR. NB.GE.N ) THEN +* +* Use unblocked code. +* + CALL DPOTF2( UPLO, N, A, LDA, INFO ) + ELSE +* +* Use blocked code. +* + IF( UPPER ) THEN +* +* Compute the Cholesky factorization A = U'*U. +* + DO 10 J = 1, N, NB +* +* Update and factorize the current diagonal block and test +* for non-positive-definiteness. +* + JB = MIN( NB, N-J+1 ) + CALL DSYRK( 'Upper', 'Transpose', JB, J-1, -ONE, + $ A( 1, J ), LDA, ONE, A( J, J ), LDA ) + CALL DPOTF2( 'Upper', JB, A( J, J ), LDA, INFO ) + IF( INFO.NE.0 ) + $ GO TO 30 + IF( J+JB.LE.N ) THEN +* +* Compute the current block row. +* + CALL DGEMM( 'Transpose', 'No transpose', JB, N-J-JB+1, + $ J-1, -ONE, A( 1, J ), LDA, A( 1, J+JB ), + $ LDA, ONE, A( J, J+JB ), LDA ) + CALL DTRSM( 'Left', 'Upper', 'Transpose', 'Non-unit', + $ JB, N-J-JB+1, ONE, A( J, J ), LDA, + $ A( J, J+JB ), LDA ) + END IF + 10 CONTINUE +* + ELSE +* +* Compute the Cholesky factorization A = L*L'. +* + DO 20 J = 1, N, NB +* +* Update and factorize the current diagonal block and test +* for non-positive-definiteness. +* + JB = MIN( NB, N-J+1 ) + CALL DSYRK( 'Lower', 'No transpose', JB, J-1, -ONE, + $ A( J, 1 ), LDA, ONE, A( J, J ), LDA ) + CALL DPOTF2( 'Lower', JB, A( J, J ), LDA, INFO ) + IF( INFO.NE.0 ) + $ GO TO 30 + IF( J+JB.LE.N ) THEN +* +* Compute the current block column. +* + CALL DGEMM( 'No transpose', 'Transpose', N-J-JB+1, JB, + $ J-1, -ONE, A( J+JB, 1 ), LDA, A( J, 1 ), + $ LDA, ONE, A( J+JB, J ), LDA ) + CALL DTRSM( 'Right', 'Lower', 'Transpose', 'Non-unit', + $ N-J-JB+1, JB, ONE, A( J, J ), LDA, + $ A( J+JB, J ), LDA ) + END IF + 20 CONTINUE + END IF + END IF + GO TO 40 +* + 30 CONTINUE + INFO = INFO + J - 1 +* + 40 CONTINUE + RETURN +* +* End of DPOTRF +* + END diff --git a/dep/lapack/dpotri.f b/dep/lapack/dpotri.f new file mode 100644 index 00000000..b3d0eb44 --- /dev/null +++ b/dep/lapack/dpotri.f @@ -0,0 +1,97 @@ + SUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DPOTRI computes the inverse of a real symmetric positive definite +* matrix A using the Cholesky factorization A = U**T*U or A = L*L**T +* computed by DPOTRF. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the triangular factor U or L from the Cholesky +* factorization A = U**T*U or A = L*L**T, as computed by +* DPOTRF. +* On exit, the upper or lower triangle of the (symmetric) +* inverse of A, overwriting the input factor U or L. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the (i,i) element of the factor U or L is +* zero, and the inverse could not be computed. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLAUUM, DTRTRI, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPOTRI', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Invert the triangular Cholesky factor U or L. +* + CALL DTRTRI( UPLO, 'Non-unit', N, A, LDA, INFO ) + IF( INFO.GT.0 ) + $ RETURN +* +* Form inv(U)*inv(U)' or inv(L)'*inv(L). +* + CALL DLAUUM( UPLO, N, A, LDA, INFO ) +* + RETURN +* +* End of DPOTRI +* + END diff --git a/dep/lapack/dpotrs.f b/dep/lapack/dpotrs.f new file mode 100644 index 00000000..71f19a3f --- /dev/null +++ b/dep/lapack/dpotrs.f @@ -0,0 +1,204 @@ +*> \brief \b DPOTRS +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DPOTRS + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER UPLO +* INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DPOTRS solves a system of linear equations A*X = B with a symmetric +*> positive definite matrix A using the Cholesky factorization +*> A = U**T*U or A = L*L**T computed by DPOTRF. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> = 'U': Upper triangle of A is stored; +*> = 'L': Lower triangle of A is stored. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in] NRHS +*> \verbatim +*> NRHS is INTEGER +*> The number of right hand sides, i.e., the number of columns +*> of the matrix B. NRHS >= 0. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The triangular factor U or L from the Cholesky factorization +*> A = U**T*U or A = L*L**T, as computed by DPOTRF. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,N). +*> \endverbatim +*> +*> \param[in,out] B +*> \verbatim +*> B is DOUBLE PRECISION array, dimension (LDB,NRHS) +*> On entry, the right hand side matrix B. +*> On exit, the solution matrix X. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> The leading dimension of the array B. LDB >= max(1,N). +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup doublePOcomputational +* +* ===================================================================== + SUBROUTINE DPOTRS( UPLO, N, NRHS, A, LDA, B, LDB, INFO ) +* +* -- LAPACK computational routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DTRSM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPOTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( UPPER ) THEN +* +* Solve A*X = B where A = U**T *U. +* +* Solve U**T *X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Upper', 'Transpose', 'Non-unit', N, NRHS, + $ ONE, A, LDA, B, LDB ) +* +* Solve U*X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', N, + $ NRHS, ONE, A, LDA, B, LDB ) + ELSE +* +* Solve A*X = B where A = L*L**T. +* +* Solve L*X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Lower', 'No transpose', 'Non-unit', N, + $ NRHS, ONE, A, LDA, B, LDB ) +* +* Solve L**T *X = B, overwriting B with X. +* + CALL DTRSM( 'Left', 'Lower', 'Transpose', 'Non-unit', N, NRHS, + $ ONE, A, LDA, B, LDB ) + END IF +* + RETURN +* +* End of DPOTRS +* + END diff --git a/dep/lapack/dpttrf.f b/dep/lapack/dpttrf.f new file mode 100644 index 00000000..cf945d0e --- /dev/null +++ b/dep/lapack/dpttrf.f @@ -0,0 +1,113 @@ + SUBROUTINE DPTTRF( N, D, E, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* March 31, 1993 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DPTTRF computes the factorization of a real symmetric positive +* definite tridiagonal matrix A. +* +* If the subdiagonal elements of A are supplied in the array E, the +* factorization has the form A = L*D*L**T, where D is diagonal and L +* is unit lower bidiagonal; if the superdiagonal elements of A are +* supplied, it has the form A = U**T*D*U, where U is unit upper +* bidiagonal. (The two forms are equivalent if A is real.) +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix +* A. On exit, the n diagonal elements of the diagonal matrix +* D from the L*D*L**T factorization of A. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the (n-1) off-diagonal elements of the tridiagonal +* matrix A. +* On exit, the (n-1) off-diagonal elements of the unit +* bidiagonal factor L or U from the factorization of A. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the leading minor of order i is not +* positive definite; if i < N, the factorization could +* not be completed, while if i = N, the factorization was +* completed, but D(N) = 0. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION DI, EI +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DPTTRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Compute the L*D*L' (or U'*D*U) factorization of A. +* + DO 10 I = 1, N - 1 +* +* Drop out of the loop if d(i) <= 0: the matrix is not positive +* definite. +* + DI = D( I ) + IF( DI.LE.ZERO ) + $ GO TO 20 +* +* Solve for e(i) and d(i+1). +* + EI = E( I ) + E( I ) = EI / DI + D( I+1 ) = D( I+1 ) - E( I )*EI + 10 CONTINUE +* +* Check d(n) for positive definiteness. +* + I = N + IF( D( I ).GT.ZERO ) + $ GO TO 30 +* + 20 CONTINUE + INFO = I +* + 30 CONTINUE + RETURN +* +* End of DPTTRF +* + END diff --git a/dep/lapack/dpttrs.f b/dep/lapack/dpttrs.f new file mode 100644 index 00000000..43fc16a0 --- /dev/null +++ b/dep/lapack/dpttrs.f @@ -0,0 +1,108 @@ + SUBROUTINE DPTTRS( N, NRHS, D, E, B, LDB, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* March 31, 1993 +* +* .. Scalar Arguments .. + INTEGER INFO, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION B( LDB, * ), D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DPTTRS solves a system of linear equations A * X = B with a +* symmetric positive definite tridiagonal matrix A using the +* factorization A = L*D*L**T or A = U**T*D*U computed by DPTTRF. +* (The two forms are equivalent if A is real.) +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the tridiagonal matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the diagonal matrix D from the +* factorization computed by DPTTRF. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) off-diagonal elements of the unit bidiagonal factor +* U or L from the factorization computed by DPTTRF. +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DPTTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Solve A * X = B using the factorization A = L*D*L', +* overwriting each right hand side vector with its solution. +* + DO 30 J = 1, NRHS +* +* Solve L * x = b. +* + DO 10 I = 2, N + B( I, J ) = B( I, J ) - B( I-1, J )*E( I-1 ) + 10 CONTINUE +* +* Solve D * L' * x = b. +* + B( N, J ) = B( N, J ) / D( N ) + DO 20 I = N - 1, 1, -1 + B( I, J ) = B( I, J ) / D( I ) - B( I+1, J )*E( I ) + 20 CONTINUE + 30 CONTINUE +* + RETURN +* +* End of DPTTRS +* + END diff --git a/dep/lapack/dstebz.f b/dep/lapack/dstebz.f new file mode 100644 index 00000000..b540715b --- /dev/null +++ b/dep/lapack/dstebz.f @@ -0,0 +1,652 @@ + SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E, + $ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK, + $ INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* 8-18-00: Increase FUDGE factor for T3E (eca) +* +* .. Scalar Arguments .. + CHARACTER ORDER, RANGE + INTEGER IL, INFO, IU, M, N, NSPLIT + DOUBLE PRECISION ABSTOL, VL, VU +* .. +* .. Array Arguments .. + INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * ) + DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DSTEBZ computes the eigenvalues of a symmetric tridiagonal +* matrix T. The user may ask for all eigenvalues, all eigenvalues +* in the half-open interval (VL, VU], or the IL-th through IU-th +* eigenvalues. +* +* To avoid overflow, the matrix must be scaled so that its +* largest element is no greater than overflow**(1/2) * +* underflow**(1/4) in absolute value, and for greatest +* accuracy, it should not be much smaller than that. +* +* See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal +* Matrix", Report CS41, Computer Science Dept., Stanford +* University, July 21, 1966. +* +* Arguments +* ========= +* +* RANGE (input) CHARACTER*1 +* = 'A': ("All") all eigenvalues will be found. +* = 'V': ("Value") all eigenvalues in the half-open interval +* (VL, VU] will be found. +* = 'I': ("Index") the IL-th through IU-th eigenvalues (of the +* entire matrix) will be found. +* +* ORDER (input) CHARACTER*1 +* = 'B': ("By Block") the eigenvalues will be grouped by +* split-off block (see IBLOCK, ISPLIT) and +* ordered from smallest to largest within +* the block. +* = 'E': ("Entire matrix") +* the eigenvalues for the entire matrix +* will be ordered from smallest to +* largest. +* +* N (input) INTEGER +* The order of the tridiagonal matrix T. N >= 0. +* +* VL (input) DOUBLE PRECISION +* VU (input) DOUBLE PRECISION +* If RANGE='V', the lower and upper bounds of the interval to +* be searched for eigenvalues. Eigenvalues less than or equal +* to VL, or greater than VU, will not be returned. VL < VU. +* Not referenced if RANGE = 'A' or 'I'. +* +* IL (input) INTEGER +* IU (input) INTEGER +* If RANGE='I', the indices (in ascending order) of the +* smallest and largest eigenvalues to be returned. +* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. +* Not referenced if RANGE = 'A' or 'V'. +* +* ABSTOL (input) DOUBLE PRECISION +* The absolute tolerance for the eigenvalues. An eigenvalue +* (or cluster) is considered to be located if it has been +* determined to lie in an interval whose width is ABSTOL or +* less. If ABSTOL is less than or equal to zero, then ULP*|T| +* will be used, where |T| means the 1-norm of T. +* +* Eigenvalues will be computed most accurately when ABSTOL is +* set to twice the underflow threshold 2*DLAMCH('S'), not zero. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the tridiagonal matrix T. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) off-diagonal elements of the tridiagonal matrix T. +* +* M (output) INTEGER +* The actual number of eigenvalues found. 0 <= M <= N. +* (See also the description of INFO=2,3.) +* +* NSPLIT (output) INTEGER +* The number of diagonal blocks in the matrix T. +* 1 <= NSPLIT <= N. +* +* W (output) DOUBLE PRECISION array, dimension (N) +* On exit, the first M elements of W will contain the +* eigenvalues. (DSTEBZ may use the remaining N-M elements as +* workspace.) +* +* IBLOCK (output) INTEGER array, dimension (N) +* At each row/column j where E(j) is zero or small, the +* matrix T is considered to split into a block diagonal +* matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which +* block (from 1 to the number of blocks) the eigenvalue W(i) +* belongs. (DSTEBZ may use the remaining N-M elements as +* workspace.) +* +* ISPLIT (output) INTEGER array, dimension (N) +* The splitting points, at which T breaks up into submatrices. +* The first submatrix consists of rows/columns 1 to ISPLIT(1), +* the second of rows/columns ISPLIT(1)+1 through ISPLIT(2), +* etc., and the NSPLIT-th consists of rows/columns +* ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N. +* (Only the first NSPLIT elements will actually be used, but +* since the user cannot know a priori what value NSPLIT will +* have, N words must be reserved for ISPLIT.) +* +* WORK (workspace) DOUBLE PRECISION array, dimension (4*N) +* +* IWORK (workspace) INTEGER array, dimension (3*N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: some or all of the eigenvalues failed to converge or +* were not computed: +* =1 or 3: Bisection failed to converge for some +* eigenvalues; these eigenvalues are flagged by a +* negative block number. The effect is that the +* eigenvalues may not be as accurate as the +* absolute and relative tolerances. This is +* generally caused by unexpectedly inaccurate +* arithmetic. +* =2 or 3: RANGE='I' only: Not all of the eigenvalues +* IL:IU were found. +* Effect: M < IU+1-IL +* Cause: non-monotonic arithmetic, causing the +* Sturm sequence to be non-monotonic. +* Cure: recalculate, using RANGE='A', and pick +* out eigenvalues IL:IU. In some cases, +* increasing the PARAMETER "FUDGE" may +* make things work. +* = 4: RANGE='I', and the Gershgorin interval +* initially used was too small. No eigenvalues +* were computed. +* Probable cause: your machine has sloppy +* floating-point arithmetic. +* Cure: Increase the PARAMETER "FUDGE", +* recompile, and try again. +* +* Internal Parameters +* =================== +* +* RELFAC DOUBLE PRECISION, default = 2.0e0 +* The relative tolerance. An interval (a,b] lies within +* "relative tolerance" if b-a < RELFAC*ulp*max(|a|,|b|), +* where "ulp" is the machine precision (distance from 1 to +* the next larger floating point number.) +* +* FUDGE DOUBLE PRECISION, default = 2 +* A "fudge factor" to widen the Gershgorin intervals. Ideally, +* a value of 1 should work, but on machines with sloppy +* arithmetic, this needs to be larger. The default for +* publicly released versions should be large enough to handle +* the worst machine around. Note that this has no effect +* on accuracy of the solution. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO, HALF + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, + $ HALF = 1.0D0 / TWO ) + DOUBLE PRECISION FUDGE, RELFAC + PARAMETER ( FUDGE = 2.1D0, RELFAC = 2.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL NCNVRG, TOOFEW + INTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO, + $ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX, + $ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL, + $ NWU + DOUBLE PRECISION ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN, + $ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL +* .. +* .. Local Arrays .. + INTEGER IDUMMA( 1 ) +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, ILAENV, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DLAEBZ, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + INFO = 0 +* +* Decode RANGE +* + IF( LSAME( RANGE, 'A' ) ) THEN + IRANGE = 1 + ELSE IF( LSAME( RANGE, 'V' ) ) THEN + IRANGE = 2 + ELSE IF( LSAME( RANGE, 'I' ) ) THEN + IRANGE = 3 + ELSE + IRANGE = 0 + END IF +* +* Decode ORDER +* + IF( LSAME( ORDER, 'B' ) ) THEN + IORDER = 2 + ELSE IF( LSAME( ORDER, 'E' ) ) THEN + IORDER = 1 + ELSE + IORDER = 0 + END IF +* +* Check for Errors +* + IF( IRANGE.LE.0 ) THEN + INFO = -1 + ELSE IF( IORDER.LE.0 ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( IRANGE.EQ.2 ) THEN + IF( VL.GE.VU ) + $ INFO = -5 + ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) ) + $ THEN + INFO = -6 + ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) + $ THEN + INFO = -7 + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSTEBZ', -INFO ) + RETURN + END IF +* +* Initialize error flags +* + INFO = 0 + NCNVRG = .FALSE. + TOOFEW = .FALSE. +* +* Quick return if possible +* + M = 0 + IF( N.EQ.0 ) + $ RETURN +* +* Simplifications: +* + IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N ) + $ IRANGE = 1 +* +* Get machine constants +* NB is the minimum vector length for vector bisection, or 0 +* if only scalar is to be done. +* + SAFEMN = DLAMCH( 'S' ) + ULP = DLAMCH( 'P' ) + RTOLI = ULP*RELFAC + NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 ) + IF( NB.LE.1 ) + $ NB = 0 +* +* Special Case when N=1 +* + IF( N.EQ.1 ) THEN + NSPLIT = 1 + ISPLIT( 1 ) = 1 + IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN + M = 0 + ELSE + W( 1 ) = D( 1 ) + IBLOCK( 1 ) = 1 + M = 1 + END IF + RETURN + END IF +* +* Compute Splitting Points +* + NSPLIT = 1 + WORK( N ) = ZERO + PIVMIN = ONE +* +*DIR$ NOVECTOR + DO 10 J = 2, N + TMP1 = E( J-1 )**2 + IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN + ISPLIT( NSPLIT ) = J - 1 + NSPLIT = NSPLIT + 1 + WORK( J-1 ) = ZERO + ELSE + WORK( J-1 ) = TMP1 + PIVMIN = MAX( PIVMIN, TMP1 ) + END IF + 10 CONTINUE + ISPLIT( NSPLIT ) = N + PIVMIN = PIVMIN*SAFEMN +* +* Compute Interval and ATOLI +* + IF( IRANGE.EQ.3 ) THEN +* +* RANGE='I': Compute the interval containing eigenvalues +* IL through IU. +* +* Compute Gershgorin interval for entire (split) matrix +* and use it as the initial interval +* + GU = D( 1 ) + GL = D( 1 ) + TMP1 = ZERO +* + DO 20 J = 1, N - 1 + TMP2 = SQRT( WORK( J ) ) + GU = MAX( GU, D( J )+TMP1+TMP2 ) + GL = MIN( GL, D( J )-TMP1-TMP2 ) + TMP1 = TMP2 + 20 CONTINUE +* + GU = MAX( GU, D( N )+TMP1 ) + GL = MIN( GL, D( N )-TMP1 ) + TNORM = MAX( ABS( GL ), ABS( GU ) ) + GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN + GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN +* +* Compute Iteration parameters +* + ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) / + $ LOG( TWO ) ) + 2 + IF( ABSTOL.LE.ZERO ) THEN + ATOLI = ULP*TNORM + ELSE + ATOLI = ABSTOL + END IF +* + WORK( N+1 ) = GL + WORK( N+2 ) = GL + WORK( N+3 ) = GU + WORK( N+4 ) = GU + WORK( N+5 ) = GL + WORK( N+6 ) = GU + IWORK( 1 ) = -1 + IWORK( 2 ) = -1 + IWORK( 3 ) = N + 1 + IWORK( 4 ) = N + 1 + IWORK( 5 ) = IL - 1 + IWORK( 6 ) = IU +* + CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E, + $ WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT, + $ IWORK, W, IBLOCK, IINFO ) +* + IF( IWORK( 6 ).EQ.IU ) THEN + WL = WORK( N+1 ) + WLU = WORK( N+3 ) + NWL = IWORK( 1 ) + WU = WORK( N+4 ) + WUL = WORK( N+2 ) + NWU = IWORK( 4 ) + ELSE + WL = WORK( N+2 ) + WLU = WORK( N+4 ) + NWL = IWORK( 2 ) + WU = WORK( N+3 ) + WUL = WORK( N+1 ) + NWU = IWORK( 3 ) + END IF +* + IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN + INFO = 4 + RETURN + END IF + ELSE +* +* RANGE='A' or 'V' -- Set ATOLI +* + TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ), + $ ABS( D( N ) )+ABS( E( N-1 ) ) ) +* + DO 30 J = 2, N - 1 + TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+ + $ ABS( E( J ) ) ) + 30 CONTINUE +* + IF( ABSTOL.LE.ZERO ) THEN + ATOLI = ULP*TNORM + ELSE + ATOLI = ABSTOL + END IF +* + IF( IRANGE.EQ.2 ) THEN + WL = VL + WU = VU + ELSE + WL = ZERO + WU = ZERO + END IF + END IF +* +* Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU. +* NWL accumulates the number of eigenvalues .le. WL, +* NWU accumulates the number of eigenvalues .le. WU +* + M = 0 + IEND = 0 + INFO = 0 + NWL = 0 + NWU = 0 +* + DO 70 JB = 1, NSPLIT + IOFF = IEND + IBEGIN = IOFF + 1 + IEND = ISPLIT( JB ) + IN = IEND - IOFF +* + IF( IN.EQ.1 ) THEN +* +* Special Case -- IN=1 +* + IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN ) + $ NWL = NWL + 1 + IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN ) + $ NWU = NWU + 1 + IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE. + $ D( IBEGIN )-PIVMIN ) ) THEN + M = M + 1 + W( M ) = D( IBEGIN ) + IBLOCK( M ) = JB + END IF + ELSE +* +* General Case -- IN > 1 +* +* Compute Gershgorin Interval +* and use it as the initial interval +* + GU = D( IBEGIN ) + GL = D( IBEGIN ) + TMP1 = ZERO +* + DO 40 J = IBEGIN, IEND - 1 + TMP2 = ABS( E( J ) ) + GU = MAX( GU, D( J )+TMP1+TMP2 ) + GL = MIN( GL, D( J )-TMP1-TMP2 ) + TMP1 = TMP2 + 40 CONTINUE +* + GU = MAX( GU, D( IEND )+TMP1 ) + GL = MIN( GL, D( IEND )-TMP1 ) + BNORM = MAX( ABS( GL ), ABS( GU ) ) + GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN + GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN +* +* Compute ATOLI for the current submatrix +* + IF( ABSTOL.LE.ZERO ) THEN + ATOLI = ULP*MAX( ABS( GL ), ABS( GU ) ) + ELSE + ATOLI = ABSTOL + END IF +* + IF( IRANGE.GT.1 ) THEN + IF( GU.LT.WL ) THEN + NWL = NWL + IN + NWU = NWU + IN + GO TO 70 + END IF + GL = MAX( GL, WL ) + GU = MIN( GU, WU ) + IF( GL.GE.GU ) + $ GO TO 70 + END IF +* +* Set Up Initial Interval +* + WORK( N+1 ) = GL + WORK( N+IN+1 ) = GU + CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, + $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), + $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM, + $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) +* + NWL = NWL + IWORK( 1 ) + NWU = NWU + IWORK( IN+1 ) + IWOFF = M - IWORK( 1 ) +* +* Compute Eigenvalues +* + ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) / + $ LOG( TWO ) ) + 2 + CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN, + $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ), + $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT, + $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO ) +* +* Copy Eigenvalues Into W and IBLOCK +* Use -JB for block number for unconverged eigenvalues. +* + DO 60 J = 1, IOUT + TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) ) +* +* Flag non-convergence. +* + IF( J.GT.IOUT-IINFO ) THEN + NCNVRG = .TRUE. + IB = -JB + ELSE + IB = JB + END IF + DO 50 JE = IWORK( J ) + 1 + IWOFF, + $ IWORK( J+IN ) + IWOFF + W( JE ) = TMP1 + IBLOCK( JE ) = IB + 50 CONTINUE + 60 CONTINUE +* + M = M + IM + END IF + 70 CONTINUE +* +* If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU +* If NWL+1 < IL or NWU > IU, discard extra eigenvalues. +* + IF( IRANGE.EQ.3 ) THEN + IM = 0 + IDISCL = IL - 1 - NWL + IDISCU = NWU - IU +* + IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN + DO 80 JE = 1, M + IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN + IDISCL = IDISCL - 1 + ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN + IDISCU = IDISCU - 1 + ELSE + IM = IM + 1 + W( IM ) = W( JE ) + IBLOCK( IM ) = IBLOCK( JE ) + END IF + 80 CONTINUE + M = IM + END IF + IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN +* +* Code to deal with effects of bad arithmetic: +* Some low eigenvalues to be discarded are not in (WL,WLU], +* or high eigenvalues to be discarded are not in (WUL,WU] +* so just kill off the smallest IDISCL/largest IDISCU +* eigenvalues, by simply finding the smallest/largest +* eigenvalue(s). +* +* (If N(w) is monotone non-decreasing, this should never +* happen.) +* + IF( IDISCL.GT.0 ) THEN + WKILL = WU + DO 100 JDISC = 1, IDISCL + IW = 0 + DO 90 JE = 1, M + IF( IBLOCK( JE ).NE.0 .AND. + $ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN + IW = JE + WKILL = W( JE ) + END IF + 90 CONTINUE + IBLOCK( IW ) = 0 + 100 CONTINUE + END IF + IF( IDISCU.GT.0 ) THEN +* + WKILL = WL + DO 120 JDISC = 1, IDISCU + IW = 0 + DO 110 JE = 1, M + IF( IBLOCK( JE ).NE.0 .AND. + $ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THEN + IW = JE + WKILL = W( JE ) + END IF + 110 CONTINUE + IBLOCK( IW ) = 0 + 120 CONTINUE + END IF + IM = 0 + DO 130 JE = 1, M + IF( IBLOCK( JE ).NE.0 ) THEN + IM = IM + 1 + W( IM ) = W( JE ) + IBLOCK( IM ) = IBLOCK( JE ) + END IF + 130 CONTINUE + M = IM + END IF + IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN + TOOFEW = .TRUE. + END IF + END IF +* +* If ORDER='B', do nothing -- the eigenvalues are already sorted +* by block. +* If ORDER='E', sort the eigenvalues from smallest to largest +* + IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THEN + DO 150 JE = 1, M - 1 + IE = 0 + TMP1 = W( JE ) + DO 140 J = JE + 1, M + IF( W( J ).LT.TMP1 ) THEN + IE = J + TMP1 = W( J ) + END IF + 140 CONTINUE +* + IF( IE.NE.0 ) THEN + ITMP1 = IBLOCK( IE ) + W( IE ) = W( JE ) + IBLOCK( IE ) = IBLOCK( JE ) + W( JE ) = TMP1 + IBLOCK( JE ) = ITMP1 + END IF + 150 CONTINUE + END IF +* + INFO = 0 + IF( NCNVRG ) + $ INFO = INFO + 1 + IF( TOOFEW ) + $ INFO = INFO + 2 + RETURN +* +* End of DSTEBZ +* + END diff --git a/dep/lapack/dstein.f b/dep/lapack/dstein.f new file mode 100644 index 00000000..a39a0f4c --- /dev/null +++ b/dep/lapack/dstein.f @@ -0,0 +1,361 @@ + SUBROUTINE DSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK, + $ IWORK, IFAIL, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDZ, M, N +* .. +* .. Array Arguments .. + INTEGER IBLOCK( * ), IFAIL( * ), ISPLIT( * ), + $ IWORK( * ) + DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DSTEIN computes the eigenvectors of a real symmetric tridiagonal +* matrix T corresponding to specified eigenvalues, using inverse +* iteration. +* +* The maximum number of iterations allowed for each eigenvector is +* specified by an internal parameter MAXITS (currently set to 5). +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix. N >= 0. +* +* D (input) DOUBLE PRECISION array, dimension (N) +* The n diagonal elements of the tridiagonal matrix T. +* +* E (input) DOUBLE PRECISION array, dimension (N-1) +* The (n-1) subdiagonal elements of the tridiagonal matrix +* T, in elements 1 to N-1. +* +* M (input) INTEGER +* The number of eigenvectors to be found. 0 <= M <= N. +* +* W (input) DOUBLE PRECISION array, dimension (N) +* The first M elements of W contain the eigenvalues for +* which eigenvectors are to be computed. The eigenvalues +* should be grouped by split-off block and ordered from +* smallest to largest within the block. ( The output array +* W from DSTEBZ with ORDER = 'B' is expected here. ) +* +* IBLOCK (input) INTEGER array, dimension (N) +* The submatrix indices associated with the corresponding +* eigenvalues in W; IBLOCK(i)=1 if eigenvalue W(i) belongs to +* the first submatrix from the top, =2 if W(i) belongs to +* the second submatrix, etc. ( The output array IBLOCK +* from DSTEBZ is expected here. ) +* +* ISPLIT (input) INTEGER array, dimension (N) +* The splitting points, at which T breaks up into submatrices. +* The first submatrix consists of rows/columns 1 to +* ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1 +* through ISPLIT( 2 ), etc. +* ( The output array ISPLIT from DSTEBZ is expected here. ) +* +* Z (output) DOUBLE PRECISION array, dimension (LDZ, M) +* The computed eigenvectors. The eigenvector associated +* with the eigenvalue W(i) is stored in the i-th column of +* Z. Any vector which fails to converge is set to its current +* iterate after MAXITS iterations. +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. LDZ >= max(1,N). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (5*N) +* +* IWORK (workspace) INTEGER array, dimension (N) +* +* IFAIL (output) INTEGER array, dimension (M) +* On normal exit, all elements of IFAIL are zero. +* If one or more eigenvectors fail to converge after +* MAXITS iterations, then their indices are stored in +* array IFAIL. +* +* INFO (output) INTEGER +* = 0: successful exit. +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, then i eigenvectors failed to converge +* in MAXITS iterations. Their indices are stored in +* array IFAIL. +* +* Internal Parameters +* =================== +* +* MAXITS INTEGER, default = 5 +* The maximum number of iterations performed. +* +* EXTRA INTEGER, default = 2 +* The number of iterations performed after norm growth +* criterion is satisfied, should be at least 1. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TEN, ODM3, ODM1 + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TEN = 1.0D+1, + $ ODM3 = 1.0D-3, ODM1 = 1.0D-1 ) + INTEGER MAXITS, EXTRA + PARAMETER ( MAXITS = 5, EXTRA = 2 ) +* .. +* .. Local Scalars .. + INTEGER B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1, + $ INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1, + $ JBLK, JMAX, NBLK, NRMCHK + DOUBLE PRECISION DTPCRT, EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL, + $ SCL, SEP, TOL, XJ, XJM, ZTR +* .. +* .. Local Arrays .. + INTEGER ISEED( 4 ) +* .. +* .. External Functions .. + INTEGER IDAMAX + DOUBLE PRECISION DASUM, DDOT, DLAMCH, DNRM2 + EXTERNAL IDAMAX, DASUM, DDOT, DLAMCH, DNRM2 +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DLAGTF, DLAGTS, DLARNV, DSCAL, + $ XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + DO 10 I = 1, M + IFAIL( I ) = 0 + 10 CONTINUE +* + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( M.LT.0 .OR. M.GT.N ) THEN + INFO = -4 + ELSE IF( LDZ.LT.MAX( 1, N ) ) THEN + INFO = -9 + ELSE + DO 20 J = 2, M + IF( IBLOCK( J ).LT.IBLOCK( J-1 ) ) THEN + INFO = -6 + GO TO 30 + END IF + IF( IBLOCK( J ).EQ.IBLOCK( J-1 ) .AND. W( J ).LT.W( J-1 ) ) + $ THEN + INFO = -5 + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSTEIN', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. M.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN + Z( 1, 1 ) = ONE + RETURN + END IF +* +* Get machine constants. +* + EPS = DLAMCH( 'Precision' ) +* +* Initialize seed for random number generator DLARNV. +* + DO 40 I = 1, 4 + ISEED( I ) = 1 + 40 CONTINUE +* +* Initialize pointers. +* + INDRV1 = 0 + INDRV2 = INDRV1 + N + INDRV3 = INDRV2 + N + INDRV4 = INDRV3 + N + INDRV5 = INDRV4 + N +* +* Compute eigenvectors of matrix blocks. +* + J1 = 1 + DO 160 NBLK = 1, IBLOCK( M ) +* +* Find starting and ending indices of block nblk. +* + IF( NBLK.EQ.1 ) THEN + B1 = 1 + ELSE + B1 = ISPLIT( NBLK-1 ) + 1 + END IF + BN = ISPLIT( NBLK ) + BLKSIZ = BN - B1 + 1 + IF( BLKSIZ.EQ.1 ) + $ GO TO 60 + GPIND = B1 +* +* Compute reorthogonalization criterion and stopping criterion. +* + ONENRM = ABS( D( B1 ) ) + ABS( E( B1 ) ) + ONENRM = MAX( ONENRM, ABS( D( BN ) )+ABS( E( BN-1 ) ) ) + DO 50 I = B1 + 1, BN - 1 + ONENRM = MAX( ONENRM, ABS( D( I ) )+ABS( E( I-1 ) )+ + $ ABS( E( I ) ) ) + 50 CONTINUE + ORTOL = ODM3*ONENRM +* + DTPCRT = SQRT( ODM1 / BLKSIZ ) +* +* Loop through eigenvalues of block nblk. +* + 60 CONTINUE + JBLK = 0 + DO 150 J = J1, M + IF( IBLOCK( J ).NE.NBLK ) THEN + J1 = J + GO TO 160 + END IF + JBLK = JBLK + 1 + XJ = W( J ) +* +* Skip all the work if the block size is one. +* + IF( BLKSIZ.EQ.1 ) THEN + WORK( INDRV1+1 ) = ONE + GO TO 120 + END IF +* +* If eigenvalues j and j-1 are too close, add a relatively +* small perturbation. +* + IF( JBLK.GT.1 ) THEN + EPS1 = ABS( EPS*XJ ) + PERTOL = TEN*EPS1 + SEP = XJ - XJM + IF( SEP.LT.PERTOL ) + $ XJ = XJM + PERTOL + END IF +* + ITS = 0 + NRMCHK = 0 +* +* Get random starting vector. +* + CALL DLARNV( 2, ISEED, BLKSIZ, WORK( INDRV1+1 ) ) +* +* Copy the matrix T so it won't be destroyed in factorization. +* + CALL DCOPY( BLKSIZ, D( B1 ), 1, WORK( INDRV4+1 ), 1 ) + CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV2+2 ), 1 ) + CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV3+1 ), 1 ) +* +* Compute LU factors with partial pivoting ( PT = LU ) +* + TOL = ZERO + CALL DLAGTF( BLKSIZ, WORK( INDRV4+1 ), XJ, WORK( INDRV2+2 ), + $ WORK( INDRV3+1 ), TOL, WORK( INDRV5+1 ), IWORK, + $ IINFO ) +* +* Update iteration count. +* + 70 CONTINUE + ITS = ITS + 1 + IF( ITS.GT.MAXITS ) + $ GO TO 100 +* +* Normalize and scale the righthand side vector Pb. +* + SCL = BLKSIZ*ONENRM*MAX( EPS, + $ ABS( WORK( INDRV4+BLKSIZ ) ) ) / + $ DASUM( BLKSIZ, WORK( INDRV1+1 ), 1 ) + CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 ) +* +* Solve the system LU = Pb. +* + CALL DLAGTS( -1, BLKSIZ, WORK( INDRV4+1 ), WORK( INDRV2+2 ), + $ WORK( INDRV3+1 ), WORK( INDRV5+1 ), IWORK, + $ WORK( INDRV1+1 ), TOL, IINFO ) +* +* Reorthogonalize by modified Gram-Schmidt if eigenvalues are +* close enough. +* + IF( JBLK.EQ.1 ) + $ GO TO 90 + IF( ABS( XJ-XJM ).GT.ORTOL ) + $ GPIND = J + IF( GPIND.NE.J ) THEN + DO 80 I = GPIND, J - 1 + ZTR = -DDOT( BLKSIZ, WORK( INDRV1+1 ), 1, Z( B1, I ), + $ 1 ) + CALL DAXPY( BLKSIZ, ZTR, Z( B1, I ), 1, + $ WORK( INDRV1+1 ), 1 ) + 80 CONTINUE + END IF +* +* Check the infinity norm of the iterate. +* + 90 CONTINUE + JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 ) + NRM = ABS( WORK( INDRV1+JMAX ) ) +* +* Continue for additional iterations after norm reaches +* stopping criterion. +* + IF( NRM.LT.DTPCRT ) + $ GO TO 70 + NRMCHK = NRMCHK + 1 + IF( NRMCHK.LT.EXTRA+1 ) + $ GO TO 70 +* + GO TO 110 +* +* If stopping criterion was not satisfied, update info and +* store eigenvector number in array ifail. +* + 100 CONTINUE + INFO = INFO + 1 + IFAIL( INFO ) = J +* +* Accept iterate as jth eigenvector. +* + 110 CONTINUE + SCL = ONE / DNRM2( BLKSIZ, WORK( INDRV1+1 ), 1 ) + JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 ) + IF( WORK( INDRV1+JMAX ).LT.ZERO ) + $ SCL = -SCL + CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 ) + 120 CONTINUE + DO 130 I = 1, N + Z( I, J ) = ZERO + 130 CONTINUE + DO 140 I = 1, BLKSIZ + Z( B1+I-1, J ) = WORK( INDRV1+I ) + 140 CONTINUE +* +* Save the shift to check eigenvalue spacing at next +* iteration. +* + XJM = XJ +* + 150 CONTINUE + 160 CONTINUE +* + RETURN +* +* End of DSTEIN +* + END diff --git a/dep/lapack/dsteqr.f b/dep/lapack/dsteqr.f new file mode 100644 index 00000000..0afd7957 --- /dev/null +++ b/dep/lapack/dsteqr.f @@ -0,0 +1,500 @@ + SUBROUTINE DSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER COMPZ + INTEGER INFO, LDZ, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DSTEQR computes all eigenvalues and, optionally, eigenvectors of a +* symmetric tridiagonal matrix using the implicit QL or QR method. +* The eigenvectors of a full or band symmetric matrix can also be found +* if DSYTRD or DSPTRD or DSBTRD has been used to reduce this matrix to +* tridiagonal form. +* +* Arguments +* ========= +* +* COMPZ (input) CHARACTER*1 +* = 'N': Compute eigenvalues only. +* = 'V': Compute eigenvalues and eigenvectors of the original +* symmetric matrix. On entry, Z must contain the +* orthogonal matrix used to reduce the original matrix +* to tridiagonal form. +* = 'I': Compute eigenvalues and eigenvectors of the +* tridiagonal matrix. Z is initialized to the identity +* matrix. +* +* N (input) INTEGER +* The order of the matrix. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the diagonal elements of the tridiagonal matrix. +* On exit, if INFO = 0, the eigenvalues in ascending order. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix. +* On exit, E has been destroyed. +* +* Z (input/output) DOUBLE PRECISION array, dimension (LDZ, N) +* On entry, if COMPZ = 'V', then Z contains the orthogonal +* matrix used in the reduction to tridiagonal form. +* On exit, if INFO = 0, then if COMPZ = 'V', Z contains the +* orthonormal eigenvectors of the original symmetric matrix, +* and if COMPZ = 'I', Z contains the orthonormal eigenvectors +* of the symmetric tridiagonal matrix. +* If COMPZ = 'N', then Z is not referenced. +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. LDZ >= 1, and if +* eigenvectors are desired, then LDZ >= max(1,N). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2)) +* If COMPZ = 'N', then WORK is not referenced. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: the algorithm has failed to find all the eigenvalues in +* a total of 30*N iterations; if INFO = i, then i +* elements of E have not converged to zero; on exit, D +* and E contain the elements of a symmetric tridiagonal +* matrix which is orthogonally similar to the original +* matrix. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO, THREE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, + $ THREE = 3.0D0 ) + INTEGER MAXIT + PARAMETER ( MAXIT = 30 ) +* .. +* .. Local Scalars .. + INTEGER I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND, + $ LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1, + $ NM1, NMAXIT + DOUBLE PRECISION ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2, + $ S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DLAMCH, DLANST, DLAPY2 + EXTERNAL LSAME, DLAMCH, DLANST, DLAPY2 +* .. +* .. External Subroutines .. + EXTERNAL DLAE2, DLAEV2, DLARTG, DLASCL, DLASET, DLASR, + $ DLASRT, DSWAP, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SIGN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 +* + IF( LSAME( COMPZ, 'N' ) ) THEN + ICOMPZ = 0 + ELSE IF( LSAME( COMPZ, 'V' ) ) THEN + ICOMPZ = 1 + ELSE IF( LSAME( COMPZ, 'I' ) ) THEN + ICOMPZ = 2 + ELSE + ICOMPZ = -1 + END IF + IF( ICOMPZ.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1, + $ N ) ) ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSTEQR', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + IF( N.EQ.1 ) THEN + IF( ICOMPZ.EQ.2 ) + $ Z( 1, 1 ) = ONE + RETURN + END IF +* +* Determine the unit roundoff and over/underflow thresholds. +* + EPS = DLAMCH( 'E' ) + EPS2 = EPS**2 + SAFMIN = DLAMCH( 'S' ) + SAFMAX = ONE / SAFMIN + SSFMAX = SQRT( SAFMAX ) / THREE + SSFMIN = SQRT( SAFMIN ) / EPS2 +* +* Compute the eigenvalues and eigenvectors of the tridiagonal +* matrix. +* + IF( ICOMPZ.EQ.2 ) + $ CALL DLASET( 'Full', N, N, ZERO, ONE, Z, LDZ ) +* + NMAXIT = N*MAXIT + JTOT = 0 +* +* Determine where the matrix splits and choose QL or QR iteration +* for each block, according to whether top or bottom diagonal +* element is smaller. +* + L1 = 1 + NM1 = N - 1 +* + 10 CONTINUE + IF( L1.GT.N ) + $ GO TO 160 + IF( L1.GT.1 ) + $ E( L1-1 ) = ZERO + IF( L1.LE.NM1 ) THEN + DO 20 M = L1, NM1 + TST = ABS( E( M ) ) + IF( TST.EQ.ZERO ) + $ GO TO 30 + IF( TST.LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+ + $ 1 ) ) ) )*EPS ) THEN + E( M ) = ZERO + GO TO 30 + END IF + 20 CONTINUE + END IF + M = N +* + 30 CONTINUE + L = L1 + LSV = L + LEND = M + LENDSV = LEND + L1 = M + 1 + IF( LEND.EQ.L ) + $ GO TO 10 +* +* Scale submatrix in rows and columns L to LEND +* + ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) ) + ISCALE = 0 + IF( ANORM.EQ.ZERO ) + $ GO TO 10 + IF( ANORM.GT.SSFMAX ) THEN + ISCALE = 1 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N, + $ INFO ) + ELSE IF( ANORM.LT.SSFMIN ) THEN + ISCALE = 2 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N, + $ INFO ) + END IF +* +* Choose between QL and QR iteration +* + IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN + LEND = LSV + L = LENDSV + END IF +* + IF( LEND.GT.L ) THEN +* +* QL Iteration +* +* Look for small subdiagonal element. +* + 40 CONTINUE + IF( L.NE.LEND ) THEN + LENDM1 = LEND - 1 + DO 50 M = L, LENDM1 + TST = ABS( E( M ) )**2 + IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M+1 ) )+ + $ SAFMIN )GO TO 60 + 50 CONTINUE + END IF +* + M = LEND +* + 60 CONTINUE + IF( M.LT.LEND ) + $ E( M ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 80 +* +* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 +* to compute its eigensystem. +* + IF( M.EQ.L+1 ) THEN + IF( ICOMPZ.GT.0 ) THEN + CALL DLAEV2( D( L ), E( L ), D( L+1 ), RT1, RT2, C, S ) + WORK( L ) = C + WORK( N-1+L ) = S + CALL DLASR( 'R', 'V', 'B', N, 2, WORK( L ), + $ WORK( N-1+L ), Z( 1, L ), LDZ ) + ELSE + CALL DLAE2( D( L ), E( L ), D( L+1 ), RT1, RT2 ) + END IF + D( L ) = RT1 + D( L+1 ) = RT2 + E( L ) = ZERO + L = L + 2 + IF( L.LE.LEND ) + $ GO TO 40 + GO TO 140 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 140 + JTOT = JTOT + 1 +* +* Form shift. +* + G = ( D( L+1 )-P ) / ( TWO*E( L ) ) + R = DLAPY2( G, ONE ) + G = D( M ) - P + ( E( L ) / ( G+SIGN( R, G ) ) ) +* + S = ONE + C = ONE + P = ZERO +* +* Inner loop +* + MM1 = M - 1 + DO 70 I = MM1, L, -1 + F = S*E( I ) + B = C*E( I ) + CALL DLARTG( G, F, C, S, R ) + IF( I.NE.M-1 ) + $ E( I+1 ) = R + G = D( I+1 ) - P + R = ( D( I )-G )*S + TWO*C*B + P = S*R + D( I+1 ) = G + P + G = C*R - B +* +* If eigenvectors are desired, then save rotations. +* + IF( ICOMPZ.GT.0 ) THEN + WORK( I ) = C + WORK( N-1+I ) = -S + END IF +* + 70 CONTINUE +* +* If eigenvectors are desired, then apply saved rotations. +* + IF( ICOMPZ.GT.0 ) THEN + MM = M - L + 1 + CALL DLASR( 'R', 'V', 'B', N, MM, WORK( L ), WORK( N-1+L ), + $ Z( 1, L ), LDZ ) + END IF +* + D( L ) = D( L ) - P + E( L ) = G + GO TO 40 +* +* Eigenvalue found. +* + 80 CONTINUE + D( L ) = P +* + L = L + 1 + IF( L.LE.LEND ) + $ GO TO 40 + GO TO 140 +* + ELSE +* +* QR Iteration +* +* Look for small superdiagonal element. +* + 90 CONTINUE + IF( L.NE.LEND ) THEN + LENDP1 = LEND + 1 + DO 100 M = L, LENDP1, -1 + TST = ABS( E( M-1 ) )**2 + IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M-1 ) )+ + $ SAFMIN )GO TO 110 + 100 CONTINUE + END IF +* + M = LEND +* + 110 CONTINUE + IF( M.GT.LEND ) + $ E( M-1 ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 130 +* +* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 +* to compute its eigensystem. +* + IF( M.EQ.L-1 ) THEN + IF( ICOMPZ.GT.0 ) THEN + CALL DLAEV2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2, C, S ) + WORK( M ) = C + WORK( N-1+M ) = S + CALL DLASR( 'R', 'V', 'F', N, 2, WORK( M ), + $ WORK( N-1+M ), Z( 1, L-1 ), LDZ ) + ELSE + CALL DLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 ) + END IF + D( L-1 ) = RT1 + D( L ) = RT2 + E( L-1 ) = ZERO + L = L - 2 + IF( L.GE.LEND ) + $ GO TO 90 + GO TO 140 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 140 + JTOT = JTOT + 1 +* +* Form shift. +* + G = ( D( L-1 )-P ) / ( TWO*E( L-1 ) ) + R = DLAPY2( G, ONE ) + G = D( M ) - P + ( E( L-1 ) / ( G+SIGN( R, G ) ) ) +* + S = ONE + C = ONE + P = ZERO +* +* Inner loop +* + LM1 = L - 1 + DO 120 I = M, LM1 + F = S*E( I ) + B = C*E( I ) + CALL DLARTG( G, F, C, S, R ) + IF( I.NE.M ) + $ E( I-1 ) = R + G = D( I ) - P + R = ( D( I+1 )-G )*S + TWO*C*B + P = S*R + D( I ) = G + P + G = C*R - B +* +* If eigenvectors are desired, then save rotations. +* + IF( ICOMPZ.GT.0 ) THEN + WORK( I ) = C + WORK( N-1+I ) = S + END IF +* + 120 CONTINUE +* +* If eigenvectors are desired, then apply saved rotations. +* + IF( ICOMPZ.GT.0 ) THEN + MM = L - M + 1 + CALL DLASR( 'R', 'V', 'F', N, MM, WORK( M ), WORK( N-1+M ), + $ Z( 1, M ), LDZ ) + END IF +* + D( L ) = D( L ) - P + E( LM1 ) = G + GO TO 90 +* +* Eigenvalue found. +* + 130 CONTINUE + D( L ) = P +* + L = L - 1 + IF( L.GE.LEND ) + $ GO TO 90 + GO TO 140 +* + END IF +* +* Undo scaling if necessary +* + 140 CONTINUE + IF( ISCALE.EQ.1 ) THEN + CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) + CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV, 1, E( LSV ), + $ N, INFO ) + ELSE IF( ISCALE.EQ.2 ) THEN + CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) + CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV, 1, E( LSV ), + $ N, INFO ) + END IF +* +* Check for no convergence to an eigenvalue after a total +* of N*MAXIT iterations. +* + IF( JTOT.LT.NMAXIT ) + $ GO TO 10 + DO 150 I = 1, N - 1 + IF( E( I ).NE.ZERO ) + $ INFO = INFO + 1 + 150 CONTINUE + GO TO 190 +* +* Order eigenvalues and eigenvectors. +* + 160 CONTINUE + IF( ICOMPZ.EQ.0 ) THEN +* +* Use Quick Sort +* + CALL DLASRT( 'I', N, D, INFO ) +* + ELSE +* +* Use Selection Sort to minimize swaps of eigenvectors +* + DO 180 II = 2, N + I = II - 1 + K = I + P = D( I ) + DO 170 J = II, N + IF( D( J ).LT.P ) THEN + K = J + P = D( J ) + END IF + 170 CONTINUE + IF( K.NE.I ) THEN + D( K ) = D( I ) + D( I ) = P + CALL DSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 ) + END IF + 180 CONTINUE + END IF +* + 190 CONTINUE + RETURN +* +* End of DSTEQR +* + END diff --git a/dep/lapack/dsterf.f b/dep/lapack/dsterf.f new file mode 100644 index 00000000..c17ea23a --- /dev/null +++ b/dep/lapack/dsterf.f @@ -0,0 +1,364 @@ + SUBROUTINE DSTERF( N, D, E, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* Purpose +* ======= +* +* DSTERF computes all eigenvalues of a symmetric tridiagonal matrix +* using the Pal-Walker-Kahan variant of the QL or QR algorithm. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix. +* On exit, if INFO = 0, the eigenvalues in ascending order. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix. +* On exit, E has been destroyed. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: the algorithm failed to find all of the eigenvalues in +* a total of 30*N iterations; if INFO = i, then i +* elements of E have not converged to zero. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO, THREE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, + $ THREE = 3.0D0 ) + INTEGER MAXIT + PARAMETER ( MAXIT = 30 ) +* .. +* .. Local Scalars .. + INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M, + $ NMAXIT + DOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC, + $ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN, + $ SIGMA, SSFMAX, SSFMIN +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLANST, DLAPY2 + EXTERNAL DLAMCH, DLANST, DLAPY2 +* .. +* .. External Subroutines .. + EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 +* +* Quick return if possible +* + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DSTERF', -INFO ) + RETURN + END IF + IF( N.LE.1 ) + $ RETURN +* +* Determine the unit roundoff for this environment. +* + EPS = DLAMCH( 'E' ) + EPS2 = EPS**2 + SAFMIN = DLAMCH( 'S' ) + SAFMAX = ONE / SAFMIN + SSFMAX = SQRT( SAFMAX ) / THREE + SSFMIN = SQRT( SAFMIN ) / EPS2 +* +* Compute the eigenvalues of the tridiagonal matrix. +* + NMAXIT = N*MAXIT + SIGMA = ZERO + JTOT = 0 +* +* Determine where the matrix splits and choose QL or QR iteration +* for each block, according to whether top or bottom diagonal +* element is smaller. +* + L1 = 1 +* + 10 CONTINUE + IF( L1.GT.N ) + $ GO TO 170 + IF( L1.GT.1 ) + $ E( L1-1 ) = ZERO + DO 20 M = L1, N - 1 + IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+ + $ 1 ) ) ) )*EPS ) THEN + E( M ) = ZERO + GO TO 30 + END IF + 20 CONTINUE + M = N +* + 30 CONTINUE + L = L1 + LSV = L + LEND = M + LENDSV = LEND + L1 = M + 1 + IF( LEND.EQ.L ) + $ GO TO 10 +* +* Scale submatrix in rows and columns L to LEND +* + ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) ) + ISCALE = 0 + IF( ANORM.GT.SSFMAX ) THEN + ISCALE = 1 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N, + $ INFO ) + ELSE IF( ANORM.LT.SSFMIN ) THEN + ISCALE = 2 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N, + $ INFO ) + END IF +* + DO 40 I = L, LEND - 1 + E( I ) = E( I )**2 + 40 CONTINUE +* +* Choose between QL and QR iteration +* + IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN + LEND = LSV + L = LENDSV + END IF +* + IF( LEND.GE.L ) THEN +* +* QL Iteration +* +* Look for small subdiagonal element. +* + 50 CONTINUE + IF( L.NE.LEND ) THEN + DO 60 M = L, LEND - 1 + IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) ) + $ GO TO 70 + 60 CONTINUE + END IF + M = LEND +* + 70 CONTINUE + IF( M.LT.LEND ) + $ E( M ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 90 +* +* If remaining matrix is 2 by 2, use DLAE2 to compute its +* eigenvalues. +* + IF( M.EQ.L+1 ) THEN + RTE = SQRT( E( L ) ) + CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 ) + D( L ) = RT1 + D( L+1 ) = RT2 + E( L ) = ZERO + L = L + 2 + IF( L.LE.LEND ) + $ GO TO 50 + GO TO 150 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 150 + JTOT = JTOT + 1 +* +* Form shift. +* + RTE = SQRT( E( L ) ) + SIGMA = ( D( L+1 )-P ) / ( TWO*RTE ) + R = DLAPY2( SIGMA, ONE ) + SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) ) +* + C = ONE + S = ZERO + GAMMA = D( M ) - SIGMA + P = GAMMA*GAMMA +* +* Inner loop +* + DO 80 I = M - 1, L, -1 + BB = E( I ) + R = P + BB + IF( I.NE.M-1 ) + $ E( I+1 ) = S*R + OLDC = C + C = P / R + S = BB / R + OLDGAM = GAMMA + ALPHA = D( I ) + GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM + D( I+1 ) = OLDGAM + ( ALPHA-GAMMA ) + IF( C.NE.ZERO ) THEN + P = ( GAMMA*GAMMA ) / C + ELSE + P = OLDC*BB + END IF + 80 CONTINUE +* + E( L ) = S*P + D( L ) = SIGMA + GAMMA + GO TO 50 +* +* Eigenvalue found. +* + 90 CONTINUE + D( L ) = P +* + L = L + 1 + IF( L.LE.LEND ) + $ GO TO 50 + GO TO 150 +* + ELSE +* +* QR Iteration +* +* Look for small superdiagonal element. +* + 100 CONTINUE + DO 110 M = L, LEND + 1, -1 + IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) ) + $ GO TO 120 + 110 CONTINUE + M = LEND +* + 120 CONTINUE + IF( M.GT.LEND ) + $ E( M-1 ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 140 +* +* If remaining matrix is 2 by 2, use DLAE2 to compute its +* eigenvalues. +* + IF( M.EQ.L-1 ) THEN + RTE = SQRT( E( L-1 ) ) + CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 ) + D( L ) = RT1 + D( L-1 ) = RT2 + E( L-1 ) = ZERO + L = L - 2 + IF( L.GE.LEND ) + $ GO TO 100 + GO TO 150 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 150 + JTOT = JTOT + 1 +* +* Form shift. +* + RTE = SQRT( E( L-1 ) ) + SIGMA = ( D( L-1 )-P ) / ( TWO*RTE ) + R = DLAPY2( SIGMA, ONE ) + SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) ) +* + C = ONE + S = ZERO + GAMMA = D( M ) - SIGMA + P = GAMMA*GAMMA +* +* Inner loop +* + DO 130 I = M, L - 1 + BB = E( I ) + R = P + BB + IF( I.NE.M ) + $ E( I-1 ) = S*R + OLDC = C + C = P / R + S = BB / R + OLDGAM = GAMMA + ALPHA = D( I+1 ) + GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM + D( I ) = OLDGAM + ( ALPHA-GAMMA ) + IF( C.NE.ZERO ) THEN + P = ( GAMMA*GAMMA ) / C + ELSE + P = OLDC*BB + END IF + 130 CONTINUE +* + E( L-1 ) = S*P + D( L ) = SIGMA + GAMMA + GO TO 100 +* +* Eigenvalue found. +* + 140 CONTINUE + D( L ) = P +* + L = L - 1 + IF( L.GE.LEND ) + $ GO TO 100 + GO TO 150 +* + END IF +* +* Undo scaling if necessary +* + 150 CONTINUE + IF( ISCALE.EQ.1 ) + $ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) + IF( ISCALE.EQ.2 ) + $ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) +* +* Check for no convergence to an eigenvalue after a total +* of N*MAXIT iterations. +* + IF( JTOT.LT.NMAXIT ) + $ GO TO 10 + DO 160 I = 1, N - 1 + IF( E( I ).NE.ZERO ) + $ INFO = INFO + 1 + 160 CONTINUE + GO TO 180 +* +* Sort eigenvalues in increasing order. +* + 170 CONTINUE + CALL DLASRT( 'I', N, D, INFO ) +* + 180 CONTINUE + RETURN +* +* End of DSTERF +* + END diff --git a/dep/lapack/dstev.f b/dep/lapack/dstev.f new file mode 100644 index 00000000..3354167a --- /dev/null +++ b/dep/lapack/dstev.f @@ -0,0 +1,164 @@ + SUBROUTINE DSTEV( JOBZ, N, D, E, Z, LDZ, WORK, INFO ) +* +* -- LAPACK driver routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER JOBZ + INTEGER INFO, LDZ, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DSTEV computes all eigenvalues and, optionally, eigenvectors of a +* real symmetric tridiagonal matrix A. +* +* Arguments +* ========= +* +* JOBZ (input) CHARACTER*1 +* = 'N': Compute eigenvalues only; +* = 'V': Compute eigenvalues and eigenvectors. +* +* N (input) INTEGER +* The order of the matrix. N >= 0. +* +* D (input/output) DOUBLE PRECISION array, dimension (N) +* On entry, the n diagonal elements of the tridiagonal matrix +* A. +* On exit, if INFO = 0, the eigenvalues in ascending order. +* +* E (input/output) DOUBLE PRECISION array, dimension (N-1) +* On entry, the (n-1) subdiagonal elements of the tridiagonal +* matrix A, stored in elements 1 to N-1 of E. +* On exit, the contents of E are destroyed. +* +* Z (output) DOUBLE PRECISION array, dimension (LDZ, N) +* If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal +* eigenvectors of the matrix A, with the i-th column of Z +* holding the eigenvector associated with D(i). +* If JOBZ = 'N', then Z is not referenced. +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. LDZ >= 1, and if +* JOBZ = 'V', LDZ >= max(1,N). +* +* WORK (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2)) +* If JOBZ = 'N', WORK is not referenced. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the algorithm failed to converge; i +* off-diagonal elements of E did not converge to zero. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL WANTZ + INTEGER IMAX, ISCALE + DOUBLE PRECISION BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA, SMLNUM, + $ TNRM +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DLAMCH, DLANST + EXTERNAL LSAME, DLAMCH, DLANST +* .. +* .. External Subroutines .. + EXTERNAL DSCAL, DSTEQR, DSTERF, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + WANTZ = LSAME( JOBZ, 'V' ) +* + INFO = 0 + IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN + INFO = -6 + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSTEV ', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* + IF( N.EQ.1 ) THEN + IF( WANTZ ) + $ Z( 1, 1 ) = ONE + RETURN + END IF +* +* Get machine constants. +* + SAFMIN = DLAMCH( 'Safe minimum' ) + EPS = DLAMCH( 'Precision' ) + SMLNUM = SAFMIN / EPS + BIGNUM = ONE / SMLNUM + RMIN = SQRT( SMLNUM ) + RMAX = SQRT( BIGNUM ) +* +* Scale matrix to allowable range, if necessary. +* + ISCALE = 0 + TNRM = DLANST( 'M', N, D, E ) + IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THEN + ISCALE = 1 + SIGMA = RMIN / TNRM + ELSE IF( TNRM.GT.RMAX ) THEN + ISCALE = 1 + SIGMA = RMAX / TNRM + END IF + IF( ISCALE.EQ.1 ) THEN + CALL DSCAL( N, SIGMA, D, 1 ) + CALL DSCAL( N-1, SIGMA, E( 1 ), 1 ) + END IF +* +* For eigenvalues only, call DSTERF. For eigenvalues and +* eigenvectors, call DSTEQR. +* + IF( .NOT.WANTZ ) THEN + CALL DSTERF( N, D, E, INFO ) + ELSE + CALL DSTEQR( 'I', N, D, E, Z, LDZ, WORK, INFO ) + END IF +* +* If matrix was scaled, then rescale eigenvalues appropriately. +* + IF( ISCALE.EQ.1 ) THEN + IF( INFO.EQ.0 ) THEN + IMAX = N + ELSE + IMAX = INFO - 1 + END IF + CALL DSCAL( IMAX, ONE / SIGMA, D, 1 ) + END IF +* + RETURN +* +* End of DSTEV +* + END diff --git a/dep/lapack/dsyevx.f b/dep/lapack/dsyevx.f new file mode 100644 index 00000000..8ea48b21 --- /dev/null +++ b/dep/lapack/dsyevx.f @@ -0,0 +1,433 @@ + SUBROUTINE DSYEVX( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU, IL, IU, + $ ABSTOL, M, W, Z, LDZ, WORK, LWORK, IWORK, + $ IFAIL, INFO ) +* +* -- LAPACK driver routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER JOBZ, RANGE, UPLO + INTEGER IL, INFO, IU, LDA, LDZ, LWORK, M, N + DOUBLE PRECISION ABSTOL, VL, VU +* .. +* .. Array Arguments .. + INTEGER IFAIL( * ), IWORK( * ) + DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DSYEVX computes selected eigenvalues and, optionally, eigenvectors +* of a real symmetric matrix A. Eigenvalues and eigenvectors can be +* selected by specifying either a range of values or a range of indices +* for the desired eigenvalues. +* +* Arguments +* ========= +* +* JOBZ (input) CHARACTER*1 +* = 'N': Compute eigenvalues only; +* = 'V': Compute eigenvalues and eigenvectors. +* +* RANGE (input) CHARACTER*1 +* = 'A': all eigenvalues will be found. +* = 'V': all eigenvalues in the half-open interval (VL,VU] +* will be found. +* = 'I': the IL-th through IU-th eigenvalues will be found. +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA, N) +* On entry, the symmetric matrix A. If UPLO = 'U', the +* leading N-by-N upper triangular part of A contains the +* upper triangular part of the matrix A. If UPLO = 'L', +* the leading N-by-N lower triangular part of A contains +* the lower triangular part of the matrix A. +* On exit, the lower triangle (if UPLO='L') or the upper +* triangle (if UPLO='U') of A, including the diagonal, is +* destroyed. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* VL (input) DOUBLE PRECISION +* VU (input) DOUBLE PRECISION +* If RANGE='V', the lower and upper bounds of the interval to +* be searched for eigenvalues. VL < VU. +* Not referenced if RANGE = 'A' or 'I'. +* +* IL (input) INTEGER +* IU (input) INTEGER +* If RANGE='I', the indices (in ascending order) of the +* smallest and largest eigenvalues to be returned. +* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. +* Not referenced if RANGE = 'A' or 'V'. +* +* ABSTOL (input) DOUBLE PRECISION +* The absolute error tolerance for the eigenvalues. +* An approximate eigenvalue is accepted as converged +* when it is determined to lie in an interval [a,b] +* of width less than or equal to +* +* ABSTOL + EPS * max( |a|,|b| ) , +* +* where EPS is the machine precision. If ABSTOL is less than +* or equal to zero, then EPS*|T| will be used in its place, +* where |T| is the 1-norm of the tridiagonal matrix obtained +* by reducing A to tridiagonal form. +* +* Eigenvalues will be computed most accurately when ABSTOL is +* set to twice the underflow threshold 2*DLAMCH('S'), not zero. +* If this routine returns with INFO>0, indicating that some +* eigenvectors did not converge, try setting ABSTOL to +* 2*DLAMCH('S'). +* +* See "Computing Small Singular Values of Bidiagonal Matrices +* with Guaranteed High Relative Accuracy," by Demmel and +* Kahan, LAPACK Working Note #3. +* +* M (output) INTEGER +* The total number of eigenvalues found. 0 <= M <= N. +* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. +* +* W (output) DOUBLE PRECISION array, dimension (N) +* On normal exit, the first M elements contain the selected +* eigenvalues in ascending order. +* +* Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M)) +* If JOBZ = 'V', then if INFO = 0, the first M columns of Z +* contain the orthonormal eigenvectors of the matrix A +* corresponding to the selected eigenvalues, with the i-th +* column of Z holding the eigenvector associated with W(i). +* If an eigenvector fails to converge, then that column of Z +* contains the latest approximation to the eigenvector, and the +* index of the eigenvector is returned in IFAIL. +* If JOBZ = 'N', then Z is not referenced. +* Note: the user must ensure that at least max(1,M) columns are +* supplied in the array Z; if RANGE = 'V', the exact value of M +* is not known in advance and an upper bound must be used. +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. LDZ >= 1, and if +* JOBZ = 'V', LDZ >= max(1,N). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The length of the array WORK. LWORK >= 1, when N <= 1; +* otherwise 8*N. +* For optimal efficiency, LWORK >= (NB+3)*N, +* where NB is the max of the blocksize for DSYTRD and DORMTR +* returned by ILAENV. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* IWORK (workspace) INTEGER array, dimension (5*N) +* +* IFAIL (output) INTEGER array, dimension (N) +* If JOBZ = 'V', then if INFO = 0, the first M elements of +* IFAIL are zero. If INFO > 0, then IFAIL contains the +* indices of the eigenvectors that failed to converge. +* If JOBZ = 'N', then IFAIL is not referenced. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, then i eigenvectors failed to converge. +* Their indices are stored in array IFAIL. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, TEST, VALEIG, + $ WANTZ + CHARACTER ORDER + INTEGER I, IINFO, IMAX, INDD, INDE, INDEE, INDIBL, + $ INDISP, INDIWO, INDTAU, INDWKN, INDWRK, ISCALE, + $ ITMP1, J, JJ, LLWORK, LLWRKN, LWKMIN, + $ LWKOPT, NB, NSPLIT + DOUBLE PRECISION ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, + $ SIGMA, SMLNUM, TMP1, VLL, VUU +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + DOUBLE PRECISION DLAMCH, DLANSY + EXTERNAL LSAME, ILAENV, DLAMCH, DLANSY +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DLACPY, DORGTR, DORMTR, DSCAL, DSTEBZ, + $ DSTEIN, DSTEQR, DSTERF, DSWAP, DSYTRD, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + LOWER = LSAME( UPLO, 'L' ) + WANTZ = LSAME( JOBZ, 'V' ) + ALLEIG = LSAME( RANGE, 'A' ) + VALEIG = LSAME( RANGE, 'V' ) + INDEIG = LSAME( RANGE, 'I' ) + LQUERY = ( LWORK.EQ.-1 ) +* + INFO = 0 + IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN + INFO = -1 + ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN + INFO = -2 + ELSE IF( .NOT.( LOWER .OR. LSAME( UPLO, 'U' ) ) ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -6 + ELSE + IF( VALEIG ) THEN + IF( N.GT.0 .AND. VU.LE.VL ) + $ INFO = -8 + ELSE IF( INDEIG ) THEN + IF( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) THEN + INFO = -9 + ELSE IF( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) THEN + INFO = -10 + END IF + END IF + END IF + IF( INFO.EQ.0 ) THEN + IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN + INFO = -15 + END IF + END IF +* + IF( INFO.EQ.0 ) THEN + IF( N.LE.1 ) THEN + LWKMIN = 1 + WORK( 1 ) = LWKMIN + ELSE + LWKMIN = 8*N + NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 ) + NB = MAX( NB, ILAENV( 1, 'DORMTR', UPLO, N, -1, -1, -1 ) ) + LWKOPT = MAX( LWKMIN, ( NB + 3 )*N ) + WORK( 1 ) = LWKOPT + END IF +* + IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) + $ INFO = -17 + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSYEVX', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + M = 0 + IF( N.EQ.0 ) THEN + RETURN + END IF +* + IF( N.EQ.1 ) THEN + IF( ALLEIG .OR. INDEIG ) THEN + M = 1 + W( 1 ) = A( 1, 1 ) + ELSE + IF( VL.LT.A( 1, 1 ) .AND. VU.GE.A( 1, 1 ) ) THEN + M = 1 + W( 1 ) = A( 1, 1 ) + END IF + END IF + IF( WANTZ ) + $ Z( 1, 1 ) = ONE + RETURN + END IF +* +* Get machine constants. +* + SAFMIN = DLAMCH( 'Safe minimum' ) + EPS = DLAMCH( 'Precision' ) + SMLNUM = SAFMIN / EPS + BIGNUM = ONE / SMLNUM + RMIN = SQRT( SMLNUM ) + RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) ) +* +* Scale matrix to allowable range, if necessary. +* + ISCALE = 0 + ABSTLL = ABSTOL + IF( VALEIG ) THEN + VLL = VL + VUU = VU + END IF + ANRM = DLANSY( 'M', UPLO, N, A, LDA, WORK ) + IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN + ISCALE = 1 + SIGMA = RMIN / ANRM + ELSE IF( ANRM.GT.RMAX ) THEN + ISCALE = 1 + SIGMA = RMAX / ANRM + END IF + IF( ISCALE.EQ.1 ) THEN + IF( LOWER ) THEN + DO 10 J = 1, N + CALL DSCAL( N-J+1, SIGMA, A( J, J ), 1 ) + 10 CONTINUE + ELSE + DO 20 J = 1, N + CALL DSCAL( J, SIGMA, A( 1, J ), 1 ) + 20 CONTINUE + END IF + IF( ABSTOL.GT.0 ) + $ ABSTLL = ABSTOL*SIGMA + IF( VALEIG ) THEN + VLL = VL*SIGMA + VUU = VU*SIGMA + END IF + END IF +* +* Call DSYTRD to reduce symmetric matrix to tridiagonal form. +* + INDTAU = 1 + INDE = INDTAU + N + INDD = INDE + N + INDWRK = INDD + N + LLWORK = LWORK - INDWRK + 1 + CALL DSYTRD( UPLO, N, A, LDA, WORK( INDD ), WORK( INDE ), + $ WORK( INDTAU ), WORK( INDWRK ), LLWORK, IINFO ) +* +* If all eigenvalues are desired and ABSTOL is less than or equal to +* zero, then call DSTERF or DORGTR and SSTEQR. If this fails for +* some eigenvalue, then try DSTEBZ. +* + TEST = .FALSE. + IF( INDEIG ) THEN + IF( IL.EQ.1 .AND. IU.EQ.N ) THEN + TEST = .TRUE. + END IF + END IF + IF( ( ALLEIG .OR. TEST ) .AND. ( ABSTOL.LE.ZERO ) ) THEN + CALL DCOPY( N, WORK( INDD ), 1, W, 1 ) + INDEE = INDWRK + 2*N + IF( .NOT.WANTZ ) THEN + CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 ) + CALL DSTERF( N, W, WORK( INDEE ), INFO ) + ELSE + CALL DLACPY( 'A', N, N, A, LDA, Z, LDZ ) + CALL DORGTR( UPLO, N, Z, LDZ, WORK( INDTAU ), + $ WORK( INDWRK ), LLWORK, IINFO ) + CALL DCOPY( N-1, WORK( INDE ), 1, WORK( INDEE ), 1 ) + CALL DSTEQR( JOBZ, N, W, WORK( INDEE ), Z, LDZ, + $ WORK( INDWRK ), INFO ) + IF( INFO.EQ.0 ) THEN + DO 30 I = 1, N + IFAIL( I ) = 0 + 30 CONTINUE + END IF + END IF + IF( INFO.EQ.0 ) THEN + M = N + GO TO 40 + END IF + INFO = 0 + END IF +* +* Otherwise, call DSTEBZ and, if eigenvectors are desired, SSTEIN. +* + IF( WANTZ ) THEN + ORDER = 'B' + ELSE + ORDER = 'E' + END IF + INDIBL = 1 + INDISP = INDIBL + N + INDIWO = INDISP + N + CALL DSTEBZ( RANGE, ORDER, N, VLL, VUU, IL, IU, ABSTLL, + $ WORK( INDD ), WORK( INDE ), M, NSPLIT, W, + $ IWORK( INDIBL ), IWORK( INDISP ), WORK( INDWRK ), + $ IWORK( INDIWO ), INFO ) +* + IF( WANTZ ) THEN + CALL DSTEIN( N, WORK( INDD ), WORK( INDE ), M, W, + $ IWORK( INDIBL ), IWORK( INDISP ), Z, LDZ, + $ WORK( INDWRK ), IWORK( INDIWO ), IFAIL, INFO ) +* +* Apply orthogonal matrix used in reduction to tridiagonal +* form to eigenvectors returned by DSTEIN. +* + INDWKN = INDE + LLWRKN = LWORK - INDWKN + 1 + CALL DORMTR( 'L', UPLO, 'N', N, M, A, LDA, WORK( INDTAU ), Z, + $ LDZ, WORK( INDWKN ), LLWRKN, IINFO ) + END IF +* +* If matrix was scaled, then rescale eigenvalues appropriately. +* + 40 CONTINUE + IF( ISCALE.EQ.1 ) THEN + IF( INFO.EQ.0 ) THEN + IMAX = M + ELSE + IMAX = INFO - 1 + END IF + CALL DSCAL( IMAX, ONE / SIGMA, W, 1 ) + END IF +* +* If eigenvalues are not in order, then sort them, along with +* eigenvectors. +* + IF( WANTZ ) THEN + DO 60 J = 1, M - 1 + I = 0 + TMP1 = W( J ) + DO 50 JJ = J + 1, M + IF( W( JJ ).LT.TMP1 ) THEN + I = JJ + TMP1 = W( JJ ) + END IF + 50 CONTINUE +* + IF( I.NE.0 ) THEN + ITMP1 = IWORK( INDIBL+I-1 ) + W( I ) = W( J ) + IWORK( INDIBL+I-1 ) = IWORK( INDIBL+J-1 ) + W( J ) = TMP1 + IWORK( INDIBL+J-1 ) = ITMP1 + CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 ) + IF( INFO.NE.0 ) THEN + ITMP1 = IFAIL( I ) + IFAIL( I ) = IFAIL( J ) + IFAIL( J ) = ITMP1 + END IF + END IF + 60 CONTINUE + END IF +* +* Set WORK(1) to optimal workspace size. +* + WORK( 1 ) = LWKOPT +* + RETURN +* +* End of DSYEVX +* + END diff --git a/dep/lapack/dsytd2.f b/dep/lapack/dsytd2.f new file mode 100644 index 00000000..c696818e --- /dev/null +++ b/dep/lapack/dsytd2.f @@ -0,0 +1,248 @@ + SUBROUTINE DSYTD2( UPLO, N, A, LDA, D, E, TAU, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * ) +* .. +* +* Purpose +* ======= +* +* DSYTD2 reduces a real symmetric matrix A to symmetric tridiagonal +* form T by an orthogonal similarity transformation: Q' * A * Q = T. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the upper or lower triangular part of the +* symmetric matrix A is stored: +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the symmetric matrix A. If UPLO = 'U', the leading +* n-by-n upper triangular part of A contains the upper +* triangular part of the matrix A, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading n-by-n lower triangular part of A contains the lower +* triangular part of the matrix A, and the strictly upper +* triangular part of A is not referenced. +* On exit, if UPLO = 'U', the diagonal and first superdiagonal +* of A are overwritten by the corresponding elements of the +* tridiagonal matrix T, and the elements above the first +* superdiagonal, with the array TAU, represent the orthogonal +* matrix Q as a product of elementary reflectors; if UPLO +* = 'L', the diagonal and first subdiagonal of A are over- +* written by the corresponding elements of the tridiagonal +* matrix T, and the elements below the first subdiagonal, with +* the array TAU, represent the orthogonal matrix Q as a product +* of elementary reflectors. See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* D (output) DOUBLE PRECISION array, dimension (N) +* The diagonal elements of the tridiagonal matrix T: +* D(i) = A(i,i). +* +* E (output) DOUBLE PRECISION array, dimension (N-1) +* The off-diagonal elements of the tridiagonal matrix T: +* E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'. +* +* TAU (output) DOUBLE PRECISION array, dimension (N-1) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value. +* +* Further Details +* =============== +* +* If UPLO = 'U', the matrix Q is represented as a product of elementary +* reflectors +* +* Q = H(n-1) . . . H(2) H(1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in +* A(1:i-1,i+1), and tau in TAU(i). +* +* If UPLO = 'L', the matrix Q is represented as a product of elementary +* reflectors +* +* Q = H(1) H(2) . . . H(n-1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i), +* and tau in TAU(i). +* +* The contents of A on exit are illustrated by the following examples +* with n = 5: +* +* if UPLO = 'U': if UPLO = 'L': +* +* ( d e v2 v3 v4 ) ( d ) +* ( d e v3 v4 ) ( e d ) +* ( d e v4 ) ( v1 e d ) +* ( d e ) ( v1 v2 e d ) +* ( d ) ( v1 v2 v3 e d ) +* +* where d and e denote diagonal and off-diagonal elements of T, and vi +* denotes an element of the vector defining H(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO, HALF + PARAMETER ( ONE = 1.0D0, ZERO = 0.0D0, + $ HALF = 1.0D0 / 2.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL UPPER + INTEGER I + DOUBLE PRECISION ALPHA, TAUI +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DLARFG, DSYMV, DSYR2, XERBLA +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DDOT + EXTERNAL LSAME, DDOT +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSYTD2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.0 ) + $ RETURN +* + IF( UPPER ) THEN +* +* Reduce the upper triangle of A +* + DO 10 I = N - 1, 1, -1 +* +* Generate elementary reflector H(i) = I - tau * v * v' +* to annihilate A(1:i-1,i+1) +* + CALL DLARFG( I, A( I, I+1 ), A( 1, I+1 ), 1, TAUI ) + E( I ) = A( I, I+1 ) +* + IF( TAUI.NE.ZERO ) THEN +* +* Apply H(i) from both sides to A(1:i,1:i) +* + A( I, I+1 ) = ONE +* +* Compute x := tau * A * v storing x in TAU(1:i) +* + CALL DSYMV( UPLO, I, TAUI, A, LDA, A( 1, I+1 ), 1, ZERO, + $ TAU, 1 ) +* +* Compute w := x - 1/2 * tau * (x'*v) * v +* + ALPHA = -HALF*TAUI*DDOT( I, TAU, 1, A( 1, I+1 ), 1 ) + CALL DAXPY( I, ALPHA, A( 1, I+1 ), 1, TAU, 1 ) +* +* Apply the transformation as a rank-2 update: +* A := A - v * w' - w * v' +* + CALL DSYR2( UPLO, I, -ONE, A( 1, I+1 ), 1, TAU, 1, A, + $ LDA ) +* + A( I, I+1 ) = E( I ) + END IF + D( I+1 ) = A( I+1, I+1 ) + TAU( I ) = TAUI + 10 CONTINUE + D( 1 ) = A( 1, 1 ) + ELSE +* +* Reduce the lower triangle of A +* + DO 20 I = 1, N - 1 +* +* Generate elementary reflector H(i) = I - tau * v * v' +* to annihilate A(i+2:n,i) +* + CALL DLARFG( N-I, A( I+1, I ), A( MIN( I+2, N ), I ), 1, + $ TAUI ) + E( I ) = A( I+1, I ) +* + IF( TAUI.NE.ZERO ) THEN +* +* Apply H(i) from both sides to A(i+1:n,i+1:n) +* + A( I+1, I ) = ONE +* +* Compute x := tau * A * v storing y in TAU(i:n-1) +* + CALL DSYMV( UPLO, N-I, TAUI, A( I+1, I+1 ), LDA, + $ A( I+1, I ), 1, ZERO, TAU( I ), 1 ) +* +* Compute w := x - 1/2 * tau * (x'*v) * v +* + ALPHA = -HALF*TAUI*DDOT( N-I, TAU( I ), 1, A( I+1, I ), + $ 1 ) + CALL DAXPY( N-I, ALPHA, A( I+1, I ), 1, TAU( I ), 1 ) +* +* Apply the transformation as a rank-2 update: +* A := A - v * w' - w * v' +* + CALL DSYR2( UPLO, N-I, -ONE, A( I+1, I ), 1, TAU( I ), 1, + $ A( I+1, I+1 ), LDA ) +* + A( I+1, I ) = E( I ) + END IF + D( I ) = A( I, I ) + TAU( I ) = TAUI + 20 CONTINUE + D( N ) = A( N, N ) + END IF +* + RETURN +* +* End of DSYTD2 +* + END diff --git a/dep/lapack/dsytrd.f b/dep/lapack/dsytrd.f new file mode 100644 index 00000000..569ee35b --- /dev/null +++ b/dep/lapack/dsytrd.f @@ -0,0 +1,294 @@ + SUBROUTINE DSYTRD( UPLO, N, A, LDA, D, E, TAU, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER INFO, LDA, LWORK, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), D( * ), E( * ), TAU( * ), + $ WORK( * ) +* .. +* +* Purpose +* ======= +* +* DSYTRD reduces a real symmetric matrix A to real symmetric +* tridiagonal form T by an orthogonal similarity transformation: +* Q**T * A * Q = T. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the symmetric matrix A. If UPLO = 'U', the leading +* N-by-N upper triangular part of A contains the upper +* triangular part of the matrix A, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading N-by-N lower triangular part of A contains the lower +* triangular part of the matrix A, and the strictly upper +* triangular part of A is not referenced. +* On exit, if UPLO = 'U', the diagonal and first superdiagonal +* of A are overwritten by the corresponding elements of the +* tridiagonal matrix T, and the elements above the first +* superdiagonal, with the array TAU, represent the orthogonal +* matrix Q as a product of elementary reflectors; if UPLO +* = 'L', the diagonal and first subdiagonal of A are over- +* written by the corresponding elements of the tridiagonal +* matrix T, and the elements below the first subdiagonal, with +* the array TAU, represent the orthogonal matrix Q as a product +* of elementary reflectors. See Further Details. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* D (output) DOUBLE PRECISION array, dimension (N) +* The diagonal elements of the tridiagonal matrix T: +* D(i) = A(i,i). +* +* E (output) DOUBLE PRECISION array, dimension (N-1) +* The off-diagonal elements of the tridiagonal matrix T: +* E(i) = A(i,i+1) if UPLO = 'U', E(i) = A(i+1,i) if UPLO = 'L'. +* +* TAU (output) DOUBLE PRECISION array, dimension (N-1) +* The scalar factors of the elementary reflectors (see Further +* Details). +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= 1. +* For optimum performance LWORK >= N*NB, where NB is the +* optimal blocksize. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* Further Details +* =============== +* +* If UPLO = 'U', the matrix Q is represented as a product of elementary +* reflectors +* +* Q = H(n-1) . . . H(2) H(1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(i+1:n) = 0 and v(i) = 1; v(1:i-1) is stored on exit in +* A(1:i-1,i+1), and tau in TAU(i). +* +* If UPLO = 'L', the matrix Q is represented as a product of elementary +* reflectors +* +* Q = H(1) H(2) . . . H(n-1). +* +* Each H(i) has the form +* +* H(i) = I - tau * v * v' +* +* where tau is a real scalar, and v is a real vector with +* v(1:i) = 0 and v(i+1) = 1; v(i+2:n) is stored on exit in A(i+2:n,i), +* and tau in TAU(i). +* +* The contents of A on exit are illustrated by the following examples +* with n = 5: +* +* if UPLO = 'U': if UPLO = 'L': +* +* ( d e v2 v3 v4 ) ( d ) +* ( d e v3 v4 ) ( e d ) +* ( d e v4 ) ( v1 e d ) +* ( d e ) ( v1 v2 e d ) +* ( d ) ( v1 v2 v3 e d ) +* +* where d and e denote diagonal and off-diagonal elements of T, and vi +* denotes an element of the vector defining H(i). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY, UPPER + INTEGER I, IINFO, IWS, J, KK, LDWORK, LWKOPT, NB, + $ NBMIN, NX +* .. +* .. External Subroutines .. + EXTERNAL DLATRD, DSYR2K, DSYTD2, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. Executable Statements .. +* +* Test the input parameters +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + LQUERY = ( LWORK.EQ.-1 ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THEN + INFO = -9 + END IF +* + IF( INFO.EQ.0 ) THEN +* +* Determine the block size. +* + NB = ILAENV( 1, 'DSYTRD', UPLO, N, -1, -1, -1 ) + LWKOPT = N*NB + WORK( 1 ) = LWKOPT + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DSYTRD', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) THEN + WORK( 1 ) = 1 + RETURN + END IF +* + NX = N + IWS = 1 + IF( NB.GT.1 .AND. NB.LT.N ) THEN +* +* Determine when to cross over from blocked to unblocked code +* (last block is always handled by unblocked code). +* + NX = MAX( NB, ILAENV( 3, 'DSYTRD', UPLO, N, -1, -1, -1 ) ) + IF( NX.LT.N ) THEN +* +* Determine if workspace is large enough for blocked code. +* + LDWORK = N + IWS = LDWORK*NB + IF( LWORK.LT.IWS ) THEN +* +* Not enough workspace to use optimal NB: determine the +* minimum value of NB, and reduce NB or force use of +* unblocked code by setting NX = N. +* + NB = MAX( LWORK / LDWORK, 1 ) + NBMIN = ILAENV( 2, 'DSYTRD', UPLO, N, -1, -1, -1 ) + IF( NB.LT.NBMIN ) + $ NX = N + END IF + ELSE + NX = N + END IF + ELSE + NB = 1 + END IF +* + IF( UPPER ) THEN +* +* Reduce the upper triangle of A. +* Columns 1:kk are handled by the unblocked method. +* + KK = N - ( ( N-NX+NB-1 ) / NB )*NB + DO 20 I = N - NB + 1, KK + 1, -NB +* +* Reduce columns i:i+nb-1 to tridiagonal form and form the +* matrix W which is needed to update the unreduced part of +* the matrix +* + CALL DLATRD( UPLO, I+NB-1, NB, A, LDA, E, TAU, WORK, + $ LDWORK ) +* +* Update the unreduced submatrix A(1:i-1,1:i-1), using an +* update of the form: A := A - V*W' - W*V' +* + CALL DSYR2K( UPLO, 'No transpose', I-1, NB, -ONE, A( 1, I ), + $ LDA, WORK, LDWORK, ONE, A, LDA ) +* +* Copy superdiagonal elements back into A, and diagonal +* elements into D +* + DO 10 J = I, I + NB - 1 + A( J-1, J ) = E( J-1 ) + D( J ) = A( J, J ) + 10 CONTINUE + 20 CONTINUE +* +* Use unblocked code to reduce the last or only block +* + CALL DSYTD2( UPLO, KK, A, LDA, D, E, TAU, IINFO ) + ELSE +* +* Reduce the lower triangle of A +* + DO 40 I = 1, N - NX, NB +* +* Reduce columns i:i+nb-1 to tridiagonal form and form the +* matrix W which is needed to update the unreduced part of +* the matrix +* + CALL DLATRD( UPLO, N-I+1, NB, A( I, I ), LDA, E( I ), + $ TAU( I ), WORK, LDWORK ) +* +* Update the unreduced submatrix A(i+ib:n,i+ib:n), using +* an update of the form: A := A - V*W' - W*V' +* + CALL DSYR2K( UPLO, 'No transpose', N-I-NB+1, NB, -ONE, + $ A( I+NB, I ), LDA, WORK( NB+1 ), LDWORK, ONE, + $ A( I+NB, I+NB ), LDA ) +* +* Copy subdiagonal elements back into A, and diagonal +* elements into D +* + DO 30 J = I, I + NB - 1 + A( J+1, J ) = E( J ) + D( J ) = A( J, J ) + 30 CONTINUE + 40 CONTINUE +* +* Use unblocked code to reduce the last or only block +* + CALL DSYTD2( UPLO, N-I+1, A( I, I ), LDA, D( I ), E( I ), + $ TAU( I ), IINFO ) + END IF +* + WORK( 1 ) = LWKOPT + RETURN +* +* End of DSYTRD +* + END diff --git a/dep/lapack/dtrevc.f b/dep/lapack/dtrevc.f new file mode 100644 index 00000000..09e9048e --- /dev/null +++ b/dep/lapack/dtrevc.f @@ -0,0 +1,989 @@ + SUBROUTINE DTREVC( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR, + $ LDVR, MM, M, WORK, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER HOWMNY, SIDE + INTEGER INFO, LDT, LDVL, LDVR, M, MM, N +* .. +* .. Array Arguments .. + LOGICAL SELECT( * ) + DOUBLE PRECISION T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ), + $ WORK( * ) +* .. +* +* Purpose +* ======= +* +* DTREVC computes some or all of the right and/or left eigenvectors of +* a real upper quasi-triangular matrix T. +* +* The right eigenvector x and the left eigenvector y of T corresponding +* to an eigenvalue w are defined by: +* +* T*x = w*x, y'*T = w*y' +* +* where y' denotes the conjugate transpose of the vector y. +* +* If all eigenvectors are requested, the routine may either return the +* matrices X and/or Y of right or left eigenvectors of T, or the +* products Q*X and/or Q*Y, where Q is an input orthogonal +* matrix. If T was obtained from the real-Schur factorization of an +* original matrix A = Q*T*Q', then Q*X and Q*Y are the matrices of +* right or left eigenvectors of A. +* +* T must be in Schur canonical form (as returned by DHSEQR), that is, +* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each +* 2-by-2 diagonal block has its diagonal elements equal and its +* off-diagonal elements of opposite sign. Corresponding to each 2-by-2 +* diagonal block is a complex conjugate pair of eigenvalues and +* eigenvectors; only one eigenvector of the pair is computed, namely +* the one corresponding to the eigenvalue with positive imaginary part. +* +* +* Arguments +* ========= +* +* SIDE (input) CHARACTER*1 +* = 'R': compute right eigenvectors only; +* = 'L': compute left eigenvectors only; +* = 'B': compute both right and left eigenvectors. +* +* HOWMNY (input) CHARACTER*1 +* = 'A': compute all right and/or left eigenvectors; +* = 'B': compute all right and/or left eigenvectors, +* and backtransform them using the input matrices +* supplied in VR and/or VL; +* = 'S': compute selected right and/or left eigenvectors, +* specified by the logical array SELECT. +* +* SELECT (input/output) LOGICAL array, dimension (N) +* If HOWMNY = 'S', SELECT specifies the eigenvectors to be +* computed. +* If HOWMNY = 'A' or 'B', SELECT is not referenced. +* To select the real eigenvector corresponding to a real +* eigenvalue w(j), SELECT(j) must be set to .TRUE.. To select +* the complex eigenvector corresponding to a complex conjugate +* pair w(j) and w(j+1), either SELECT(j) or SELECT(j+1) must be +* set to .TRUE.; then on exit SELECT(j) is .TRUE. and +* SELECT(j+1) is .FALSE.. +* +* N (input) INTEGER +* The order of the matrix T. N >= 0. +* +* T (input) DOUBLE PRECISION array, dimension (LDT,N) +* The upper quasi-triangular matrix T in Schur canonical form. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= max(1,N). +* +* VL (input/output) DOUBLE PRECISION array, dimension (LDVL,MM) +* On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must +* contain an N-by-N matrix Q (usually the orthogonal matrix Q +* of Schur vectors returned by DHSEQR). +* On exit, if SIDE = 'L' or 'B', VL contains: +* if HOWMNY = 'A', the matrix Y of left eigenvectors of T; +* if HOWMNY = 'B', the matrix Q*Y; +* if HOWMNY = 'S', the left eigenvectors of T specified by +* SELECT, stored consecutively in the columns +* of VL, in the same order as their +* eigenvalues. +* A complex eigenvector corresponding to a complex eigenvalue +* is stored in two consecutive columns, the first holding the +* real part, and the second the imaginary part. +* If SIDE = 'R', VL is not referenced. +* +* LDVL (input) INTEGER +* The leading dimension of the array VL. LDVL >= max(1,N) if +* SIDE = 'L' or 'B'; LDVL >= 1 otherwise. +* +* VR (input/output) DOUBLE PRECISION array, dimension (LDVR,MM) +* On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must +* contain an N-by-N matrix Q (usually the orthogonal matrix Q +* of Schur vectors returned by DHSEQR). +* On exit, if SIDE = 'R' or 'B', VR contains: +* if HOWMNY = 'A', the matrix X of right eigenvectors of T; +* if HOWMNY = 'B', the matrix Q*X; +* if HOWMNY = 'S', the right eigenvectors of T specified by +* SELECT, stored consecutively in the columns +* of VR, in the same order as their +* eigenvalues. +* A complex eigenvector corresponding to a complex eigenvalue +* is stored in two consecutive columns, the first holding the +* real part and the second the imaginary part. +* If SIDE = 'L', VR is not referenced. +* +* LDVR (input) INTEGER +* The leading dimension of the array VR. LDVR >= max(1,N) if +* SIDE = 'R' or 'B'; LDVR >= 1 otherwise. +* +* MM (input) INTEGER +* The number of columns in the arrays VL and/or VR. MM >= M. +* +* M (output) INTEGER +* The number of columns in the arrays VL and/or VR actually +* used to store the eigenvectors. +* If HOWMNY = 'A' or 'B', M is set to N. +* Each selected real eigenvector occupies one column and each +* selected complex eigenvector occupies two columns. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (3*N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* Further Details +* =============== +* +* The algorithm used in this program is basically backward (forward) +* substitution, with scaling to make the the code robust against +* possible overflow. +* +* Each eigenvector is normalized so that the element of largest +* magnitude has magnitude 1; here the magnitude of a complex number +* (x,y) is taken to be |x| + |y|. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL ALLV, BOTHV, LEFTV, OVER, PAIR, RIGHTV, SOMEV + INTEGER I, IERR, II, IP, IS, J, J1, J2, JNXT, K, KI, N2 + DOUBLE PRECISION BETA, BIGNUM, EMAX, OVFL, REC, REMAX, SCALE, + $ SMIN, SMLNUM, ULP, UNFL, VCRIT, VMAX, WI, WR, + $ XNORM +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER IDAMAX + DOUBLE PRECISION DDOT, DLAMCH + EXTERNAL LSAME, IDAMAX, DDOT, DLAMCH +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DGEMV, DLABAD, DLALN2, DSCAL, + $ XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Local Arrays .. + DOUBLE PRECISION X( 2, 2 ) +* .. +* .. Executable Statements .. +* +* Decode and test the input parameters +* + BOTHV = LSAME( SIDE, 'B' ) + RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHV + LEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV +* + ALLV = LSAME( HOWMNY, 'A' ) + OVER = LSAME( HOWMNY, 'B' ) .OR. LSAME( HOWMNY, 'O' ) + SOMEV = LSAME( HOWMNY, 'S' ) +* + INFO = 0 + IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THEN + INFO = -1 + ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( LDT.LT.MAX( 1, N ) ) THEN + INFO = -6 + ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THEN + INFO = -8 + ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THEN + INFO = -10 + ELSE +* +* Set M to the number of columns required to store the selected +* eigenvectors, standardize the array SELECT if necessary, and +* test MM. +* + IF( SOMEV ) THEN + M = 0 + PAIR = .FALSE. + DO 10 J = 1, N + IF( PAIR ) THEN + PAIR = .FALSE. + SELECT( J ) = .FALSE. + ELSE + IF( J.LT.N ) THEN + IF( T( J+1, J ).EQ.ZERO ) THEN + IF( SELECT( J ) ) + $ M = M + 1 + ELSE + PAIR = .TRUE. + IF( SELECT( J ) .OR. SELECT( J+1 ) ) THEN + SELECT( J ) = .TRUE. + M = M + 2 + END IF + END IF + ELSE + IF( SELECT( N ) ) + $ M = M + 1 + END IF + END IF + 10 CONTINUE + ELSE + M = N + END IF +* + IF( MM.LT.M ) THEN + INFO = -11 + END IF + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTREVC', -INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( N.EQ.0 ) + $ RETURN +* +* Set the constants to control overflow. +* + UNFL = DLAMCH( 'Safe minimum' ) + OVFL = ONE / UNFL + CALL DLABAD( UNFL, OVFL ) + ULP = DLAMCH( 'Precision' ) + SMLNUM = UNFL*( N / ULP ) + BIGNUM = ( ONE-ULP ) / SMLNUM +* +* Compute 1-norm of each column of strictly upper triangular +* part of T to control overflow in triangular solver. +* + WORK( 1 ) = ZERO + DO 30 J = 2, N + WORK( J ) = ZERO + DO 20 I = 1, J - 1 + WORK( J ) = WORK( J ) + ABS( T( I, J ) ) + 20 CONTINUE + 30 CONTINUE +* +* Index IP is used to specify the real or complex eigenvalue: +* IP = 0, real eigenvalue, +* 1, first of conjugate complex pair: (wr,wi) +* -1, second of conjugate complex pair: (wr,wi) +* + N2 = 2*N +* + IF( RIGHTV ) THEN +* +* Compute right eigenvectors. +* + IP = 0 + IS = M + DO 140 KI = N, 1, -1 +* + IF( IP.EQ.1 ) + $ GO TO 130 + IF( KI.EQ.1 ) + $ GO TO 40 + IF( T( KI, KI-1 ).EQ.ZERO ) + $ GO TO 40 + IP = -1 +* + 40 CONTINUE + IF( SOMEV ) THEN + IF( IP.EQ.0 ) THEN + IF( .NOT.SELECT( KI ) ) + $ GO TO 130 + ELSE + IF( .NOT.SELECT( KI-1 ) ) + $ GO TO 130 + END IF + END IF +* +* Compute the KI-th eigenvalue (WR,WI). +* + WR = T( KI, KI ) + WI = ZERO + IF( IP.NE.0 ) + $ WI = SQRT( ABS( T( KI, KI-1 ) ) )* + $ SQRT( ABS( T( KI-1, KI ) ) ) + SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM ) +* + IF( IP.EQ.0 ) THEN +* +* Real right eigenvector +* + WORK( KI+N ) = ONE +* +* Form right-hand side +* + DO 50 K = 1, KI - 1 + WORK( K+N ) = -T( K, KI ) + 50 CONTINUE +* +* Solve the upper quasi-triangular system: +* (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK. +* + JNXT = KI - 1 + DO 60 J = KI - 1, 1, -1 + IF( J.GT.JNXT ) + $ GO TO 60 + J1 = J + J2 = J + JNXT = J - 1 + IF( J.GT.1 ) THEN + IF( T( J, J-1 ).NE.ZERO ) THEN + J1 = J - 1 + JNXT = J - 2 + END IF + END IF +* + IF( J1.EQ.J2 ) THEN +* +* 1-by-1 diagonal block +* + CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ), + $ LDT, ONE, ONE, WORK( J+N ), N, WR, + $ ZERO, X, 2, SCALE, XNORM, IERR ) +* +* Scale X(1,1) to avoid overflow when updating +* the right-hand side. +* + IF( XNORM.GT.ONE ) THEN + IF( WORK( J ).GT.BIGNUM / XNORM ) THEN + X( 1, 1 ) = X( 1, 1 ) / XNORM + SCALE = SCALE / XNORM + END IF + END IF +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) + $ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) + WORK( J+N ) = X( 1, 1 ) +* +* Update right-hand side +* + CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1, + $ WORK( 1+N ), 1 ) +* + ELSE +* +* 2-by-2 diagonal block +* + CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, + $ T( J-1, J-1 ), LDT, ONE, ONE, + $ WORK( J-1+N ), N, WR, ZERO, X, 2, + $ SCALE, XNORM, IERR ) +* +* Scale X(1,1) and X(2,1) to avoid overflow when +* updating the right-hand side. +* + IF( XNORM.GT.ONE ) THEN + BETA = MAX( WORK( J-1 ), WORK( J ) ) + IF( BETA.GT.BIGNUM / XNORM ) THEN + X( 1, 1 ) = X( 1, 1 ) / XNORM + X( 2, 1 ) = X( 2, 1 ) / XNORM + SCALE = SCALE / XNORM + END IF + END IF +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) + $ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) + WORK( J-1+N ) = X( 1, 1 ) + WORK( J+N ) = X( 2, 1 ) +* +* Update right-hand side +* + CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1, + $ WORK( 1+N ), 1 ) + CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1, + $ WORK( 1+N ), 1 ) + END IF + 60 CONTINUE +* +* Copy the vector x or Q*x to VR and normalize. +* + IF( .NOT.OVER ) THEN + CALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS ), 1 ) +* + II = IDAMAX( KI, VR( 1, IS ), 1 ) + REMAX = ONE / ABS( VR( II, IS ) ) + CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 ) +* + DO 70 K = KI + 1, N + VR( K, IS ) = ZERO + 70 CONTINUE + ELSE + IF( KI.GT.1 ) + $ CALL DGEMV( 'N', N, KI-1, ONE, VR, LDVR, + $ WORK( 1+N ), 1, WORK( KI+N ), + $ VR( 1, KI ), 1 ) +* + II = IDAMAX( N, VR( 1, KI ), 1 ) + REMAX = ONE / ABS( VR( II, KI ) ) + CALL DSCAL( N, REMAX, VR( 1, KI ), 1 ) + END IF +* + ELSE +* +* Complex right eigenvector. +* +* Initial solve +* [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0. +* [ (T(KI,KI-1) T(KI,KI) ) ] +* + IF( ABS( T( KI-1, KI ) ).GE.ABS( T( KI, KI-1 ) ) ) THEN + WORK( KI-1+N ) = ONE + WORK( KI+N2 ) = WI / T( KI-1, KI ) + ELSE + WORK( KI-1+N ) = -WI / T( KI, KI-1 ) + WORK( KI+N2 ) = ONE + END IF + WORK( KI+N ) = ZERO + WORK( KI-1+N2 ) = ZERO +* +* Form right-hand side +* + DO 80 K = 1, KI - 2 + WORK( K+N ) = -WORK( KI-1+N )*T( K, KI-1 ) + WORK( K+N2 ) = -WORK( KI+N2 )*T( K, KI ) + 80 CONTINUE +* +* Solve upper quasi-triangular system: +* (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2) +* + JNXT = KI - 2 + DO 90 J = KI - 2, 1, -1 + IF( J.GT.JNXT ) + $ GO TO 90 + J1 = J + J2 = J + JNXT = J - 1 + IF( J.GT.1 ) THEN + IF( T( J, J-1 ).NE.ZERO ) THEN + J1 = J - 1 + JNXT = J - 2 + END IF + END IF +* + IF( J1.EQ.J2 ) THEN +* +* 1-by-1 diagonal block +* + CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ), + $ LDT, ONE, ONE, WORK( J+N ), N, WR, WI, + $ X, 2, SCALE, XNORM, IERR ) +* +* Scale X(1,1) and X(1,2) to avoid overflow when +* updating the right-hand side. +* + IF( XNORM.GT.ONE ) THEN + IF( WORK( J ).GT.BIGNUM / XNORM ) THEN + X( 1, 1 ) = X( 1, 1 ) / XNORM + X( 1, 2 ) = X( 1, 2 ) / XNORM + SCALE = SCALE / XNORM + END IF + END IF +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) THEN + CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) + CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 ) + END IF + WORK( J+N ) = X( 1, 1 ) + WORK( J+N2 ) = X( 1, 2 ) +* +* Update the right-hand side +* + CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1, + $ WORK( 1+N ), 1 ) + CALL DAXPY( J-1, -X( 1, 2 ), T( 1, J ), 1, + $ WORK( 1+N2 ), 1 ) +* + ELSE +* +* 2-by-2 diagonal block +* + CALL DLALN2( .FALSE., 2, 2, SMIN, ONE, + $ T( J-1, J-1 ), LDT, ONE, ONE, + $ WORK( J-1+N ), N, WR, WI, X, 2, SCALE, + $ XNORM, IERR ) +* +* Scale X to avoid overflow when updating +* the right-hand side. +* + IF( XNORM.GT.ONE ) THEN + BETA = MAX( WORK( J-1 ), WORK( J ) ) + IF( BETA.GT.BIGNUM / XNORM ) THEN + REC = ONE / XNORM + X( 1, 1 ) = X( 1, 1 )*REC + X( 1, 2 ) = X( 1, 2 )*REC + X( 2, 1 ) = X( 2, 1 )*REC + X( 2, 2 ) = X( 2, 2 )*REC + SCALE = SCALE*REC + END IF + END IF +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) THEN + CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) + CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 ) + END IF + WORK( J-1+N ) = X( 1, 1 ) + WORK( J+N ) = X( 2, 1 ) + WORK( J-1+N2 ) = X( 1, 2 ) + WORK( J+N2 ) = X( 2, 2 ) +* +* Update the right-hand side +* + CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1, + $ WORK( 1+N ), 1 ) + CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1, + $ WORK( 1+N ), 1 ) + CALL DAXPY( J-2, -X( 1, 2 ), T( 1, J-1 ), 1, + $ WORK( 1+N2 ), 1 ) + CALL DAXPY( J-2, -X( 2, 2 ), T( 1, J ), 1, + $ WORK( 1+N2 ), 1 ) + END IF + 90 CONTINUE +* +* Copy the vector x or Q*x to VR and normalize. +* + IF( .NOT.OVER ) THEN + CALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS-1 ), 1 ) + CALL DCOPY( KI, WORK( 1+N2 ), 1, VR( 1, IS ), 1 ) +* + EMAX = ZERO + DO 100 K = 1, KI + EMAX = MAX( EMAX, ABS( VR( K, IS-1 ) )+ + $ ABS( VR( K, IS ) ) ) + 100 CONTINUE +* + REMAX = ONE / EMAX + CALL DSCAL( KI, REMAX, VR( 1, IS-1 ), 1 ) + CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 ) +* + DO 110 K = KI + 1, N + VR( K, IS-1 ) = ZERO + VR( K, IS ) = ZERO + 110 CONTINUE +* + ELSE +* + IF( KI.GT.2 ) THEN + CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR, + $ WORK( 1+N ), 1, WORK( KI-1+N ), + $ VR( 1, KI-1 ), 1 ) + CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR, + $ WORK( 1+N2 ), 1, WORK( KI+N2 ), + $ VR( 1, KI ), 1 ) + ELSE + CALL DSCAL( N, WORK( KI-1+N ), VR( 1, KI-1 ), 1 ) + CALL DSCAL( N, WORK( KI+N2 ), VR( 1, KI ), 1 ) + END IF +* + EMAX = ZERO + DO 120 K = 1, N + EMAX = MAX( EMAX, ABS( VR( K, KI-1 ) )+ + $ ABS( VR( K, KI ) ) ) + 120 CONTINUE + REMAX = ONE / EMAX + CALL DSCAL( N, REMAX, VR( 1, KI-1 ), 1 ) + CALL DSCAL( N, REMAX, VR( 1, KI ), 1 ) + END IF + END IF +* + IS = IS - 1 + IF( IP.NE.0 ) + $ IS = IS - 1 + 130 CONTINUE + IF( IP.EQ.1 ) + $ IP = 0 + IF( IP.EQ.-1 ) + $ IP = 1 + 140 CONTINUE + END IF +* + IF( LEFTV ) THEN +* +* Compute left eigenvectors. +* + IP = 0 + IS = 1 + DO 260 KI = 1, N +* + IF( IP.EQ.-1 ) + $ GO TO 250 + IF( KI.EQ.N ) + $ GO TO 150 + IF( T( KI+1, KI ).EQ.ZERO ) + $ GO TO 150 + IP = 1 +* + 150 CONTINUE + IF( SOMEV ) THEN + IF( .NOT.SELECT( KI ) ) + $ GO TO 250 + END IF +* +* Compute the KI-th eigenvalue (WR,WI). +* + WR = T( KI, KI ) + WI = ZERO + IF( IP.NE.0 ) + $ WI = SQRT( ABS( T( KI, KI+1 ) ) )* + $ SQRT( ABS( T( KI+1, KI ) ) ) + SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM ) +* + IF( IP.EQ.0 ) THEN +* +* Real left eigenvector. +* + WORK( KI+N ) = ONE +* +* Form right-hand side +* + DO 160 K = KI + 1, N + WORK( K+N ) = -T( KI, K ) + 160 CONTINUE +* +* Solve the quasi-triangular system: +* (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK +* + VMAX = ONE + VCRIT = BIGNUM +* + JNXT = KI + 1 + DO 170 J = KI + 1, N + IF( J.LT.JNXT ) + $ GO TO 170 + J1 = J + J2 = J + JNXT = J + 1 + IF( J.LT.N ) THEN + IF( T( J+1, J ).NE.ZERO ) THEN + J2 = J + 1 + JNXT = J + 2 + END IF + END IF +* + IF( J1.EQ.J2 ) THEN +* +* 1-by-1 diagonal block +* +* Scale if necessary to avoid overflow when forming +* the right-hand side. +* + IF( WORK( J ).GT.VCRIT ) THEN + REC = ONE / VMAX + CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) + VMAX = ONE + VCRIT = BIGNUM + END IF +* + WORK( J+N ) = WORK( J+N ) - + $ DDOT( J-KI-1, T( KI+1, J ), 1, + $ WORK( KI+1+N ), 1 ) +* +* Solve (T(J,J)-WR)'*X = WORK +* + CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ), + $ LDT, ONE, ONE, WORK( J+N ), N, WR, + $ ZERO, X, 2, SCALE, XNORM, IERR ) +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) + $ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) + WORK( J+N ) = X( 1, 1 ) + VMAX = MAX( ABS( WORK( J+N ) ), VMAX ) + VCRIT = BIGNUM / VMAX +* + ELSE +* +* 2-by-2 diagonal block +* +* Scale if necessary to avoid overflow when forming +* the right-hand side. +* + BETA = MAX( WORK( J ), WORK( J+1 ) ) + IF( BETA.GT.VCRIT ) THEN + REC = ONE / VMAX + CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) + VMAX = ONE + VCRIT = BIGNUM + END IF +* + WORK( J+N ) = WORK( J+N ) - + $ DDOT( J-KI-1, T( KI+1, J ), 1, + $ WORK( KI+1+N ), 1 ) +* + WORK( J+1+N ) = WORK( J+1+N ) - + $ DDOT( J-KI-1, T( KI+1, J+1 ), 1, + $ WORK( KI+1+N ), 1 ) +* +* Solve +* [T(J,J)-WR T(J,J+1) ]'* X = SCALE*( WORK1 ) +* [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 ) +* + CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, T( J, J ), + $ LDT, ONE, ONE, WORK( J+N ), N, WR, + $ ZERO, X, 2, SCALE, XNORM, IERR ) +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) + $ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) + WORK( J+N ) = X( 1, 1 ) + WORK( J+1+N ) = X( 2, 1 ) +* + VMAX = MAX( ABS( WORK( J+N ) ), + $ ABS( WORK( J+1+N ) ), VMAX ) + VCRIT = BIGNUM / VMAX +* + END IF + 170 CONTINUE +* +* Copy the vector x or Q*x to VL and normalize. +* + IF( .NOT.OVER ) THEN + CALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 ) +* + II = IDAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1 + REMAX = ONE / ABS( VL( II, IS ) ) + CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 ) +* + DO 180 K = 1, KI - 1 + VL( K, IS ) = ZERO + 180 CONTINUE +* + ELSE +* + IF( KI.LT.N ) + $ CALL DGEMV( 'N', N, N-KI, ONE, VL( 1, KI+1 ), LDVL, + $ WORK( KI+1+N ), 1, WORK( KI+N ), + $ VL( 1, KI ), 1 ) +* + II = IDAMAX( N, VL( 1, KI ), 1 ) + REMAX = ONE / ABS( VL( II, KI ) ) + CALL DSCAL( N, REMAX, VL( 1, KI ), 1 ) +* + END IF +* + ELSE +* +* Complex left eigenvector. +* +* Initial solve: +* ((T(KI,KI) T(KI,KI+1) )' - (WR - I* WI))*X = 0. +* ((T(KI+1,KI) T(KI+1,KI+1)) ) +* + IF( ABS( T( KI, KI+1 ) ).GE.ABS( T( KI+1, KI ) ) ) THEN + WORK( KI+N ) = WI / T( KI, KI+1 ) + WORK( KI+1+N2 ) = ONE + ELSE + WORK( KI+N ) = ONE + WORK( KI+1+N2 ) = -WI / T( KI+1, KI ) + END IF + WORK( KI+1+N ) = ZERO + WORK( KI+N2 ) = ZERO +* +* Form right-hand side +* + DO 190 K = KI + 2, N + WORK( K+N ) = -WORK( KI+N )*T( KI, K ) + WORK( K+N2 ) = -WORK( KI+1+N2 )*T( KI+1, K ) + 190 CONTINUE +* +* Solve complex quasi-triangular system: +* ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2 +* + VMAX = ONE + VCRIT = BIGNUM +* + JNXT = KI + 2 + DO 200 J = KI + 2, N + IF( J.LT.JNXT ) + $ GO TO 200 + J1 = J + J2 = J + JNXT = J + 1 + IF( J.LT.N ) THEN + IF( T( J+1, J ).NE.ZERO ) THEN + J2 = J + 1 + JNXT = J + 2 + END IF + END IF +* + IF( J1.EQ.J2 ) THEN +* +* 1-by-1 diagonal block +* +* Scale if necessary to avoid overflow when +* forming the right-hand side elements. +* + IF( WORK( J ).GT.VCRIT ) THEN + REC = ONE / VMAX + CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) + CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 ) + VMAX = ONE + VCRIT = BIGNUM + END IF +* + WORK( J+N ) = WORK( J+N ) - + $ DDOT( J-KI-2, T( KI+2, J ), 1, + $ WORK( KI+2+N ), 1 ) + WORK( J+N2 ) = WORK( J+N2 ) - + $ DDOT( J-KI-2, T( KI+2, J ), 1, + $ WORK( KI+2+N2 ), 1 ) +* +* Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2 +* + CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ), + $ LDT, ONE, ONE, WORK( J+N ), N, WR, + $ -WI, X, 2, SCALE, XNORM, IERR ) +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) THEN + CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) + CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 ) + END IF + WORK( J+N ) = X( 1, 1 ) + WORK( J+N2 ) = X( 1, 2 ) + VMAX = MAX( ABS( WORK( J+N ) ), + $ ABS( WORK( J+N2 ) ), VMAX ) + VCRIT = BIGNUM / VMAX +* + ELSE +* +* 2-by-2 diagonal block +* +* Scale if necessary to avoid overflow when forming +* the right-hand side elements. +* + BETA = MAX( WORK( J ), WORK( J+1 ) ) + IF( BETA.GT.VCRIT ) THEN + REC = ONE / VMAX + CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) + CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 ) + VMAX = ONE + VCRIT = BIGNUM + END IF +* + WORK( J+N ) = WORK( J+N ) - + $ DDOT( J-KI-2, T( KI+2, J ), 1, + $ WORK( KI+2+N ), 1 ) +* + WORK( J+N2 ) = WORK( J+N2 ) - + $ DDOT( J-KI-2, T( KI+2, J ), 1, + $ WORK( KI+2+N2 ), 1 ) +* + WORK( J+1+N ) = WORK( J+1+N ) - + $ DDOT( J-KI-2, T( KI+2, J+1 ), 1, + $ WORK( KI+2+N ), 1 ) +* + WORK( J+1+N2 ) = WORK( J+1+N2 ) - + $ DDOT( J-KI-2, T( KI+2, J+1 ), 1, + $ WORK( KI+2+N2 ), 1 ) +* +* Solve 2-by-2 complex linear equation +* ([T(j,j) T(j,j+1) ]'-(wr-i*wi)*I)*X = SCALE*B +* ([T(j+1,j) T(j+1,j+1)] ) +* + CALL DLALN2( .TRUE., 2, 2, SMIN, ONE, T( J, J ), + $ LDT, ONE, ONE, WORK( J+N ), N, WR, + $ -WI, X, 2, SCALE, XNORM, IERR ) +* +* Scale if necessary +* + IF( SCALE.NE.ONE ) THEN + CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) + CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 ) + END IF + WORK( J+N ) = X( 1, 1 ) + WORK( J+N2 ) = X( 1, 2 ) + WORK( J+1+N ) = X( 2, 1 ) + WORK( J+1+N2 ) = X( 2, 2 ) + VMAX = MAX( ABS( X( 1, 1 ) ), ABS( X( 1, 2 ) ), + $ ABS( X( 2, 1 ) ), ABS( X( 2, 2 ) ), VMAX ) + VCRIT = BIGNUM / VMAX +* + END IF + 200 CONTINUE +* +* Copy the vector x or Q*x to VL and normalize. +* + 210 CONTINUE + IF( .NOT.OVER ) THEN + CALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 ) + CALL DCOPY( N-KI+1, WORK( KI+N2 ), 1, VL( KI, IS+1 ), + $ 1 ) +* + EMAX = ZERO + DO 220 K = KI, N + EMAX = MAX( EMAX, ABS( VL( K, IS ) )+ + $ ABS( VL( K, IS+1 ) ) ) + 220 CONTINUE + REMAX = ONE / EMAX + CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 ) + CALL DSCAL( N-KI+1, REMAX, VL( KI, IS+1 ), 1 ) +* + DO 230 K = 1, KI - 1 + VL( K, IS ) = ZERO + VL( K, IS+1 ) = ZERO + 230 CONTINUE + ELSE + IF( KI.LT.N-1 ) THEN + CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ), + $ LDVL, WORK( KI+2+N ), 1, WORK( KI+N ), + $ VL( 1, KI ), 1 ) + CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ), + $ LDVL, WORK( KI+2+N2 ), 1, + $ WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 ) + ELSE + CALL DSCAL( N, WORK( KI+N ), VL( 1, KI ), 1 ) + CALL DSCAL( N, WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 ) + END IF +* + EMAX = ZERO + DO 240 K = 1, N + EMAX = MAX( EMAX, ABS( VL( K, KI ) )+ + $ ABS( VL( K, KI+1 ) ) ) + 240 CONTINUE + REMAX = ONE / EMAX + CALL DSCAL( N, REMAX, VL( 1, KI ), 1 ) + CALL DSCAL( N, REMAX, VL( 1, KI+1 ), 1 ) +* + END IF +* + END IF +* + IS = IS + 1 + IF( IP.NE.0 ) + $ IS = IS + 1 + 250 CONTINUE + IF( IP.EQ.-1 ) + $ IP = 0 + IF( IP.EQ.1 ) + $ IP = -1 +* + 260 CONTINUE +* + END IF +* + RETURN +* +* End of DTREVC +* + END diff --git a/dep/lapack/dtrexc.f b/dep/lapack/dtrexc.f new file mode 100644 index 00000000..dbd5c506 --- /dev/null +++ b/dep/lapack/dtrexc.f @@ -0,0 +1,346 @@ + SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK, + $ INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* March 31, 1993 +* +* .. Scalar Arguments .. + CHARACTER COMPQ + INTEGER IFST, ILST, INFO, LDQ, LDT, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* DTREXC reorders the real Schur factorization of a real matrix +* A = Q*T*Q**T, so that the diagonal block of T with row index IFST is +* moved to row ILST. +* +* The real Schur form T is reordered by an orthogonal similarity +* transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors +* is updated by postmultiplying it with Z. +* +* T must be in Schur canonical form (as returned by DHSEQR), that is, +* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each +* 2-by-2 diagonal block has its diagonal elements equal and its +* off-diagonal elements of opposite sign. +* +* Arguments +* ========= +* +* COMPQ (input) CHARACTER*1 +* = 'V': update the matrix Q of Schur vectors; +* = 'N': do not update Q. +* +* N (input) INTEGER +* The order of the matrix T. N >= 0. +* +* T (input/output) DOUBLE PRECISION array, dimension (LDT,N) +* On entry, the upper quasi-triangular matrix T, in Schur +* Schur canonical form. +* On exit, the reordered upper quasi-triangular matrix, again +* in Schur canonical form. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= max(1,N). +* +* Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N) +* On entry, if COMPQ = 'V', the matrix Q of Schur vectors. +* On exit, if COMPQ = 'V', Q has been postmultiplied by the +* orthogonal transformation matrix Z which reorders T. +* If COMPQ = 'N', Q is not referenced. +* +* LDQ (input) INTEGER +* The leading dimension of the array Q. LDQ >= max(1,N). +* +* IFST (input/output) INTEGER +* ILST (input/output) INTEGER +* Specify the reordering of the diagonal blocks of T. +* The block with row index IFST is moved to row ILST, by a +* sequence of transpositions between adjacent blocks. +* On exit, if IFST pointed on entry to the second row of a +* 2-by-2 block, it is changed to point to the first row; ILST +* always points to the first row of the block in its final +* position (which may differ from its input value by +1 or -1). +* 1 <= IFST <= N; 1 <= ILST <= N. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (N) +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* = 1: two adjacent blocks were too close to swap (the problem +* is very ill-conditioned); T may have been partially +* reordered, and ILST points to the first row of the +* current position of the block being moved. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL WANTQ + INTEGER HERE, NBF, NBL, NBNEXT +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DLAEXC, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Decode and test the input arguments. +* + INFO = 0 + WANTQ = LSAME( COMPQ, 'V' ) + IF( .NOT.WANTQ .AND. .NOT.LSAME( COMPQ, 'N' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDT.LT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.MAX( 1, N ) ) ) THEN + INFO = -6 + ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN + INFO = -7 + ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTREXC', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* +* Determine the first row of specified block +* and find out it is 1 by 1 or 2 by 2. +* + IF( IFST.GT.1 ) THEN + IF( T( IFST, IFST-1 ).NE.ZERO ) + $ IFST = IFST - 1 + END IF + NBF = 1 + IF( IFST.LT.N ) THEN + IF( T( IFST+1, IFST ).NE.ZERO ) + $ NBF = 2 + END IF +* +* Determine the first row of the final block +* and find out it is 1 by 1 or 2 by 2. +* + IF( ILST.GT.1 ) THEN + IF( T( ILST, ILST-1 ).NE.ZERO ) + $ ILST = ILST - 1 + END IF + NBL = 1 + IF( ILST.LT.N ) THEN + IF( T( ILST+1, ILST ).NE.ZERO ) + $ NBL = 2 + END IF +* + IF( IFST.EQ.ILST ) + $ RETURN +* + IF( IFST.LT.ILST ) THEN +* +* Update ILST +* + IF( NBF.EQ.2 .AND. NBL.EQ.1 ) + $ ILST = ILST - 1 + IF( NBF.EQ.1 .AND. NBL.EQ.2 ) + $ ILST = ILST + 1 +* + HERE = IFST +* + 10 CONTINUE +* +* Swap block with next one below +* + IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN +* +* Current block either 1 by 1 or 2 by 2 +* + NBNEXT = 1 + IF( HERE+NBF+1.LE.N ) THEN + IF( T( HERE+NBF+1, HERE+NBF ).NE.ZERO ) + $ NBNEXT = 2 + END IF + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBF, NBNEXT, + $ WORK, INFO ) + IF( INFO.NE.0 ) THEN + ILST = HERE + RETURN + END IF + HERE = HERE + NBNEXT +* +* Test if 2 by 2 block breaks into two 1 by 1 blocks +* + IF( NBF.EQ.2 ) THEN + IF( T( HERE+1, HERE ).EQ.ZERO ) + $ NBF = 3 + END IF +* + ELSE +* +* Current block consists of two 1 by 1 blocks each of which +* must be swapped individually +* + NBNEXT = 1 + IF( HERE+3.LE.N ) THEN + IF( T( HERE+3, HERE+2 ).NE.ZERO ) + $ NBNEXT = 2 + END IF + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, NBNEXT, + $ WORK, INFO ) + IF( INFO.NE.0 ) THEN + ILST = HERE + RETURN + END IF + IF( NBNEXT.EQ.1 ) THEN +* +* Swap two 1 by 1 blocks, no problems possible +* + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, NBNEXT, + $ WORK, INFO ) + HERE = HERE + 1 + ELSE +* +* Recompute NBNEXT in case 2 by 2 split +* + IF( T( HERE+2, HERE+1 ).EQ.ZERO ) + $ NBNEXT = 1 + IF( NBNEXT.EQ.2 ) THEN +* +* 2 by 2 Block did not split +* + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, + $ NBNEXT, WORK, INFO ) + IF( INFO.NE.0 ) THEN + ILST = HERE + RETURN + END IF + HERE = HERE + 2 + ELSE +* +* 2 by 2 Block did split +* + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1, + $ WORK, INFO ) + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, 1, + $ WORK, INFO ) + HERE = HERE + 2 + END IF + END IF + END IF + IF( HERE.LT.ILST ) + $ GO TO 10 +* + ELSE +* + HERE = IFST + 20 CONTINUE +* +* Swap block with next one above +* + IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN +* +* Current block either 1 by 1 or 2 by 2 +* + NBNEXT = 1 + IF( HERE.GE.3 ) THEN + IF( T( HERE-1, HERE-2 ).NE.ZERO ) + $ NBNEXT = 2 + END IF + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT, + $ NBF, WORK, INFO ) + IF( INFO.NE.0 ) THEN + ILST = HERE + RETURN + END IF + HERE = HERE - NBNEXT +* +* Test if 2 by 2 block breaks into two 1 by 1 blocks +* + IF( NBF.EQ.2 ) THEN + IF( T( HERE+1, HERE ).EQ.ZERO ) + $ NBF = 3 + END IF +* + ELSE +* +* Current block consists of two 1 by 1 blocks each of which +* must be swapped individually +* + NBNEXT = 1 + IF( HERE.GE.3 ) THEN + IF( T( HERE-1, HERE-2 ).NE.ZERO ) + $ NBNEXT = 2 + END IF + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT, + $ 1, WORK, INFO ) + IF( INFO.NE.0 ) THEN + ILST = HERE + RETURN + END IF + IF( NBNEXT.EQ.1 ) THEN +* +* Swap two 1 by 1 blocks, no problems possible +* + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBNEXT, 1, + $ WORK, INFO ) + HERE = HERE - 1 + ELSE +* +* Recompute NBNEXT in case 2 by 2 split +* + IF( T( HERE, HERE-1 ).EQ.ZERO ) + $ NBNEXT = 1 + IF( NBNEXT.EQ.2 ) THEN +* +* 2 by 2 Block did not split +* + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 2, 1, + $ WORK, INFO ) + IF( INFO.NE.0 ) THEN + ILST = HERE + RETURN + END IF + HERE = HERE - 2 + ELSE +* +* 2 by 2 Block did split +* + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1, + $ WORK, INFO ) + CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 1, 1, + $ WORK, INFO ) + HERE = HERE - 2 + END IF + END IF + END IF + IF( HERE.GT.ILST ) + $ GO TO 20 + END IF + ILST = HERE +* + RETURN +* +* End of DTREXC +* + END diff --git a/dep/lapack/dtrsen.f b/dep/lapack/dtrsen.f new file mode 100644 index 00000000..3dda961e --- /dev/null +++ b/dep/lapack/dtrsen.f @@ -0,0 +1,421 @@ + SUBROUTINE DTRSEN( JOB, COMPQ, SELECT, N, T, LDT, Q, LDQ, WR, WI, + $ M, S, SEP, WORK, LWORK, IWORK, LIWORK, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER COMPQ, JOB + INTEGER INFO, LDQ, LDT, LIWORK, LWORK, M, N + DOUBLE PRECISION S, SEP +* .. +* .. Array Arguments .. + LOGICAL SELECT( * ) + INTEGER IWORK( * ) + DOUBLE PRECISION Q( LDQ, * ), T( LDT, * ), WI( * ), WORK( * ), + $ WR( * ) +* .. +* +* Purpose +* ======= +* +* DTRSEN reorders the real Schur factorization of a real matrix +* A = Q*T*Q**T, so that a selected cluster of eigenvalues appears in +* the leading diagonal blocks of the upper quasi-triangular matrix T, +* and the leading columns of Q form an orthonormal basis of the +* corresponding right invariant subspace. +* +* Optionally the routine computes the reciprocal condition numbers of +* the cluster of eigenvalues and/or the invariant subspace. +* +* T must be in Schur canonical form (as returned by DHSEQR), that is, +* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each +* 2-by-2 diagonal block has its diagonal elemnts equal and its +* off-diagonal elements of opposite sign. +* +* Arguments +* ========= +* +* JOB (input) CHARACTER*1 +* Specifies whether condition numbers are required for the +* cluster of eigenvalues (S) or the invariant subspace (SEP): +* = 'N': none; +* = 'E': for eigenvalues only (S); +* = 'V': for invariant subspace only (SEP); +* = 'B': for both eigenvalues and invariant subspace (S and +* SEP). +* +* COMPQ (input) CHARACTER*1 +* = 'V': update the matrix Q of Schur vectors; +* = 'N': do not update Q. +* +* SELECT (input) LOGICAL array, dimension (N) +* SELECT specifies the eigenvalues in the selected cluster. To +* select a real eigenvalue w(j), SELECT(j) must be set to +* .TRUE.. To select a complex conjugate pair of eigenvalues +* w(j) and w(j+1), corresponding to a 2-by-2 diagonal block, +* either SELECT(j) or SELECT(j+1) or both must be set to +* .TRUE.; a complex conjugate pair of eigenvalues must be +* either both included in the cluster or both excluded. +* +* N (input) INTEGER +* The order of the matrix T. N >= 0. +* +* T (input/output) DOUBLE PRECISION array, dimension (LDT,N) +* On entry, the upper quasi-triangular matrix T, in Schur +* canonical form. +* On exit, T is overwritten by the reordered matrix T, again in +* Schur canonical form, with the selected eigenvalues in the +* leading diagonal blocks. +* +* LDT (input) INTEGER +* The leading dimension of the array T. LDT >= max(1,N). +* +* Q (input/output) DOUBLE PRECISION array, dimension (LDQ,N) +* On entry, if COMPQ = 'V', the matrix Q of Schur vectors. +* On exit, if COMPQ = 'V', Q has been postmultiplied by the +* orthogonal transformation matrix which reorders T; the +* leading M columns of Q form an orthonormal basis for the +* specified invariant subspace. +* If COMPQ = 'N', Q is not referenced. +* +* LDQ (input) INTEGER +* The leading dimension of the array Q. +* LDQ >= 1; and if COMPQ = 'V', LDQ >= N. +* +* WR (output) DOUBLE PRECISION array, dimension (N) +* WI (output) DOUBLE PRECISION array, dimension (N) +* The real and imaginary parts, respectively, of the reordered +* eigenvalues of T. The eigenvalues are stored in the same +* order as on the diagonal of T, with WR(i) = T(i,i) and, if +* T(i:i+1,i:i+1) is a 2-by-2 diagonal block, WI(i) > 0 and +* WI(i+1) = -WI(i). Note that if a complex eigenvalue is +* sufficiently ill-conditioned, then its value may differ +* significantly from its value before reordering. +* +* M (output) INTEGER +* The dimension of the specified invariant subspace. +* 0 < = M <= N. +* +* S (output) DOUBLE PRECISION +* If JOB = 'E' or 'B', S is a lower bound on the reciprocal +* condition number for the selected cluster of eigenvalues. +* S cannot underestimate the true reciprocal condition number +* by more than a factor of sqrt(N). If M = 0 or N, S = 1. +* If JOB = 'N' or 'V', S is not referenced. +* +* SEP (output) DOUBLE PRECISION +* If JOB = 'V' or 'B', SEP is the estimated reciprocal +* condition number of the specified invariant subspace. If +* M = 0 or N, SEP = norm(T). +* If JOB = 'N' or 'E', SEP is not referenced. +* +* WORK (workspace) DOUBLE PRECISION array, dimension (LWORK) +* +* LWORK (input) INTEGER +* The dimension of the array WORK. +* If JOB = 'N', LWORK >= max(1,N); +* if JOB = 'E', LWORK >= M*(N-M); +* if JOB = 'V' or 'B', LWORK >= 2*M*(N-M). +* +* IWORK (workspace) INTEGER array, dimension (LIWORK) +* IF JOB = 'N' or 'E', IWORK is not referenced. +* +* LIWORK (input) INTEGER +* The dimension of the array IWORK. +* If JOB = 'N' or 'E', LIWORK >= 1; +* if JOB = 'V' or 'B', LIWORK >= M*(N-M). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* = 1: reordering of T failed because some eigenvalues are too +* close to separate (the problem is very ill-conditioned); +* T may have been partially reordered, and WR and WI +* contain the eigenvalues in the same order as in T; S and +* SEP (if requested) are set to zero. +* +* Further Details +* =============== +* +* DTRSEN first collects the selected eigenvalues by computing an +* orthogonal transformation Z to move them to the top left corner of T. +* In other words, the selected eigenvalues are the eigenvalues of T11 +* in: +* +* Z'*T*Z = ( T11 T12 ) n1 +* ( 0 T22 ) n2 +* n1 n2 +* +* where N = n1+n2 and Z' means the transpose of Z. The first n1 columns +* of Z span the specified invariant subspace of T. +* +* If T has been obtained from the real Schur factorization of a matrix +* A = Q*T*Q', then the reordered real Schur factorization of A is given +* by A = (Q*Z)*(Z'*T*Z)*(Q*Z)', and the first n1 columns of Q*Z span +* the corresponding invariant subspace of A. +* +* The reciprocal condition number of the average of the eigenvalues of +* T11 may be returned in S. S lies between 0 (very badly conditioned) +* and 1 (very well conditioned). It is computed as follows. First we +* compute R so that +* +* P = ( I R ) n1 +* ( 0 0 ) n2 +* n1 n2 +* +* is the projector on the invariant subspace associated with T11. +* R is the solution of the Sylvester equation: +* +* T11*R - R*T22 = T12. +* +* Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote +* the two-norm of M. Then S is computed as the lower bound +* +* (1 + F-norm(R)**2)**(-1/2) +* +* on the reciprocal of 2-norm(P), the true reciprocal condition number. +* S cannot underestimate 1 / 2-norm(P) by more than a factor of +* sqrt(N). +* +* An approximate error bound for the computed average of the +* eigenvalues of T11 is +* +* EPS * norm(T) / S +* +* where EPS is the machine precision. +* +* The reciprocal condition number of the right invariant subspace +* spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP. +* SEP is defined as the separation of T11 and T22: +* +* sep( T11, T22 ) = sigma-min( C ) +* +* where sigma-min(C) is the smallest singular value of the +* n1*n2-by-n1*n2 matrix +* +* C = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) ) +* +* I(m) is an m by m identity matrix, and kprod denotes the Kronecker +* product. We estimate sigma-min(C) by the reciprocal of an estimate of +* the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C) +* cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2). +* +* When SEP is small, small changes in T can cause large changes in +* the invariant subspace. An approximate bound on the maximum angular +* error in the computed right invariant subspace is +* +* EPS * norm(T) / SEP +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL PAIR, SWAP, WANTBH, WANTQ, WANTS, WANTSP + INTEGER IERR, K, KASE, KK, KS, N1, N2, NN + DOUBLE PRECISION EST, RNORM, SCALE +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DLANGE + EXTERNAL LSAME, DLANGE +* .. +* .. External Subroutines .. + EXTERNAL DLACON, DLACPY, DTREXC, DTRSYL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* +* Decode and test the input parameters +* + WANTBH = LSAME( JOB, 'B' ) + WANTS = LSAME( JOB, 'E' ) .OR. WANTBH + WANTSP = LSAME( JOB, 'V' ) .OR. WANTBH + WANTQ = LSAME( COMPQ, 'V' ) +* + INFO = 0 + IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.WANTS .AND. .NOT.WANTSP ) + $ THEN + INFO = -1 + ELSE IF( .NOT.LSAME( COMPQ, 'N' ) .AND. .NOT.WANTQ ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( LDT.LT.MAX( 1, N ) ) THEN + INFO = -6 + ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THEN + INFO = -8 + ELSE +* +* Set M to the dimension of the specified invariant subspace, +* and test LWORK and LIWORK. +* + M = 0 + PAIR = .FALSE. + DO 10 K = 1, N + IF( PAIR ) THEN + PAIR = .FALSE. + ELSE + IF( K.LT.N ) THEN + IF( T( K+1, K ).EQ.ZERO ) THEN + IF( SELECT( K ) ) + $ M = M + 1 + ELSE + PAIR = .TRUE. + IF( SELECT( K ) .OR. SELECT( K+1 ) ) + $ M = M + 2 + END IF + ELSE + IF( SELECT( N ) ) + $ M = M + 1 + END IF + END IF + 10 CONTINUE +* + N1 = M + N2 = N - M + NN = N1*N2 +* + IF( LWORK.LT.1 .OR. ( ( WANTS .AND. .NOT.WANTSP ) .AND. + $ LWORK.LT.NN ) .OR. ( WANTSP .AND. LWORK.LT.2*NN ) ) THEN + INFO = -15 + ELSE IF( LIWORK.LT.1 .OR. ( WANTSP .AND. LIWORK.LT.NN ) ) THEN + INFO = -17 + END IF + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTRSEN', -INFO ) + RETURN + END IF +* +* Quick return if possible. +* + IF( M.EQ.N .OR. M.EQ.0 ) THEN + IF( WANTS ) + $ S = ONE + IF( WANTSP ) + $ SEP = DLANGE( '1', N, N, T, LDT, WORK ) + GO TO 40 + END IF +* +* Collect the selected blocks at the top-left corner of T. +* + KS = 0 + PAIR = .FALSE. + DO 20 K = 1, N + IF( PAIR ) THEN + PAIR = .FALSE. + ELSE + SWAP = SELECT( K ) + IF( K.LT.N ) THEN + IF( T( K+1, K ).NE.ZERO ) THEN + PAIR = .TRUE. + SWAP = SWAP .OR. SELECT( K+1 ) + END IF + END IF + IF( SWAP ) THEN + KS = KS + 1 +* +* Swap the K-th block to position KS. +* + IERR = 0 + KK = K + IF( K.NE.KS ) + $ CALL DTREXC( COMPQ, N, T, LDT, Q, LDQ, KK, KS, WORK, + $ IERR ) + IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN +* +* Blocks too close to swap: exit. +* + INFO = 1 + IF( WANTS ) + $ S = ZERO + IF( WANTSP ) + $ SEP = ZERO + GO TO 40 + END IF + IF( PAIR ) + $ KS = KS + 1 + END IF + END IF + 20 CONTINUE +* + IF( WANTS ) THEN +* +* Solve Sylvester equation for R: +* +* T11*R - R*T22 = scale*T12 +* + CALL DLACPY( 'F', N1, N2, T( 1, N1+1 ), LDT, WORK, N1 ) + CALL DTRSYL( 'N', 'N', -1, N1, N2, T, LDT, T( N1+1, N1+1 ), + $ LDT, WORK, N1, SCALE, IERR ) +* +* Estimate the reciprocal of the condition number of the cluster +* of eigenvalues. +* + RNORM = DLANGE( 'F', N1, N2, WORK, N1, WORK ) + IF( RNORM.EQ.ZERO ) THEN + S = ONE + ELSE + S = SCALE / ( SQRT( SCALE*SCALE / RNORM+RNORM )* + $ SQRT( RNORM ) ) + END IF + END IF +* + IF( WANTSP ) THEN +* +* Estimate sep(T11,T22). +* + EST = ZERO + KASE = 0 + 30 CONTINUE + CALL DLACON( NN, WORK( NN+1 ), WORK, IWORK, EST, KASE ) + IF( KASE.NE.0 ) THEN + IF( KASE.EQ.1 ) THEN +* +* Solve T11*R - R*T22 = scale*X. +* + CALL DTRSYL( 'N', 'N', -1, N1, N2, T, LDT, + $ T( N1+1, N1+1 ), LDT, WORK, N1, SCALE, + $ IERR ) + ELSE +* +* Solve T11'*R - R*T22' = scale*X. +* + CALL DTRSYL( 'T', 'T', -1, N1, N2, T, LDT, + $ T( N1+1, N1+1 ), LDT, WORK, N1, SCALE, + $ IERR ) + END IF + GO TO 30 + END IF +* + SEP = SCALE / EST + END IF +* + 40 CONTINUE +* +* Store the output eigenvalues in WR and WI. +* + DO 50 K = 1, N + WR( K ) = T( K, K ) + WI( K ) = ZERO + 50 CONTINUE + DO 60 K = 1, N - 1 + IF( T( K+1, K ).NE.ZERO ) THEN + WI( K ) = SQRT( ABS( T( K, K+1 ) ) )* + $ SQRT( ABS( T( K+1, K ) ) ) + WI( K+1 ) = -WI( K ) + END IF + 60 CONTINUE + RETURN +* +* End of DTRSEN +* + END diff --git a/dep/lapack/dtrsyl.f b/dep/lapack/dtrsyl.f new file mode 100644 index 00000000..5432e9da --- /dev/null +++ b/dep/lapack/dtrsyl.f @@ -0,0 +1,914 @@ + SUBROUTINE DTRSYL( TRANA, TRANB, ISGN, M, N, A, LDA, B, LDB, C, + $ LDC, SCALE, INFO ) +* +* -- LAPACK routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* March 31, 1993 +* +* .. Scalar Arguments .. + CHARACTER TRANA, TRANB + INTEGER INFO, ISGN, LDA, LDB, LDC, M, N + DOUBLE PRECISION SCALE +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ), C( LDC, * ) +* .. +* +* Purpose +* ======= +* +* DTRSYL solves the real Sylvester matrix equation: +* +* op(A)*X + X*op(B) = scale*C or +* op(A)*X - X*op(B) = scale*C, +* +* where op(A) = A or A**T, and A and B are both upper quasi- +* triangular. A is M-by-M and B is N-by-N; the right hand side C and +* the solution X are M-by-N; and scale is an output scale factor, set +* <= 1 to avoid overflow in X. +* +* A and B must be in Schur canonical form (as returned by DHSEQR), that +* is, block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; +* each 2-by-2 diagonal block has its diagonal elements equal and its +* off-diagonal elements of opposite sign. +* +* Arguments +* ========= +* +* TRANA (input) CHARACTER*1 +* Specifies the option op(A): +* = 'N': op(A) = A (No transpose) +* = 'T': op(A) = A**T (Transpose) +* = 'C': op(A) = A**H (Conjugate transpose = Transpose) +* +* TRANB (input) CHARACTER*1 +* Specifies the option op(B): +* = 'N': op(B) = B (No transpose) +* = 'T': op(B) = B**T (Transpose) +* = 'C': op(B) = B**H (Conjugate transpose = Transpose) +* +* ISGN (input) INTEGER +* Specifies the sign in the equation: +* = +1: solve op(A)*X + X*op(B) = scale*C +* = -1: solve op(A)*X - X*op(B) = scale*C +* +* M (input) INTEGER +* The order of the matrix A, and the number of rows in the +* matrices X and C. M >= 0. +* +* N (input) INTEGER +* The order of the matrix B, and the number of columns in the +* matrices X and C. N >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,M) +* The upper quasi-triangular matrix A, in Schur canonical form. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* B (input) DOUBLE PRECISION array, dimension (LDB,N) +* The upper quasi-triangular matrix B, in Schur canonical form. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) +* On entry, the M-by-N right hand side matrix C. +* On exit, C is overwritten by the solution matrix X. +* +* LDC (input) INTEGER +* The leading dimension of the array C. LDC >= max(1,M) +* +* SCALE (output) DOUBLE PRECISION +* The scale factor, scale, set <= 1 to avoid overflow in X. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* = 1: A and B have common or very close eigenvalues; perturbed +* values were used to solve the equation (but the matrices +* A and B are unchanged). +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOTRNA, NOTRNB + INTEGER IERR, J, K, K1, K2, KNEXT, L, L1, L2, LNEXT + DOUBLE PRECISION A11, BIGNUM, DA11, DB, EPS, SCALOC, SGN, SMIN, + $ SMLNUM, SUML, SUMR, XNORM +* .. +* .. Local Arrays .. + DOUBLE PRECISION DUM( 1 ), VEC( 2, 2 ), X( 2, 2 ) +* .. +* .. External Functions .. + LOGICAL LSAME + DOUBLE PRECISION DDOT, DLAMCH, DLANGE + EXTERNAL LSAME, DDOT, DLAMCH, DLANGE +* .. +* .. External Subroutines .. + EXTERNAL DLABAD, DLALN2, DLASY2, DSCAL, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, MAX, MIN +* .. +* .. Executable Statements .. +* +* Decode and Test input parameters +* + NOTRNA = LSAME( TRANA, 'N' ) + NOTRNB = LSAME( TRANB, 'N' ) +* + INFO = 0 + IF( .NOT.NOTRNA .AND. .NOT.LSAME( TRANA, 'T' ) .AND. .NOT. + $ LSAME( TRANA, 'C' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOTRNB .AND. .NOT.LSAME( TRANB, 'T' ) .AND. .NOT. + $ LSAME( TRANB, 'C' ) ) THEN + INFO = -2 + ELSE IF( ISGN.NE.1 .AND. ISGN.NE.-1 ) THEN + INFO = -3 + ELSE IF( M.LT.0 ) THEN + INFO = -4 + ELSE IF( N.LT.0 ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -7 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -9 + ELSE IF( LDC.LT.MAX( 1, M ) ) THEN + INFO = -11 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTRSYL', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Set constants to control overflow +* + EPS = DLAMCH( 'P' ) + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM + CALL DLABAD( SMLNUM, BIGNUM ) + SMLNUM = SMLNUM*DBLE( M*N ) / EPS + BIGNUM = ONE / SMLNUM +* + SMIN = MAX( SMLNUM, EPS*DLANGE( 'M', M, M, A, LDA, DUM ), + $ EPS*DLANGE( 'M', N, N, B, LDB, DUM ) ) +* + SCALE = ONE + SGN = ISGN +* + IF( NOTRNA .AND. NOTRNB ) THEN +* +* Solve A*X + ISGN*X*B = scale*C. +* +* The (K,L)th block of X is determined starting from +* bottom-left corner column by column by +* +* A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L) +* +* Where +* M L-1 +* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(J,L)]. +* I=K+1 J=1 +* +* Start column loop (index = L) +* L1 (L2) : column index of the first (first) row of X(K,L). +* + LNEXT = 1 + DO 60 L = 1, N + IF( L.LT.LNEXT ) + $ GO TO 60 + IF( L.EQ.N ) THEN + L1 = L + L2 = L + ELSE + IF( B( L+1, L ).NE.ZERO ) THEN + L1 = L + L2 = L + 1 + LNEXT = L + 2 + ELSE + L1 = L + L2 = L + LNEXT = L + 1 + END IF + END IF +* +* Start row loop (index = K) +* K1 (K2): row index of the first (last) row of X(K,L). +* + KNEXT = M + DO 50 K = M, 1, -1 + IF( K.GT.KNEXT ) + $ GO TO 50 + IF( K.EQ.1 ) THEN + K1 = K + K2 = K + ELSE + IF( A( K, K-1 ).NE.ZERO ) THEN + K1 = K - 1 + K2 = K + KNEXT = K - 2 + ELSE + K1 = K + K2 = K + KNEXT = K - 1 + END IF + END IF +* + IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN + SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA, + $ C( MIN( K1+1, M ), L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) + SCALOC = ONE +* + A11 = A( K1, K1 ) + SGN*B( L1, L1 ) + DA11 = ABS( A11 ) + IF( DA11.LE.SMIN ) THEN + A11 = SMIN + DA11 = SMIN + INFO = 1 + END IF + DB = ABS( VEC( 1, 1 ) ) + IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN + IF( DB.GT.BIGNUM*DA11 ) + $ SCALOC = ONE / DB + END IF + X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11 +* + IF( SCALOC.NE.ONE ) THEN + DO 10 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 10 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) +* + ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ), + $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 20 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 20 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K2, L1 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN +* + SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA, + $ C( MIN( K1+1, M ), L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) ) +* + SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA, + $ C( MIN( K1+1, M ), L2 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 ) + VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) ) +* + CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ), + $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 30 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 30 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L2 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 ) + VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L2 ), 1 ) + SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 ) + VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR ) +* + CALL DLASY2( .FALSE., .FALSE., ISGN, 2, 2, + $ A( K1, K1 ), LDA, B( L1, L1 ), LDB, VEC, + $ 2, SCALOC, X, 2, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 40 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 40 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 1, 2 ) + C( K2, L1 ) = X( 2, 1 ) + C( K2, L2 ) = X( 2, 2 ) + END IF +* + 50 CONTINUE +* + 60 CONTINUE +* + ELSE IF( .NOT.NOTRNA .AND. NOTRNB ) THEN +* +* Solve A' *X + ISGN*X*B = scale*C. +* +* The (K,L)th block of X is determined starting from +* upper-left corner column by column by +* +* A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L) = C(K,L) - R(K,L) +* +* Where +* K-1 L-1 +* R(K,L) = SUM [A(I,K)'*X(I,L)] +ISGN*SUM [X(K,J)*B(J,L)] +* I=1 J=1 +* +* Start column loop (index = L) +* L1 (L2): column index of the first (last) row of X(K,L) +* + LNEXT = 1 + DO 120 L = 1, N + IF( L.LT.LNEXT ) + $ GO TO 120 + IF( L.EQ.N ) THEN + L1 = L + L2 = L + ELSE + IF( B( L+1, L ).NE.ZERO ) THEN + L1 = L + L2 = L + 1 + LNEXT = L + 2 + ELSE + L1 = L + L2 = L + LNEXT = L + 1 + END IF + END IF +* +* Start row loop (index = K) +* K1 (K2): row index of the first (last) row of X(K,L) +* + KNEXT = 1 + DO 110 K = 1, M + IF( K.LT.KNEXT ) + $ GO TO 110 + IF( K.EQ.M ) THEN + K1 = K + K2 = K + ELSE + IF( A( K+1, K ).NE.ZERO ) THEN + K1 = K + K2 = K + 1 + KNEXT = K + 2 + ELSE + K1 = K + K2 = K + KNEXT = K + 1 + END IF + END IF +* + IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) + SCALOC = ONE +* + A11 = A( K1, K1 ) + SGN*B( L1, L1 ) + DA11 = ABS( A11 ) + IF( DA11.LE.SMIN ) THEN + A11 = SMIN + DA11 = SMIN + INFO = 1 + END IF + DB = ABS( VEC( 1, 1 ) ) + IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN + IF( DB.GT.BIGNUM*DA11 ) + $ SCALOC = ONE / DB + END IF + X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11 +* + IF( SCALOC.NE.ONE ) THEN + DO 70 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 70 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) +* + ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ), + $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 80 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 80 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K2, L1 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) ) +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 ) + VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) ) +* + CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, B( L1, L1 ), + $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 90 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 90 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 ) + SUMR = DDOT( L1-1, C( K1, 1 ), LDC, B( 1, L2 ), 1 ) + VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L1 ), 1 ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 ) + SUMR = DDOT( L1-1, C( K2, 1 ), LDC, B( 1, L2 ), 1 ) + VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR ) +* + CALL DLASY2( .TRUE., .FALSE., ISGN, 2, 2, A( K1, K1 ), + $ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X, + $ 2, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 100 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 100 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 1, 2 ) + C( K2, L1 ) = X( 2, 1 ) + C( K2, L2 ) = X( 2, 2 ) + END IF +* + 110 CONTINUE + 120 CONTINUE +* + ELSE IF( .NOT.NOTRNA .AND. .NOT.NOTRNB ) THEN +* +* Solve A'*X + ISGN*X*B' = scale*C. +* +* The (K,L)th block of X is determined starting from +* top-right corner column by column by +* +* A(K,K)'*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L) +* +* Where +* K-1 N +* R(K,L) = SUM [A(I,K)'*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)']. +* I=1 J=L+1 +* +* Start column loop (index = L) +* L1 (L2): column index of the first (last) row of X(K,L) +* + LNEXT = N + DO 180 L = N, 1, -1 + IF( L.GT.LNEXT ) + $ GO TO 180 + IF( L.EQ.1 ) THEN + L1 = L + L2 = L + ELSE + IF( B( L, L-1 ).NE.ZERO ) THEN + L1 = L - 1 + L2 = L + LNEXT = L - 2 + ELSE + L1 = L + L2 = L + LNEXT = L - 1 + END IF + END IF +* +* Start row loop (index = K) +* K1 (K2): row index of the first (last) row of X(K,L) +* + KNEXT = 1 + DO 170 K = 1, M + IF( K.LT.KNEXT ) + $ GO TO 170 + IF( K.EQ.M ) THEN + K1 = K + K2 = K + ELSE + IF( A( K+1, K ).NE.ZERO ) THEN + K1 = K + K2 = K + 1 + KNEXT = K + 2 + ELSE + K1 = K + K2 = K + KNEXT = K + 1 + END IF + END IF +* + IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC, + $ B( L1, MIN( L1+1, N ) ), LDB ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) + SCALOC = ONE +* + A11 = A( K1, K1 ) + SGN*B( L1, L1 ) + DA11 = ABS( A11 ) + IF( DA11.LE.SMIN ) THEN + A11 = SMIN + DA11 = SMIN + INFO = 1 + END IF + DB = ABS( VEC( 1, 1 ) ) + IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN + IF( DB.GT.BIGNUM*DA11 ) + $ SCALOC = ONE / DB + END IF + X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11 +* + IF( SCALOC.NE.ONE ) THEN + DO 130 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 130 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) +* + ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, A( K1, K1 ), + $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 140 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 140 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K2, L1 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) ) +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L2, MIN( L2+1, N ) ), LDB ) + VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) ) +* + CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ), + $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 150 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 150 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K1 ), 1, C( 1, L2 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L2, MIN( L2+1, N ) ), LDB ) + VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L1 ), 1 ) + SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( K1-1, A( 1, K2 ), 1, C( 1, L2 ), 1 ) + SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC, + $ B( L2, MIN( L2+1, N ) ), LDB ) + VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR ) +* + CALL DLASY2( .TRUE., .TRUE., ISGN, 2, 2, A( K1, K1 ), + $ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X, + $ 2, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 160 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 160 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 1, 2 ) + C( K2, L1 ) = X( 2, 1 ) + C( K2, L2 ) = X( 2, 2 ) + END IF +* + 170 CONTINUE + 180 CONTINUE +* + ELSE IF( NOTRNA .AND. .NOT.NOTRNB ) THEN +* +* Solve A*X + ISGN*X*B' = scale*C. +* +* The (K,L)th block of X is determined starting from +* bottom-right corner column by column by +* +* A(K,K)*X(K,L) + ISGN*X(K,L)*B(L,L)' = C(K,L) - R(K,L) +* +* Where +* M N +* R(K,L) = SUM [A(K,I)*X(I,L)] + ISGN*SUM [X(K,J)*B(L,J)']. +* I=K+1 J=L+1 +* +* Start column loop (index = L) +* L1 (L2): column index of the first (last) row of X(K,L) +* + LNEXT = N + DO 240 L = N, 1, -1 + IF( L.GT.LNEXT ) + $ GO TO 240 + IF( L.EQ.1 ) THEN + L1 = L + L2 = L + ELSE + IF( B( L, L-1 ).NE.ZERO ) THEN + L1 = L - 1 + L2 = L + LNEXT = L - 2 + ELSE + L1 = L + L2 = L + LNEXT = L - 1 + END IF + END IF +* +* Start row loop (index = K) +* K1 (K2): row index of the first (last) row of X(K,L) +* + KNEXT = M + DO 230 K = M, 1, -1 + IF( K.GT.KNEXT ) + $ GO TO 230 + IF( K.EQ.1 ) THEN + K1 = K + K2 = K + ELSE + IF( A( K, K-1 ).NE.ZERO ) THEN + K1 = K - 1 + K2 = K + KNEXT = K - 2 + ELSE + K1 = K + K2 = K + KNEXT = K - 1 + END IF + END IF +* + IF( L1.EQ.L2 .AND. K1.EQ.K2 ) THEN + SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA, + $ C( MIN( K1+1, M ), L1 ), 1 ) + SUMR = DDOT( N-L1, C( K1, MIN( L1+1, N ) ), LDC, + $ B( L1, MIN( L1+1, N ) ), LDB ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) + SCALOC = ONE +* + A11 = A( K1, K1 ) + SGN*B( L1, L1 ) + DA11 = ABS( A11 ) + IF( DA11.LE.SMIN ) THEN + A11 = SMIN + DA11 = SMIN + INFO = 1 + END IF + DB = ABS( VEC( 1, 1 ) ) + IF( DA11.LT.ONE .AND. DB.GT.ONE ) THEN + IF( DB.GT.BIGNUM*DA11 ) + $ SCALOC = ONE / DB + END IF + X( 1, 1 ) = ( VEC( 1, 1 )*SCALOC ) / A11 +* + IF( SCALOC.NE.ONE ) THEN + DO 190 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 190 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) +* + ELSE IF( L1.EQ.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, A( K1, K1 ), + $ LDA, ONE, ONE, VEC, 2, -SGN*B( L1, L1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 200 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 200 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K2, L1 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.EQ.K2 ) THEN +* + SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA, + $ C( MIN( K1+1, M ), L1 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 1, 1 ) = SGN*( C( K1, L1 )-( SUML+SGN*SUMR ) ) +* + SUML = DDOT( M-K1, A( K1, MIN( K1+1, M ) ), LDA, + $ C( MIN( K1+1, M ), L2 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L2, MIN( L2+1, N ) ), LDB ) + VEC( 2, 1 ) = SGN*( C( K1, L2 )-( SUML+SGN*SUMR ) ) +* + CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, B( L1, L1 ), + $ LDB, ONE, ONE, VEC, 2, -SGN*A( K1, K1 ), + $ ZERO, X, 2, SCALOC, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 210 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 210 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 2, 1 ) +* + ELSE IF( L1.NE.L2 .AND. K1.NE.K2 ) THEN +* + SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 1, 1 ) = C( K1, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K1, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L2 ), 1 ) + SUMR = DDOT( N-L2, C( K1, MIN( L2+1, N ) ), LDC, + $ B( L2, MIN( L2+1, N ) ), LDB ) + VEC( 1, 2 ) = C( K1, L2 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L1 ), 1 ) + SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC, + $ B( L1, MIN( L2+1, N ) ), LDB ) + VEC( 2, 1 ) = C( K2, L1 ) - ( SUML+SGN*SUMR ) +* + SUML = DDOT( M-K2, A( K2, MIN( K2+1, M ) ), LDA, + $ C( MIN( K2+1, M ), L2 ), 1 ) + SUMR = DDOT( N-L2, C( K2, MIN( L2+1, N ) ), LDC, + $ B( L2, MIN( L2+1, N ) ), LDB ) + VEC( 2, 2 ) = C( K2, L2 ) - ( SUML+SGN*SUMR ) +* + CALL DLASY2( .FALSE., .TRUE., ISGN, 2, 2, A( K1, K1 ), + $ LDA, B( L1, L1 ), LDB, VEC, 2, SCALOC, X, + $ 2, XNORM, IERR ) + IF( IERR.NE.0 ) + $ INFO = 1 +* + IF( SCALOC.NE.ONE ) THEN + DO 220 J = 1, N + CALL DSCAL( M, SCALOC, C( 1, J ), 1 ) + 220 CONTINUE + SCALE = SCALE*SCALOC + END IF + C( K1, L1 ) = X( 1, 1 ) + C( K1, L2 ) = X( 1, 2 ) + C( K2, L1 ) = X( 2, 1 ) + C( K2, L2 ) = X( 2, 2 ) + END IF +* + 230 CONTINUE + 240 CONTINUE +* + END IF +* + RETURN +* +* End of DTRSYL +* + END diff --git a/dep/lapack/dtrti2.f b/dep/lapack/dtrti2.f new file mode 100644 index 00000000..e7ae764d --- /dev/null +++ b/dep/lapack/dtrti2.f @@ -0,0 +1,146 @@ + SUBROUTINE DTRTI2( UPLO, DIAG, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER DIAG, UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DTRTI2 computes the inverse of a real upper or lower triangular +* matrix. +* +* This is the Level 2 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the matrix A is upper or lower triangular. +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* DIAG (input) CHARACTER*1 +* Specifies whether or not the matrix A is unit triangular. +* = 'N': Non-unit triangular +* = 'U': Unit triangular +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the triangular matrix A. If UPLO = 'U', the +* leading n by n upper triangular part of the array A contains +* the upper triangular matrix, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading n by n lower triangular part of the array A contains +* the lower triangular matrix, and the strictly upper +* triangular part of A is not referenced. If DIAG = 'U', the +* diagonal elements of A are also not referenced and are +* assumed to be 1. +* +* On exit, the (triangular) inverse of the original matrix, in +* the same storage format. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOUNIT, UPPER + INTEGER J + DOUBLE PRECISION AJJ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DSCAL, DTRMV, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + NOUNIT = LSAME( DIAG, 'N' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTRTI2', -INFO ) + RETURN + END IF +* + IF( UPPER ) THEN +* +* Compute inverse of upper triangular matrix. +* + DO 10 J = 1, N + IF( NOUNIT ) THEN + A( J, J ) = ONE / A( J, J ) + AJJ = -A( J, J ) + ELSE + AJJ = -ONE + END IF +* +* Compute elements 1:j-1 of j-th column. +* + CALL DTRMV( 'Upper', 'No transpose', DIAG, J-1, A, LDA, + $ A( 1, J ), 1 ) + CALL DSCAL( J-1, AJJ, A( 1, J ), 1 ) + 10 CONTINUE + ELSE +* +* Compute inverse of lower triangular matrix. +* + DO 20 J = N, 1, -1 + IF( NOUNIT ) THEN + A( J, J ) = ONE / A( J, J ) + AJJ = -A( J, J ) + ELSE + AJJ = -ONE + END IF + IF( J.LT.N ) THEN +* +* Compute elements j+1:n of j-th column. +* + CALL DTRMV( 'Lower', 'No transpose', DIAG, N-J, + $ A( J+1, J+1 ), LDA, A( J+1, J ), 1 ) + CALL DSCAL( N-J, AJJ, A( J+1, J ), 1 ) + END IF + 20 CONTINUE + END IF +* + RETURN +* +* End of DTRTI2 +* + END diff --git a/dep/lapack/dtrtri.f b/dep/lapack/dtrtri.f new file mode 100644 index 00000000..6a04cdf1 --- /dev/null +++ b/dep/lapack/dtrtri.f @@ -0,0 +1,177 @@ + SUBROUTINE DTRTRI( UPLO, DIAG, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER DIAG, UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* DTRTRI computes the inverse of a real upper or lower triangular +* matrix A. +* +* This is the Level 3 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': A is upper triangular; +* = 'L': A is lower triangular. +* +* DIAG (input) CHARACTER*1 +* = 'N': A is non-unit triangular; +* = 'U': A is unit triangular. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) +* On entry, the triangular matrix A. If UPLO = 'U', the +* leading N-by-N upper triangular part of the array A contains +* the upper triangular matrix, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading N-by-N lower triangular part of the array A contains +* the lower triangular matrix, and the strictly upper +* triangular part of A is not referenced. If DIAG = 'U', the +* diagonal elements of A are also not referenced and are +* assumed to be 1. +* On exit, the (triangular) inverse of the original matrix, in +* the same storage format. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, A(i,i) is exactly zero. The triangular +* matrix is singular and its inverse can not be computed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOUNIT, UPPER + INTEGER J, JB, NB, NN +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL DTRMM, DTRSM, DTRTI2, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + NOUNIT = LSAME( DIAG, 'N' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTRTRI', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Check for singularity if non-unit. +* + IF( NOUNIT ) THEN + DO 10 INFO = 1, N + IF( A( INFO, INFO ).EQ.ZERO ) + $ RETURN + 10 CONTINUE + INFO = 0 + END IF +* +* Determine the block size for this environment. +* + NB = ILAENV( 1, 'DTRTRI', UPLO // DIAG, N, -1, -1, -1 ) + IF( NB.LE.1 .OR. NB.GE.N ) THEN +* +* Use unblocked code +* + CALL DTRTI2( UPLO, DIAG, N, A, LDA, INFO ) + ELSE +* +* Use blocked code +* + IF( UPPER ) THEN +* +* Compute inverse of upper triangular matrix +* + DO 20 J = 1, N, NB + JB = MIN( NB, N-J+1 ) +* +* Compute rows 1:j-1 of current block column +* + CALL DTRMM( 'Left', 'Upper', 'No transpose', DIAG, J-1, + $ JB, ONE, A, LDA, A( 1, J ), LDA ) + CALL DTRSM( 'Right', 'Upper', 'No transpose', DIAG, J-1, + $ JB, -ONE, A( J, J ), LDA, A( 1, J ), LDA ) +* +* Compute inverse of current diagonal block +* + CALL DTRTI2( 'Upper', DIAG, JB, A( J, J ), LDA, INFO ) + 20 CONTINUE + ELSE +* +* Compute inverse of lower triangular matrix +* + NN = ( ( N-1 ) / NB )*NB + 1 + DO 30 J = NN, 1, -NB + JB = MIN( NB, N-J+1 ) + IF( J+JB.LE.N ) THEN +* +* Compute rows j+jb:n of current block column +* + CALL DTRMM( 'Left', 'Lower', 'No transpose', DIAG, + $ N-J-JB+1, JB, ONE, A( J+JB, J+JB ), LDA, + $ A( J+JB, J ), LDA ) + CALL DTRSM( 'Right', 'Lower', 'No transpose', DIAG, + $ N-J-JB+1, JB, -ONE, A( J, J ), LDA, + $ A( J+JB, J ), LDA ) + END IF +* +* Compute inverse of current diagonal block +* + CALL DTRTI2( 'Lower', DIAG, JB, A( J, J ), LDA, INFO ) + 30 CONTINUE + END IF + END IF +* + RETURN +* +* End of DTRTRI +* + END diff --git a/dep/lapack/dtrtrs.f b/dep/lapack/dtrtrs.f new file mode 100644 index 00000000..c83d9c64 --- /dev/null +++ b/dep/lapack/dtrtrs.f @@ -0,0 +1,148 @@ + SUBROUTINE DTRTRS( UPLO, TRANS, DIAG, N, NRHS, A, LDA, B, LDB, + $ INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER DIAG, TRANS, UPLO + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* DTRTRS solves a triangular system of the form +* +* A * X = B or A**T * X = B, +* +* where A is a triangular matrix of order N, and B is an N-by-NRHS +* matrix. A check is made to verify that A is nonsingular. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': A is upper triangular; +* = 'L': A is lower triangular. +* +* TRANS (input) CHARACTER*1 +* Specifies the form of the system of equations: +* = 'N': A * X = B (No transpose) +* = 'T': A**T * X = B (Transpose) +* = 'C': A**H * X = B (Conjugate transpose = Transpose) +* +* DIAG (input) CHARACTER*1 +* = 'N': A is non-unit triangular; +* = 'U': A is unit triangular. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* A (input) DOUBLE PRECISION array, dimension (LDA,N) +* The triangular matrix A. If UPLO = 'U', the leading N-by-N +* upper triangular part of the array A contains the upper +* triangular matrix, and the strictly lower triangular part of +* A is not referenced. If UPLO = 'L', the leading N-by-N lower +* triangular part of the array A contains the lower triangular +* matrix, and the strictly upper triangular part of A is not +* referenced. If DIAG = 'U', the diagonal elements of A are +* also not referenced and are assumed to be 1. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, if INFO = 0, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, the i-th diagonal element of A is zero, +* indicating that the matrix is singular and the solutions +* X have not been computed. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + LOGICAL NOUNIT +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL DTRSM, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NOUNIT = LSAME( DIAG, 'N' ) + IF( .NOT.LSAME( UPLO, 'U' ) .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.LSAME( TRANS, 'N' ) .AND. .NOT. + $ LSAME( TRANS, 'T' ) .AND. .NOT.LSAME( TRANS, 'C' ) ) THEN + INFO = -2 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -3 + ELSE IF( N.LT.0 ) THEN + INFO = -4 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -5 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -7 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -9 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DTRTRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Check for singularity. +* + IF( NOUNIT ) THEN + DO 10 INFO = 1, N + IF( A( INFO, INFO ).EQ.ZERO ) + $ RETURN + 10 CONTINUE + END IF + INFO = 0 +* +* Solve A * x = b or A**T * x = b. +* + CALL DTRSM( 'Left', UPLO, TRANS, DIAG, N, NRHS, ONE, A, LDA, B, + $ LDB ) +* + RETURN +* +* End of DTRTRS +* + END diff --git a/dep/lapack/dzsum1.f b/dep/lapack/dzsum1.f new file mode 100644 index 00000000..387e4e66 --- /dev/null +++ b/dep/lapack/dzsum1.f @@ -0,0 +1,82 @@ + DOUBLE PRECISION FUNCTION DZSUM1( N, CX, INCX ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* October 31, 1992 +* +* .. Scalar Arguments .. + INTEGER INCX, N +* .. +* .. Array Arguments .. + COMPLEX*16 CX( * ) +* .. +* +* Purpose +* ======= +* +* DZSUM1 takes the sum of the absolute values of a complex +* vector and returns a double precision result. +* +* Based on DZASUM from the Level 1 BLAS. +* The change is to use the 'genuine' absolute value. +* +* Contributed by Nick Higham for use with ZLACON. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of elements in the vector CX. +* +* CX (input) COMPLEX*16 array, dimension (N) +* The vector whose elements will be summed. +* +* INCX (input) INTEGER +* The spacing between successive values of CX. INCX > 0. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, NINCX + DOUBLE PRECISION STEMP +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. +* + DZSUM1 = 0.0D0 + STEMP = 0.0D0 + IF( N.LE.0 ) + $ RETURN + IF( INCX.EQ.1 ) + $ GO TO 20 +* +* CODE FOR INCREMENT NOT EQUAL TO 1 +* + NINCX = N*INCX + DO 10 I = 1, NINCX, INCX +* +* NEXT LINE MODIFIED. +* + STEMP = STEMP + ABS( CX( I ) ) + 10 CONTINUE + DZSUM1 = STEMP + RETURN +* +* CODE FOR INCREMENT EQUAL TO 1 +* + 20 CONTINUE + DO 30 I = 1, N +* +* NEXT LINE MODIFIED. +* + STEMP = STEMP + ABS( CX( I ) ) + 30 CONTINUE + DZSUM1 = STEMP + RETURN +* +* End of DZSUM1 +* + END diff --git a/dep/lapack/icmax1.f b/dep/lapack/icmax1.f new file mode 100644 index 00000000..1d76618d --- /dev/null +++ b/dep/lapack/icmax1.f @@ -0,0 +1,96 @@ + INTEGER FUNCTION ICMAX1( N, CX, INCX ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INCX, N +* .. +* .. Array Arguments .. + COMPLEX CX( * ) +* .. +* +* Purpose +* ======= +* +* ICMAX1 finds the index of the element whose real part has maximum +* absolute value. +* +* Based on ICAMAX from Level 1 BLAS. +* The change is to use the 'genuine' absolute value. +* +* Contributed by Nick Higham for use with CLACON. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of elements in the vector CX. +* +* CX (input) COMPLEX array, dimension (N) +* The vector whose elements will be summed. +* +* INCX (input) INTEGER +* The spacing between successive values of CX. INCX >= 1. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, IX + REAL SMAX + COMPLEX ZDUM +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, REAL +* .. +* .. Statement Functions .. + REAL CABS1 +* .. +* .. Statement Function definitions .. +* +* NEXT LINE IS THE ONLY MODIFICATION. + CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) +* .. +* .. Executable Statements .. +* + ICMAX1 = 0 + IF( N.LT.1 ) + $ RETURN + ICMAX1 = 1 + IF( N.EQ.1 ) + $ RETURN + IF( INCX.EQ.1 ) + $ GO TO 30 +* +* CODE FOR INCREMENT NOT EQUAL TO 1 +* + IX = 1 + SMAX = CABS1( CX( 1 ) ) + IX = IX + INCX + DO 20 I = 2, N + IF( CABS1( CX( IX ) ).LE.SMAX ) + $ GO TO 10 + ICMAX1 = I + SMAX = CABS1( CX( IX ) ) + 10 CONTINUE + IX = IX + INCX + 20 CONTINUE + RETURN +* +* CODE FOR INCREMENT EQUAL TO 1 +* + 30 CONTINUE + SMAX = CABS1( CX( 1 ) ) + DO 40 I = 2, N + IF( CABS1( CX( I ) ).LE.SMAX ) + $ GO TO 40 + ICMAX1 = I + SMAX = CABS1( CX( I ) ) + 40 CONTINUE + RETURN +* +* End of ICMAX1 +* + END diff --git a/dep/lapack/ieeeck.f b/dep/lapack/ieeeck.f new file mode 100644 index 00000000..132e4367 --- /dev/null +++ b/dep/lapack/ieeeck.f @@ -0,0 +1,203 @@ +*> \brief \b IEEECK +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download IEEECK + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE ) +* +* .. Scalar Arguments .. +* INTEGER ISPEC +* REAL ONE, ZERO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> IEEECK is called from the ILAENV to verify that Infinity and +*> possibly NaN arithmetic is safe (i.e. will not trap). +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is INTEGER +*> Specifies whether to test just for inifinity arithmetic +*> or whether to test for infinity and NaN arithmetic. +*> = 0: Verify infinity arithmetic only. +*> = 1: Verify infinity and NaN arithmetic. +*> \endverbatim +*> +*> \param[in] ZERO +*> \verbatim +*> ZERO is REAL +*> Must contain the value 0.0 +*> This is passed to prevent the compiler from optimizing +*> away this code. +*> \endverbatim +*> +*> \param[in] ONE +*> \verbatim +*> ONE is REAL +*> Must contain the value 1.0 +*> This is passed to prevent the compiler from optimizing +*> away this code. +*> +*> RETURN VALUE: INTEGER +*> = 0: Arithmetic failed to produce the correct answers +*> = 1: Arithmetic produced the correct answers +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER ISPEC + REAL ONE, ZERO +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + REAL NAN1, NAN2, NAN3, NAN4, NAN5, NAN6, NEGINF, + $ NEGZRO, NEWZRO, POSINF +* .. +* .. Executable Statements .. + IEEECK = 1 +* + POSINF = ONE / ZERO + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = -ONE / ZERO + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGZRO = ONE / ( NEGINF+ONE ) + IF( NEGZRO.NE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = ONE / NEGZRO + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEWZRO = NEGZRO + ZERO + IF( NEWZRO.NE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + POSINF = ONE / NEWZRO + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = NEGINF*POSINF + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + POSINF = POSINF*POSINF + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* +* +* +* +* Return if we were only asked to check infinity arithmetic +* + IF( ISPEC.EQ.0 ) + $ RETURN +* + NAN1 = POSINF + NEGINF +* + NAN2 = POSINF / NEGINF +* + NAN3 = POSINF / POSINF +* + NAN4 = POSINF*ZERO +* + NAN5 = NEGINF*NEGZRO +* + NAN6 = NAN5*ZERO +* + IF( NAN1.EQ.NAN1 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN2.EQ.NAN2 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN3.EQ.NAN3 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN4.EQ.NAN4 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN5.EQ.NAN5 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN6.EQ.NAN6 ) THEN + IEEECK = 0 + RETURN + END IF +* + RETURN + END diff --git a/dep/lapack/iladlc.f b/dep/lapack/iladlc.f new file mode 100644 index 00000000..b56387d3 --- /dev/null +++ b/dep/lapack/iladlc.f @@ -0,0 +1,118 @@ +*> \brief \b ILADLC scans a matrix for its last non-zero column. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download ILADLC + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION ILADLC( M, N, A, LDA ) +* +* .. Scalar Arguments .. +* INTEGER M, N, LDA +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> ILADLC scans A for its last non-zero column. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The m by n matrix A. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + INTEGER FUNCTION ILADLC( M, N, A, LDA ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER M, N, LDA +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I +* .. +* .. Executable Statements .. +* +* Quick test for the common case where one corner is non-zero. + IF( N.EQ.0 ) THEN + ILADLC = N + ELSE IF( A(1, N).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN + ILADLC = N + ELSE +* Now scan each column from the end, returning with the first non-zero. + DO ILADLC = N, 1, -1 + DO I = 1, M + IF( A(I, ILADLC).NE.ZERO ) RETURN + END DO + END DO + END IF + RETURN + END diff --git a/dep/lapack/iladlr.f b/dep/lapack/iladlr.f new file mode 100644 index 00000000..fe155af0 --- /dev/null +++ b/dep/lapack/iladlr.f @@ -0,0 +1,121 @@ +*> \brief \b ILADLR scans a matrix for its last non-zero row. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download ILADLR + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION ILADLR( M, N, A, LDA ) +* +* .. Scalar Arguments .. +* INTEGER M, N, LDA +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> ILADLR scans A for its last non-zero row. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The m by n matrix A. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + INTEGER FUNCTION ILADLR( M, N, A, LDA ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER M, N, LDA +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I, J +* .. +* .. Executable Statements .. +* +* Quick test for the common case where one corner is non-zero. + IF( M.EQ.0 ) THEN + ILADLR = M + ELSE IF( A(M, 1).NE.ZERO .OR. A(M, N).NE.ZERO ) THEN + ILADLR = M + ELSE +* Scan up each column tracking the last zero row seen. + ILADLR = 0 + DO J = 1, N + I=M + DO WHILE((A(MAX(I,1),J).EQ.ZERO).AND.(I.GE.1)) + I=I-1 + ENDDO + ILADLR = MAX( ILADLR, I ) + END DO + END IF + RETURN + END diff --git a/dep/lapack/ilaenv.f b/dep/lapack/ilaenv.f new file mode 100644 index 00000000..867464de --- /dev/null +++ b/dep/lapack/ilaenv.f @@ -0,0 +1,624 @@ +*> \brief \b ILAENV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download ILAENV + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) +* +* .. Scalar Arguments .. +* CHARACTER*( * ) NAME, OPTS +* INTEGER ISPEC, N1, N2, N3, N4 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> ILAENV is called from the LAPACK routines to choose problem-dependent +*> parameters for the local environment. See ISPEC for a description of +*> the parameters. +*> +*> ILAENV returns an INTEGER +*> if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC +*> if ILAENV < 0: if ILAENV = -k, the k-th argument had an illegal value. +*> +*> This version provides a set of parameters which should give good, +*> but not optimal, performance on many of the currently available +*> computers. Users are encouraged to modify this subroutine to set +*> the tuning parameters for their particular machine using the option +*> and problem size information in the arguments. +*> +*> This routine will not function correctly if it is converted to all +*> lower case. Converting it to all upper case is allowed. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is INTEGER +*> Specifies the parameter to be returned as the value of +*> ILAENV. +*> = 1: the optimal blocksize; if this value is 1, an unblocked +*> algorithm will give the best performance. +*> = 2: the minimum block size for which the block routine +*> should be used; if the usable block size is less than +*> this value, an unblocked routine should be used. +*> = 3: the crossover point (in a block routine, for N less +*> than this value, an unblocked routine should be used) +*> = 4: the number of shifts, used in the nonsymmetric +*> eigenvalue routines (DEPRECATED) +*> = 5: the minimum column dimension for blocking to be used; +*> rectangular blocks must have dimension at least k by m, +*> where k is given by ILAENV(2,...) and m by ILAENV(5,...) +*> = 6: the crossover point for the SVD (when reducing an m by n +*> matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds +*> this value, a QR factorization is used first to reduce +*> the matrix to a triangular form.) +*> = 7: the number of processors +*> = 8: the crossover point for the multishift QR method +*> for nonsymmetric eigenvalue problems (DEPRECATED) +*> = 9: maximum size of the subproblems at the bottom of the +*> computation tree in the divide-and-conquer algorithm +*> (used by xGELSD and xGESDD) +*> =10: ieee NaN arithmetic can be trusted not to trap +*> =11: infinity arithmetic can be trusted not to trap +*> 12 <= ISPEC <= 16: +*> xHSEQR or one of its subroutines, +*> see IPARMQ for detailed explanation +*> \endverbatim +*> +*> \param[in] NAME +*> \verbatim +*> NAME is CHARACTER*(*) +*> The name of the calling subroutine, in either upper case or +*> lower case. +*> \endverbatim +*> +*> \param[in] OPTS +*> \verbatim +*> OPTS is CHARACTER*(*) +*> The character options to the subroutine NAME, concatenated +*> into a single character string. For example, UPLO = 'U', +*> TRANS = 'T', and DIAG = 'N' for a triangular routine would +*> be specified as OPTS = 'UTN'. +*> \endverbatim +*> +*> \param[in] N1 +*> \verbatim +*> N1 is INTEGER +*> \endverbatim +*> +*> \param[in] N2 +*> \verbatim +*> N2 is INTEGER +*> \endverbatim +*> +*> \param[in] N3 +*> \verbatim +*> N3 is INTEGER +*> \endverbatim +*> +*> \param[in] N4 +*> \verbatim +*> N4 is INTEGER +*> Problem dimensions for the subroutine NAME; these may not all +*> be required. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> The following conventions have been used when calling ILAENV from the +*> LAPACK routines: +*> 1) OPTS is a concatenation of all of the character options to +*> subroutine NAME, in the same order that they appear in the +*> argument list for NAME, even if they are not used in determining +*> the value of the parameter specified by ISPEC. +*> 2) The problem dimensions N1, N2, N3, N4 are specified in the order +*> that they appear in the argument list for NAME. N1 is used +*> first, N2 second, and so on, and unused problem dimensions are +*> passed a value of -1. +*> 3) The parameter value returned by ILAENV is checked for validity in +*> the calling subroutine. For example, ILAENV is used to retrieve +*> the optimal blocksize for STRTRI as follows: +*> +*> NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 ) +*> IF( NB.LE.1 ) NB = MAX( 1, N ) +*> \endverbatim +*> +* ===================================================================== + INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*( * ) NAME, OPTS + INTEGER ISPEC, N1, N2, N3, N4 +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, IC, IZ, NB, NBMIN, NX + LOGICAL CNAME, SNAME + CHARACTER C1*1, C2*2, C4*2, C3*3, SUBNAM*6 +* .. +* .. Intrinsic Functions .. + INTRINSIC CHAR, ICHAR, INT, MIN, REAL +* .. +* .. External Functions .. + INTEGER IEEECK, IPARMQ + EXTERNAL IEEECK, IPARMQ +* .. +* .. Executable Statements .. +* + GO TO ( 10, 10, 10, 80, 90, 100, 110, 120, + $ 130, 140, 150, 160, 160, 160, 160, 160 )ISPEC +* +* Invalid value for ISPEC +* + ILAENV = -1 + RETURN +* + 10 CONTINUE +* +* Convert NAME to upper case if the first character is lower case. +* + ILAENV = 1 + SUBNAM = NAME + IC = ICHAR( SUBNAM( 1: 1 ) ) + IZ = ICHAR( 'Z' ) + IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN +* +* ASCII character set +* + IF( IC.GE.97 .AND. IC.LE.122 ) THEN + SUBNAM( 1: 1 ) = CHAR( IC-32 ) + DO 20 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( IC.GE.97 .AND. IC.LE.122 ) + $ SUBNAM( I: I ) = CHAR( IC-32 ) + 20 CONTINUE + END IF +* + ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN +* +* EBCDIC character set +* + IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR. + $ ( IC.GE.145 .AND. IC.LE.153 ) .OR. + $ ( IC.GE.162 .AND. IC.LE.169 ) ) THEN + SUBNAM( 1: 1 ) = CHAR( IC+64 ) + DO 30 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR. + $ ( IC.GE.145 .AND. IC.LE.153 ) .OR. + $ ( IC.GE.162 .AND. IC.LE.169 ) )SUBNAM( I: + $ I ) = CHAR( IC+64 ) + 30 CONTINUE + END IF +* + ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN +* +* Prime machines: ASCII+128 +* + IF( IC.GE.225 .AND. IC.LE.250 ) THEN + SUBNAM( 1: 1 ) = CHAR( IC-32 ) + DO 40 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( IC.GE.225 .AND. IC.LE.250 ) + $ SUBNAM( I: I ) = CHAR( IC-32 ) + 40 CONTINUE + END IF + END IF +* + C1 = SUBNAM( 1: 1 ) + SNAME = C1.EQ.'S' .OR. C1.EQ.'D' + CNAME = C1.EQ.'C' .OR. C1.EQ.'Z' + IF( .NOT.( CNAME .OR. SNAME ) ) + $ RETURN + C2 = SUBNAM( 2: 3 ) + C3 = SUBNAM( 4: 6 ) + C4 = C3( 2: 3 ) +* + GO TO ( 50, 60, 70 )ISPEC +* + 50 CONTINUE +* +* ISPEC = 1: block size +* +* In these examples, separate code is provided for setting NB for +* real and complex. We assume that NB will take the same value in +* single or double precision. +* + NB = 1 +* + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + ELSE IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. + $ C3.EQ.'QLF' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'PO' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NB = 32 + ELSE IF( SNAME .AND. C3.EQ.'GST' ) THEN + NB = 64 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRF' ) THEN + NB = 64 + ELSE IF( C3.EQ.'TRD' ) THEN + NB = 32 + ELSE IF( C3.EQ.'GST' ) THEN + NB = 64 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + END IF + ELSE IF( C2.EQ.'GB' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + IF( N4.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + ELSE + IF( N4.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + END IF + END IF + ELSE IF( C2.EQ.'PB' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + IF( N2.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + ELSE + IF( N2.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + END IF + END IF + ELSE IF( C2.EQ.'TR' ) THEN + IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'LA' ) THEN + IF( C3.EQ.'UUM' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( SNAME .AND. C2.EQ.'ST' ) THEN + IF( C3.EQ.'EBZ' ) THEN + NB = 1 + END IF + END IF + ILAENV = NB + RETURN +* + 60 CONTINUE +* +* ISPEC = 2: minimum block size +* + NBMIN = 2 + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ. + $ 'QLF' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NBMIN = 8 + ELSE + NBMIN = 8 + END IF + ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NBMIN = 2 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRD' ) THEN + NBMIN = 2 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + END IF + END IF + ILAENV = NBMIN + RETURN +* + 70 CONTINUE +* +* ISPEC = 3: crossover point +* + NX = 0 + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ. + $ 'QLF' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NX = 32 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRD' ) THEN + NX = 32 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NX = 128 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NX = 128 + END IF + END IF + END IF + ILAENV = NX + RETURN +* + 80 CONTINUE +* +* ISPEC = 4: number of shifts (used by xHSEQR) +* + ILAENV = 6 + RETURN +* + 90 CONTINUE +* +* ISPEC = 5: minimum column dimension (not used) +* + ILAENV = 2 + RETURN +* + 100 CONTINUE +* +* ISPEC = 6: crossover point for SVD (used by xGELSS and xGESVD) +* + ILAENV = INT( REAL( MIN( N1, N2 ) )*1.6E0 ) + RETURN +* + 110 CONTINUE +* +* ISPEC = 7: number of processors (not used) +* + ILAENV = 1 + RETURN +* + 120 CONTINUE +* +* ISPEC = 8: crossover point for multishift (used by xHSEQR) +* + ILAENV = 50 + RETURN +* + 130 CONTINUE +* +* ISPEC = 9: maximum size of the subproblems at the bottom of the +* computation tree in the divide-and-conquer algorithm +* (used by xGELSD and xGESDD) +* + ILAENV = 25 + RETURN +* + 140 CONTINUE +* +* ISPEC = 10: ieee NaN arithmetic can be trusted not to trap +* +* ILAENV = 0 + ILAENV = 1 + IF( ILAENV.EQ.1 ) THEN + ILAENV = IEEECK( 1, 0.0, 1.0 ) + END IF + RETURN +* + 150 CONTINUE +* +* ISPEC = 11: infinity arithmetic can be trusted not to trap +* +* ILAENV = 0 + ILAENV = 1 + IF( ILAENV.EQ.1 ) THEN + ILAENV = IEEECK( 0, 0.0, 1.0 ) + END IF + RETURN +* + 160 CONTINUE +* +* 12 <= ISPEC <= 16: xHSEQR or one of its subroutines. +* + ILAENV = IPARMQ( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) + RETURN +* +* End of ILAENV +* + END diff --git a/dep/lapack/iparmq.f b/dep/lapack/iparmq.f new file mode 100644 index 00000000..bd5bd7a0 --- /dev/null +++ b/dep/lapack/iparmq.f @@ -0,0 +1,322 @@ +*> \brief \b IPARMQ +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download IPARMQ + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK ) +* +* .. Scalar Arguments .. +* INTEGER IHI, ILO, ISPEC, LWORK, N +* CHARACTER NAME*( * ), OPTS*( * ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This program sets problem and machine dependent parameters +*> useful for xHSEQR and its subroutines. It is called whenever +*> ILAENV is called with 12 <= ISPEC <= 16 +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is integer scalar +*> ISPEC specifies which tunable parameter IPARMQ should +*> return. +*> +*> ISPEC=12: (INMIN) Matrices of order nmin or less +*> are sent directly to xLAHQR, the implicit +*> double shift QR algorithm. NMIN must be +*> at least 11. +*> +*> ISPEC=13: (INWIN) Size of the deflation window. +*> This is best set greater than or equal to +*> the number of simultaneous shifts NS. +*> Larger matrices benefit from larger deflation +*> windows. +*> +*> ISPEC=14: (INIBL) Determines when to stop nibbling and +*> invest in an (expensive) multi-shift QR sweep. +*> If the aggressive early deflation subroutine +*> finds LD converged eigenvalues from an order +*> NW deflation window and LD.GT.(NW*NIBBLE)/100, +*> then the next QR sweep is skipped and early +*> deflation is applied immediately to the +*> remaining active diagonal block. Setting +*> IPARMQ(ISPEC=14) = 0 causes TTQRE to skip a +*> multi-shift QR sweep whenever early deflation +*> finds a converged eigenvalue. Setting +*> IPARMQ(ISPEC=14) greater than or equal to 100 +*> prevents TTQRE from skipping a multi-shift +*> QR sweep. +*> +*> ISPEC=15: (NSHFTS) The number of simultaneous shifts in +*> a multi-shift QR iteration. +*> +*> ISPEC=16: (IACC22) IPARMQ is set to 0, 1 or 2 with the +*> following meanings. +*> 0: During the multi-shift QR sweep, +*> xLAQR5 does not accumulate reflections and +*> does not use matrix-matrix multiply to +*> update the far-from-diagonal matrix +*> entries. +*> 1: During the multi-shift QR sweep, +*> xLAQR5 and/or xLAQRaccumulates reflections and uses +*> matrix-matrix multiply to update the +*> far-from-diagonal matrix entries. +*> 2: During the multi-shift QR sweep. +*> xLAQR5 accumulates reflections and takes +*> advantage of 2-by-2 block structure during +*> matrix-matrix multiplies. +*> (If xTRMM is slower than xGEMM, then +*> IPARMQ(ISPEC=16)=1 may be more efficient than +*> IPARMQ(ISPEC=16)=2 despite the greater level of +*> arithmetic work implied by the latter choice.) +*> \endverbatim +*> +*> \param[in] NAME +*> \verbatim +*> NAME is character string +*> Name of the calling subroutine +*> \endverbatim +*> +*> \param[in] OPTS +*> \verbatim +*> OPTS is character string +*> This is a concatenation of the string arguments to +*> TTQRE. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is integer scalar +*> N is the order of the Hessenberg matrix H. +*> \endverbatim +*> +*> \param[in] ILO +*> \verbatim +*> ILO is INTEGER +*> \endverbatim +*> +*> \param[in] IHI +*> \verbatim +*> IHI is INTEGER +*> It is assumed that H is already upper triangular +*> in rows and columns 1:ILO-1 and IHI+1:N. +*> \endverbatim +*> +*> \param[in] LWORK +*> \verbatim +*> LWORK is integer scalar +*> The amount of workspace available. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Little is known about how best to choose these parameters. +*> It is possible to use different values of the parameters +*> for each of CHSEQR, DHSEQR, SHSEQR and ZHSEQR. +*> +*> It is probably best to choose different parameters for +*> different matrices and different parameters at different +*> times during the iteration, but this has not been +*> implemented --- yet. +*> +*> +*> The best choices of most of the parameters depend +*> in an ill-understood way on the relative execution +*> rate of xLAQR3 and xLAQR5 and on the nature of each +*> particular eigenvalue problem. Experiment may be the +*> only practical way to determine which choices are most +*> effective. +*> +*> Following is a list of default values supplied by IPARMQ. +*> These defaults may be adjusted in order to attain better +*> performance in any particular computational environment. +*> +*> IPARMQ(ISPEC=12) The xLAHQR vs xLAQR0 crossover point. +*> Default: 75. (Must be at least 11.) +*> +*> IPARMQ(ISPEC=13) Recommended deflation window size. +*> This depends on ILO, IHI and NS, the +*> number of simultaneous shifts returned +*> by IPARMQ(ISPEC=15). The default for +*> (IHI-ILO+1).LE.500 is NS. The default +*> for (IHI-ILO+1).GT.500 is 3*NS/2. +*> +*> IPARMQ(ISPEC=14) Nibble crossover point. Default: 14. +*> +*> IPARMQ(ISPEC=15) Number of simultaneous shifts, NS. +*> a multi-shift QR iteration. +*> +*> If IHI-ILO+1 is ... +*> +*> greater than ...but less ... the +*> or equal to ... than default is +*> +*> 0 30 NS = 2+ +*> 30 60 NS = 4+ +*> 60 150 NS = 10 +*> 150 590 NS = ** +*> 590 3000 NS = 64 +*> 3000 6000 NS = 128 +*> 6000 infinity NS = 256 +*> +*> (+) By default matrices of this order are +*> passed to the implicit double shift routine +*> xLAHQR. See IPARMQ(ISPEC=12) above. These +*> values of NS are used only in case of a rare +*> xLAHQR failure. +*> +*> (**) The asterisks (**) indicate an ad-hoc +*> function increasing from 10 to 64. +*> +*> IPARMQ(ISPEC=16) Select structured matrix multiply. +*> (See ISPEC=16 above for details.) +*> Default: 3. +*> \endverbatim +*> +* ===================================================================== + INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, ISPEC, LWORK, N + CHARACTER NAME*( * ), OPTS*( * ) +* +* ================================================================ +* .. Parameters .. + INTEGER INMIN, INWIN, INIBL, ISHFTS, IACC22 + PARAMETER ( INMIN = 12, INWIN = 13, INIBL = 14, + $ ISHFTS = 15, IACC22 = 16 ) + INTEGER NMIN, K22MIN, KACMIN, NIBBLE, KNWSWP + PARAMETER ( NMIN = 75, K22MIN = 14, KACMIN = 14, + $ NIBBLE = 14, KNWSWP = 500 ) + REAL TWO + PARAMETER ( TWO = 2.0 ) +* .. +* .. Local Scalars .. + INTEGER NH, NS +* .. +* .. Intrinsic Functions .. + INTRINSIC LOG, MAX, MOD, NINT, REAL +* .. +* .. Executable Statements .. + IF( ( ISPEC.EQ.ISHFTS ) .OR. ( ISPEC.EQ.INWIN ) .OR. + $ ( ISPEC.EQ.IACC22 ) ) THEN +* +* ==== Set the number simultaneous shifts ==== +* + NH = IHI - ILO + 1 + NS = 2 + IF( NH.GE.30 ) + $ NS = 4 + IF( NH.GE.60 ) + $ NS = 10 + IF( NH.GE.150 ) + $ NS = MAX( 10, NH / NINT( LOG( REAL( NH ) ) / LOG( TWO ) ) ) + IF( NH.GE.590 ) + $ NS = 64 + IF( NH.GE.3000 ) + $ NS = 128 + IF( NH.GE.6000 ) + $ NS = 256 + NS = MAX( 2, NS-MOD( NS, 2 ) ) + END IF +* + IF( ISPEC.EQ.INMIN ) THEN +* +* +* ===== Matrices of order smaller than NMIN get sent +* . to xLAHQR, the classic double shift algorithm. +* . This must be at least 11. ==== +* + IPARMQ = NMIN +* + ELSE IF( ISPEC.EQ.INIBL ) THEN +* +* ==== INIBL: skip a multi-shift qr iteration and +* . whenever aggressive early deflation finds +* . at least (NIBBLE*(window size)/100) deflations. ==== +* + IPARMQ = NIBBLE +* + ELSE IF( ISPEC.EQ.ISHFTS ) THEN +* +* ==== NSHFTS: The number of simultaneous shifts ===== +* + IPARMQ = NS +* + ELSE IF( ISPEC.EQ.INWIN ) THEN +* +* ==== NW: deflation window size. ==== +* + IF( NH.LE.KNWSWP ) THEN + IPARMQ = NS + ELSE + IPARMQ = 3*NS / 2 + END IF +* + ELSE IF( ISPEC.EQ.IACC22 ) THEN +* +* ==== IACC22: Whether to accumulate reflections +* . before updating the far-from-diagonal elements +* . and whether to use 2-by-2 block structure while +* . doing it. A small amount of work could be saved +* . by making this choice dependent also upon the +* . NH=IHI-ILO+1. +* + IPARMQ = 0 + IF( NS.GE.KACMIN ) + $ IPARMQ = 1 + IF( NS.GE.K22MIN ) + $ IPARMQ = 2 +* + ELSE +* ===== invalid value of ispec ===== + IPARMQ = -1 +* + END IF +* +* ==== End of IPARMQ ==== +* + END diff --git a/dep/lapack/izmax1.f b/dep/lapack/izmax1.f new file mode 100644 index 00000000..785100eb --- /dev/null +++ b/dep/lapack/izmax1.f @@ -0,0 +1,96 @@ + INTEGER FUNCTION IZMAX1( N, CX, INCX ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + INTEGER INCX, N +* .. +* .. Array Arguments .. + COMPLEX*16 CX( * ) +* .. +* +* Purpose +* ======= +* +* IZMAX1 finds the index of the element whose real part has maximum +* absolute value. +* +* Based on IZAMAX from Level 1 BLAS. +* The change is to use the 'genuine' absolute value. +* +* Contributed by Nick Higham for use with ZLACON. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of elements in the vector CX. +* +* CX (input) COMPLEX*16 array, dimension (N) +* The vector whose elements will be summed. +* +* INCX (input) INTEGER +* The spacing between successive values of CX. INCX >= 1. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, IX + DOUBLE PRECISION SMAX + COMPLEX*16 ZDUM +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE +* .. +* .. Statement Functions .. + DOUBLE PRECISION CABS1 +* .. +* .. Statement Function definitions .. +* +* NEXT LINE IS THE ONLY MODIFICATION. + CABS1( ZDUM ) = ABS( DBLE( ZDUM ) ) +* .. +* .. Executable Statements .. +* + IZMAX1 = 0 + IF( N.LT.1 ) + $ RETURN + IZMAX1 = 1 + IF( N.EQ.1 ) + $ RETURN + IF( INCX.EQ.1 ) + $ GO TO 30 +* +* CODE FOR INCREMENT NOT EQUAL TO 1 +* + IX = 1 + SMAX = CABS1( CX( 1 ) ) + IX = IX + INCX + DO 20 I = 2, N + IF( CABS1( CX( IX ) ).LE.SMAX ) + $ GO TO 10 + IZMAX1 = I + SMAX = CABS1( CX( IX ) ) + 10 CONTINUE + IX = IX + INCX + 20 CONTINUE + RETURN +* +* CODE FOR INCREMENT EQUAL TO 1 +* + 30 CONTINUE + SMAX = CABS1( CX( 1 ) ) + DO 40 I = 2, N + IF( CABS1( CX( I ) ).LE.SMAX ) + $ GO TO 40 + IZMAX1 = I + SMAX = CABS1( CX( I ) ) + 40 CONTINUE + RETURN +* +* End of IZMAX1 +* + END diff --git a/dep/lapack/lsamen.f b/dep/lapack/lsamen.f new file mode 100644 index 00000000..adcbd596 --- /dev/null +++ b/dep/lapack/lsamen.f @@ -0,0 +1,68 @@ + LOGICAL FUNCTION LSAMEN( N, CA, CB ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* September 30, 1994 +* +* .. Scalar Arguments .. + CHARACTER*( * ) CA, CB + INTEGER N +* .. +* +* Purpose +* ======= +* +* LSAMEN tests if the first N letters of CA are the same as the +* first N letters of CB, regardless of case. +* LSAMEN returns .TRUE. if CA and CB are equivalent except for case +* and .FALSE. otherwise. LSAMEN also returns .FALSE. if LEN( CA ) +* or LEN( CB ) is less than N. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of characters in CA and CB to be compared. +* +* CA (input) CHARACTER*(*) +* CB (input) CHARACTER*(*) +* CA and CB specify two character strings of length at least N. +* Only the first N characters of each string will be accessed. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC LEN +* .. +* .. Executable Statements .. +* + LSAMEN = .FALSE. + IF( LEN( CA ).LT.N .OR. LEN( CB ).LT.N ) + $ GO TO 20 +* +* Do for each character in the two strings. +* + DO 10 I = 1, N +* +* Test if the characters are equal using LSAME. +* + IF( .NOT.LSAME( CA( I: I ), CB( I: I ) ) ) + $ GO TO 20 +* + 10 CONTINUE + LSAMEN = .TRUE. +* + 20 CONTINUE + RETURN +* +* End of LSAMEN +* + END diff --git a/dep/lapack/xlaenv.f b/dep/lapack/xlaenv.f new file mode 100644 index 00000000..50135409 --- /dev/null +++ b/dep/lapack/xlaenv.f @@ -0,0 +1,67 @@ + SUBROUTINE XLAENV( ISPEC, NVALUE ) +* +* -- LAPACK auxiliary routine (version 2.0) -- +* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., +* Courant Institute, Argonne National Lab, and Rice University +* February 29, 1992 +* +* .. Scalar Arguments .. + INTEGER ISPEC, NVALUE +* .. +* +* Purpose +* ======= +* +* XLAENV sets certain machine- and problem-dependent quantities +* which will later be retrieved by ILAENV. +* +* Arguments +* ========= +* +* ISPEC (input) INTEGER +* Specifies the parameter to be set in the COMMON array IPARMS. +* = 1: the optimal blocksize; if this value is 1, an unblocked +* algorithm will give the best performance. +* = 2: the minimum block size for which the block routine +* should be used; if the usable block size is less than +* this value, an unblocked routine should be used. +* = 3: the crossover point (in a block routine, for N less +* than this value, an unblocked routine should be used) +* = 4: the number of shifts, used in the nonsymmetric +* eigenvalue routines +* = 5: the minimum column dimension for blocking to be used; +* rectangular blocks must have dimension at least k by m, +* where k is given by ILAENV(2,...) and m by ILAENV(5,...) +* = 6: the crossover point for the SVD (when reducing an m by n +* matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds +* this value, a QR factorization is used first to reduce +* the matrix to a triangular form) +* = 7: the number of processors +* = 8: another crossover point, for the multishift QR and QZ +* methods for nonsymmetric eigenvalue problems. +* +* NVALUE (input) INTEGER +* The value of the parameter specified by ISPEC. +* +* ===================================================================== +* +* .. Arrays in Common .. + INTEGER IPARMS( 100 ) +* .. +* .. Common blocks .. + COMMON / CLAENV / IPARMS +* .. +* .. Save statement .. + SAVE / CLAENV / +* .. +* .. Executable Statements .. +* + IF( ISPEC.GE.1 .AND. ISPEC.LE.8 ) THEN + IPARMS( ISPEC ) = NVALUE + END IF +* + RETURN +* +* End of XLAENV +* + END diff --git a/dep/lapack/zgesv.f b/dep/lapack/zgesv.f new file mode 100644 index 00000000..6b83e81b --- /dev/null +++ b/dep/lapack/zgesv.f @@ -0,0 +1,108 @@ + SUBROUTINE ZGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO ) +* +* -- LAPACK driver routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* ZGESV computes the solution to a complex system of linear equations +* A * X = B, +* where A is an N-by-N matrix and X and B are N-by-NRHS matrices. +* +* The LU decomposition with partial pivoting and row interchanges is +* used to factor A as +* A = P * L * U, +* where P is a permutation matrix, L is unit lower triangular, and U is +* upper triangular. The factored form of A is then used to solve the +* system of equations A * X = B. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of linear equations, i.e., the order of the +* matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the N-by-N coefficient matrix A. +* On exit, the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (output) INTEGER array, dimension (N) +* The pivot indices that define the permutation matrix P; +* row i of the matrix was interchanged with row IPIV(i). +* +* B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) +* On entry, the N-by-NRHS matrix of right hand side matrix B. +* On exit, if INFO = 0, the N-by-NRHS solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, so the solution could not be computed. +* +* ===================================================================== +* +* .. External Subroutines .. + EXTERNAL XERBLA, ZGETRF, ZGETRS +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -4 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -7 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGESV ', -INFO ) + RETURN + END IF +* +* Compute the LU factorization of A. +* + CALL ZGETRF( N, N, A, LDA, IPIV, INFO ) + IF( INFO.EQ.0 ) THEN +* +* Solve the system A*X = B, overwriting B with X. +* + CALL ZGETRS( 'No transpose', N, NRHS, A, LDA, IPIV, B, LDB, + $ INFO ) + END IF + RETURN +* +* End of ZGESV +* + END diff --git a/dep/lapack/zgetf2.f b/dep/lapack/zgetf2.f new file mode 100644 index 00000000..79c2170f --- /dev/null +++ b/dep/lapack/zgetf2.f @@ -0,0 +1,149 @@ + SUBROUTINE ZGETF2( M, N, A, LDA, IPIV, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* ZGETF2 computes an LU factorization of a general m-by-n matrix A +* using partial pivoting with row interchanges. +* +* The factorization has the form +* A = P * L * U +* where P is a permutation matrix, L is lower triangular with unit +* diagonal elements (lower trapezoidal if m > n), and U is upper +* triangular (upper trapezoidal if m < n). +* +* This is the right-looking Level 2 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the m by n matrix to be factored. +* On exit, the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* > 0: if INFO = k, U(k,k) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE, ZERO + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ), + $ ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION SFMIN + INTEGER I, J, JP +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + INTEGER IZAMAX + EXTERNAL DLAMCH, IZAMAX +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZGERU, ZSCAL, ZSWAP +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGETF2', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Compute machine safe minimum +* + SFMIN = DLAMCH('S') +* + DO 10 J = 1, MIN( M, N ) +* +* Find pivot and test for singularity. +* + JP = J - 1 + IZAMAX( M-J+1, A( J, J ), 1 ) + IPIV( J ) = JP + IF( A( JP, J ).NE.ZERO ) THEN +* +* Apply the interchange to columns 1:N. +* + IF( JP.NE.J ) + $ CALL ZSWAP( N, A( J, 1 ), LDA, A( JP, 1 ), LDA ) +* +* Compute elements J+1:M of J-th column. +* + IF( J.LT.M ) THEN + IF( ABS(A( J, J )) .GE. SFMIN ) THEN + CALL ZSCAL( M-J, ONE / A( J, J ), A( J+1, J ), 1 ) + ELSE + DO 20 I = 1, M-J + A( J+I, J ) = A( J+I, J ) / A( J, J ) + 20 CONTINUE + END IF + END IF +* + ELSE IF( INFO.EQ.0 ) THEN +* + INFO = J + END IF +* + IF( J.LT.MIN( M, N ) ) THEN +* +* Update trailing submatrix. +* + CALL ZGERU( M-J, N-J, -ONE, A( J+1, J ), 1, A( J, J+1 ), + $ LDA, A( J+1, J+1 ), LDA ) + END IF + 10 CONTINUE + RETURN +* +* End of ZGETF2 +* + END diff --git a/dep/lapack/zgetrf.f b/dep/lapack/zgetrf.f new file mode 100644 index 00000000..23aabe9c --- /dev/null +++ b/dep/lapack/zgetrf.f @@ -0,0 +1,160 @@ + SUBROUTINE ZGETRF( M, N, A, LDA, IPIV, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, M, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* ZGETRF computes an LU factorization of a general M-by-N matrix A +* using partial pivoting with row interchanges. +* +* The factorization has the form +* A = P * L * U +* where P is a permutation matrix, L is lower triangular with unit +* diagonal elements (lower trapezoidal if m > n), and U is upper +* triangular (upper trapezoidal if m < n). +* +* This is the right-looking Level 3 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* M (input) INTEGER +* The number of rows of the matrix A. M >= 0. +* +* N (input) INTEGER +* The number of columns of the matrix A. N >= 0. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the M-by-N matrix to be factored. +* On exit, the factors L and U from the factorization +* A = P*L*U; the unit diagonal elements of L are not stored. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,M). +* +* IPIV (output) INTEGER array, dimension (min(M,N)) +* The pivot indices; for 1 <= i <= min(M,N), row i of the +* matrix was interchanged with row IPIV(i). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero. The factorization +* has been completed, but the factor U is exactly +* singular, and division by zero will occur if it is used +* to solve a system of equations. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + INTEGER I, IINFO, J, JB, NB +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZGEMM, ZGETF2, ZLASWP, ZTRSM +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + IF( M.LT.0 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( LDA.LT.MAX( 1, M ) ) THEN + INFO = -4 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGETRF', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( M.EQ.0 .OR. N.EQ.0 ) + $ RETURN +* +* Determine the block size for this environment. +* + NB = ILAENV( 1, 'ZGETRF', ' ', M, N, -1, -1 ) + IF( NB.LE.1 .OR. NB.GE.MIN( M, N ) ) THEN +* +* Use unblocked code. +* + CALL ZGETF2( M, N, A, LDA, IPIV, INFO ) + ELSE +* +* Use blocked code. +* + DO 20 J = 1, MIN( M, N ), NB + JB = MIN( MIN( M, N )-J+1, NB ) +* +* Factor diagonal and subdiagonal blocks and test for exact +* singularity. +* + CALL ZGETF2( M-J+1, JB, A( J, J ), LDA, IPIV( J ), IINFO ) +* +* Adjust INFO and the pivot indices. +* + IF( INFO.EQ.0 .AND. IINFO.GT.0 ) + $ INFO = IINFO + J - 1 + DO 10 I = J, MIN( M, J+JB-1 ) + IPIV( I ) = J - 1 + IPIV( I ) + 10 CONTINUE +* +* Apply interchanges to columns 1:J-1. +* + CALL ZLASWP( J-1, A, LDA, J, J+JB-1, IPIV, 1 ) +* + IF( J+JB.LE.N ) THEN +* +* Apply interchanges to columns J+JB:N. +* + CALL ZLASWP( N-J-JB+1, A( 1, J+JB ), LDA, J, J+JB-1, + $ IPIV, 1 ) +* +* Compute block row of U. +* + CALL ZTRSM( 'Left', 'Lower', 'No transpose', 'Unit', JB, + $ N-J-JB+1, ONE, A( J, J ), LDA, A( J, J+JB ), + $ LDA ) + IF( J+JB.LE.M ) THEN +* +* Update trailing submatrix. +* + CALL ZGEMM( 'No transpose', 'No transpose', M-J-JB+1, + $ N-J-JB+1, JB, -ONE, A( J+JB, J ), LDA, + $ A( J, J+JB ), LDA, ONE, A( J+JB, J+JB ), + $ LDA ) + END IF + END IF + 20 CONTINUE + END IF + RETURN +* +* End of ZGETRF +* + END diff --git a/dep/lapack/zgetri.f b/dep/lapack/zgetri.f new file mode 100644 index 00000000..188a3817 --- /dev/null +++ b/dep/lapack/zgetri.f @@ -0,0 +1,194 @@ + SUBROUTINE ZGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INFO, LDA, LWORK, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 A( LDA, * ), WORK( * ) +* .. +* +* Purpose +* ======= +* +* ZGETRI computes the inverse of a matrix using the LU factorization +* computed by ZGETRF. +* +* This method inverts U and then computes inv(A) by solving the system +* inv(A)*L = inv(U) for inv(A). +* +* Arguments +* ========= +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the factors L and U from the factorization +* A = P*L*U as computed by ZGETRF. +* On exit, if INFO = 0, the inverse of the original matrix A. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices from ZGETRF; for 1<=i<=N, row i of the +* matrix was interchanged with row IPIV(i). +* +* WORK (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) +* On exit, if INFO=0, then WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,N). +* For optimal performance LWORK >= N*NB, where NB is +* the optimal blocksize returned by ILAENV. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, U(i,i) is exactly zero; the matrix is +* singular and its inverse could not be computed. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ZERO, ONE + PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ), + $ ONE = ( 1.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + LOGICAL LQUERY + INTEGER I, IWS, J, JB, JJ, JP, LDWORK, LWKOPT, NB, + $ NBMIN, NN +* .. +* .. External Functions .. + INTEGER ILAENV + EXTERNAL ILAENV +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZGEMM, ZGEMV, ZSWAP, ZTRSM, ZTRTRI +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NB = ILAENV( 1, 'ZGETRI', ' ', N, -1, -1, -1 ) + LWKOPT = N*NB + WORK( 1 ) = LWKOPT + LQUERY = ( LWORK.EQ.-1 ) + IF( N.LT.0 ) THEN + INFO = -1 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -3 + ELSE IF( LWORK.LT.MAX( 1, N ) .AND. .NOT.LQUERY ) THEN + INFO = -6 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGETRI', -INFO ) + RETURN + ELSE IF( LQUERY ) THEN + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Form inv(U). If INFO > 0 from ZTRTRI, then U is singular, +* and the inverse is not computed. +* + CALL ZTRTRI( 'Upper', 'Non-unit', N, A, LDA, INFO ) + IF( INFO.GT.0 ) + $ RETURN +* + NBMIN = 2 + LDWORK = N + IF( NB.GT.1 .AND. NB.LT.N ) THEN + IWS = MAX( LDWORK*NB, 1 ) + IF( LWORK.LT.IWS ) THEN + NB = LWORK / LDWORK + NBMIN = MAX( 2, ILAENV( 2, 'ZGETRI', ' ', N, -1, -1, -1 ) ) + END IF + ELSE + IWS = N + END IF +* +* Solve the equation inv(A)*L = inv(U) for inv(A). +* + IF( NB.LT.NBMIN .OR. NB.GE.N ) THEN +* +* Use unblocked code. +* + DO 20 J = N, 1, -1 +* +* Copy current column of L to WORK and replace with zeros. +* + DO 10 I = J + 1, N + WORK( I ) = A( I, J ) + A( I, J ) = ZERO + 10 CONTINUE +* +* Compute current column of inv(A). +* + IF( J.LT.N ) + $ CALL ZGEMV( 'No transpose', N, N-J, -ONE, A( 1, J+1 ), + $ LDA, WORK( J+1 ), 1, ONE, A( 1, J ), 1 ) + 20 CONTINUE + ELSE +* +* Use blocked code. +* + NN = ( ( N-1 ) / NB )*NB + 1 + DO 50 J = NN, 1, -NB + JB = MIN( NB, N-J+1 ) +* +* Copy current block column of L to WORK and replace with +* zeros. +* + DO 40 JJ = J, J + JB - 1 + DO 30 I = JJ + 1, N + WORK( I+( JJ-J )*LDWORK ) = A( I, JJ ) + A( I, JJ ) = ZERO + 30 CONTINUE + 40 CONTINUE +* +* Compute current block column of inv(A). +* + IF( J+JB.LE.N ) + $ CALL ZGEMM( 'No transpose', 'No transpose', N, JB, + $ N-J-JB+1, -ONE, A( 1, J+JB ), LDA, + $ WORK( J+JB ), LDWORK, ONE, A( 1, J ), LDA ) + CALL ZTRSM( 'Right', 'Lower', 'No transpose', 'Unit', N, JB, + $ ONE, WORK( J ), LDWORK, A( 1, J ), LDA ) + 50 CONTINUE + END IF +* +* Apply column interchanges. +* + DO 60 J = N - 1, 1, -1 + JP = IPIV( J ) + IF( JP.NE.J ) + $ CALL ZSWAP( N, A( 1, J ), 1, A( 1, JP ), 1 ) + 60 CONTINUE +* + WORK( 1 ) = IWS + RETURN +* +* End of ZGETRI +* + END diff --git a/dep/lapack/zgetrs.f b/dep/lapack/zgetrs.f new file mode 100644 index 00000000..9c5de812 --- /dev/null +++ b/dep/lapack/zgetrs.f @@ -0,0 +1,150 @@ + SUBROUTINE ZGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO ) +* +* -- LAPACK routine (version 3.3.1) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* -- April 2011 -- +* +* .. Scalar Arguments .. + CHARACTER TRANS + INTEGER INFO, LDA, LDB, N, NRHS +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 A( LDA, * ), B( LDB, * ) +* .. +* +* Purpose +* ======= +* +* ZGETRS solves a system of linear equations +* A * X = B, A**T * X = B, or A**H * X = B +* with a general N-by-N matrix A using the LU factorization computed +* by ZGETRF. +* +* Arguments +* ========= +* +* TRANS (input) CHARACTER*1 +* Specifies the form of the system of equations: +* = 'N': A * X = B (No transpose) +* = 'T': A**T * X = B (Transpose) +* = 'C': A**H * X = B (Conjugate transpose) +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* NRHS (input) INTEGER +* The number of right hand sides, i.e., the number of columns +* of the matrix B. NRHS >= 0. +* +* A (input) COMPLEX*16 array, dimension (LDA,N) +* The factors L and U from the factorization A = P*L*U +* as computed by ZGETRF. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* IPIV (input) INTEGER array, dimension (N) +* The pivot indices from ZGETRF; for 1<=i<=N, row i of the +* matrix was interchanged with row IPIV(i). +* +* B (input/output) COMPLEX*16 array, dimension (LDB,NRHS) +* On entry, the right hand side matrix B. +* On exit, the solution matrix X. +* +* LDB (input) INTEGER +* The leading dimension of the array B. LDB >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + LOGICAL NOTRAN +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZLASWP, ZTRSM +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + NOTRAN = LSAME( TRANS, 'N' ) + IF( .NOT.NOTRAN .AND. .NOT.LSAME( TRANS, 'T' ) .AND. .NOT. + $ LSAME( TRANS, 'C' ) ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + ELSE IF( NRHS.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + ELSE IF( LDB.LT.MAX( 1, N ) ) THEN + INFO = -8 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZGETRS', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. NRHS.EQ.0 ) + $ RETURN +* + IF( NOTRAN ) THEN +* +* Solve A * X = B. +* +* Apply row interchanges to the right hand sides. +* + CALL ZLASWP( NRHS, B, LDB, 1, N, IPIV, 1 ) +* +* Solve L*X = B, overwriting B with X. +* + CALL ZTRSM( 'Left', 'Lower', 'No transpose', 'Unit', N, NRHS, + $ ONE, A, LDA, B, LDB ) +* +* Solve U*X = B, overwriting B with X. +* + CALL ZTRSM( 'Left', 'Upper', 'No transpose', 'Non-unit', N, + $ NRHS, ONE, A, LDA, B, LDB ) + ELSE +* +* Solve A**T * X = B or A**H * X = B. +* +* Solve U**T *X = B or U**H *X = B, overwriting B with X. +* + CALL ZTRSM( 'Left', 'Upper', TRANS, 'Non-unit', N, NRHS, ONE, + $ A, LDA, B, LDB ) +* +* Solve L**T *X = B, or L**H *X = B overwriting B with X. +* + CALL ZTRSM( 'Left', 'Lower', TRANS, 'Unit', N, NRHS, ONE, A, + $ LDA, B, LDB ) +* +* Apply row interchanges to the solution vectors. +* + CALL ZLASWP( NRHS, B, LDB, 1, N, IPIV, -1 ) + END IF +* + RETURN +* +* End of ZGETRS +* + END diff --git a/dep/lapack/zlaswp.f b/dep/lapack/zlaswp.f new file mode 100644 index 00000000..29edd05f --- /dev/null +++ b/dep/lapack/zlaswp.f @@ -0,0 +1,120 @@ + SUBROUTINE ZLASWP( N, A, LDA, K1, K2, IPIV, INCX ) +* +* -- LAPACK auxiliary routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + INTEGER INCX, K1, K2, LDA, N +* .. +* .. Array Arguments .. + INTEGER IPIV( * ) + COMPLEX*16 A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* ZLASWP performs a series of row interchanges on the matrix A. +* One row interchange is initiated for each of rows K1 through K2 of A. +* +* Arguments +* ========= +* +* N (input) INTEGER +* The number of columns of the matrix A. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the matrix of column dimension N to which the row +* interchanges will be applied. +* On exit, the permuted matrix. +* +* LDA (input) INTEGER +* The leading dimension of the array A. +* +* K1 (input) INTEGER +* The first element of IPIV for which a row interchange will +* be done. +* +* K2 (input) INTEGER +* The last element of IPIV for which a row interchange will +* be done. +* +* IPIV (input) INTEGER array, dimension (K2*abs(INCX)) +* The vector of pivot indices. Only the elements in positions +* K1 through K2 of IPIV are accessed. +* IPIV(K) = L implies rows K and L are to be interchanged. +* +* INCX (input) INTEGER +* The increment between successive values of IPIV. If IPIV +* is negative, the pivots are applied in reverse order. +* +* Further Details +* =============== +* +* Modified by +* R. C. Whaley, Computer Science Dept., Univ. of Tenn., Knoxville, USA +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, I1, I2, INC, IP, IX, IX0, J, K, N32 + COMPLEX*16 TEMP +* .. +* .. Executable Statements .. +* +* Interchange row I with row IPIV(I) for each of rows K1 through K2. +* + IF( INCX.GT.0 ) THEN + IX0 = K1 + I1 = K1 + I2 = K2 + INC = 1 + ELSE IF( INCX.LT.0 ) THEN + IX0 = 1 + ( 1-K2 )*INCX + I1 = K2 + I2 = K1 + INC = -1 + ELSE + RETURN + END IF +* + N32 = ( N / 32 )*32 + IF( N32.NE.0 ) THEN + DO 30 J = 1, N32, 32 + IX = IX0 + DO 20 I = I1, I2, INC + IP = IPIV( IX ) + IF( IP.NE.I ) THEN + DO 10 K = J, J + 31 + TEMP = A( I, K ) + A( I, K ) = A( IP, K ) + A( IP, K ) = TEMP + 10 CONTINUE + END IF + IX = IX + INCX + 20 CONTINUE + 30 CONTINUE + END IF + IF( N32.NE.N ) THEN + N32 = N32 + 1 + IX = IX0 + DO 50 I = I1, I2, INC + IP = IPIV( IX ) + IF( IP.NE.I ) THEN + DO 40 K = N32, N + TEMP = A( I, K ) + A( I, K ) = A( IP, K ) + A( IP, K ) = TEMP + 40 CONTINUE + END IF + IX = IX + INCX + 50 CONTINUE + END IF +* + RETURN +* +* End of ZLASWP +* + END diff --git a/dep/lapack/ztrti2.f b/dep/lapack/ztrti2.f new file mode 100644 index 00000000..0cf8c2af --- /dev/null +++ b/dep/lapack/ztrti2.f @@ -0,0 +1,147 @@ + SUBROUTINE ZTRTI2( UPLO, DIAG, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER DIAG, UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* ZTRTI2 computes the inverse of a complex upper or lower triangular +* matrix. +* +* This is the Level 2 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* Specifies whether the matrix A is upper or lower triangular. +* = 'U': Upper triangular +* = 'L': Lower triangular +* +* DIAG (input) CHARACTER*1 +* Specifies whether or not the matrix A is unit triangular. +* = 'N': Non-unit triangular +* = 'U': Unit triangular +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the triangular matrix A. If UPLO = 'U', the +* leading n by n upper triangular part of the array A contains +* the upper triangular matrix, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading n by n lower triangular part of the array A contains +* the lower triangular matrix, and the strictly upper +* triangular part of A is not referenced. If DIAG = 'U', the +* diagonal elements of A are also not referenced and are +* assumed to be 1. +* +* On exit, the (triangular) inverse of the original matrix, in +* the same storage format. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -k, the k-th argument had an illegal value +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + LOGICAL NOUNIT, UPPER + INTEGER J + COMPLEX*16 AJJ +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZSCAL, ZTRMV +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + NOUNIT = LSAME( DIAG, 'N' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZTRTI2', -INFO ) + RETURN + END IF +* + IF( UPPER ) THEN +* +* Compute inverse of upper triangular matrix. +* + DO 10 J = 1, N + IF( NOUNIT ) THEN + A( J, J ) = ONE / A( J, J ) + AJJ = -A( J, J ) + ELSE + AJJ = -ONE + END IF +* +* Compute elements 1:j-1 of j-th column. +* + CALL ZTRMV( 'Upper', 'No transpose', DIAG, J-1, A, LDA, + $ A( 1, J ), 1 ) + CALL ZSCAL( J-1, AJJ, A( 1, J ), 1 ) + 10 CONTINUE + ELSE +* +* Compute inverse of lower triangular matrix. +* + DO 20 J = N, 1, -1 + IF( NOUNIT ) THEN + A( J, J ) = ONE / A( J, J ) + AJJ = -A( J, J ) + ELSE + AJJ = -ONE + END IF + IF( J.LT.N ) THEN +* +* Compute elements j+1:n of j-th column. +* + CALL ZTRMV( 'Lower', 'No transpose', DIAG, N-J, + $ A( J+1, J+1 ), LDA, A( J+1, J ), 1 ) + CALL ZSCAL( N-J, AJJ, A( J+1, J ), 1 ) + END IF + 20 CONTINUE + END IF +* + RETURN +* +* End of ZTRTI2 +* + END diff --git a/dep/lapack/ztrtri.f b/dep/lapack/ztrtri.f new file mode 100644 index 00000000..8b193f0c --- /dev/null +++ b/dep/lapack/ztrtri.f @@ -0,0 +1,178 @@ + SUBROUTINE ZTRTRI( UPLO, DIAG, N, A, LDA, INFO ) +* +* -- LAPACK routine (version 3.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER DIAG, UPLO + INTEGER INFO, LDA, N +* .. +* .. Array Arguments .. + COMPLEX*16 A( LDA, * ) +* .. +* +* Purpose +* ======= +* +* ZTRTRI computes the inverse of a complex upper or lower triangular +* matrix A. +* +* This is the Level 3 BLAS version of the algorithm. +* +* Arguments +* ========= +* +* UPLO (input) CHARACTER*1 +* = 'U': A is upper triangular; +* = 'L': A is lower triangular. +* +* DIAG (input) CHARACTER*1 +* = 'N': A is non-unit triangular; +* = 'U': A is unit triangular. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) COMPLEX*16 array, dimension (LDA,N) +* On entry, the triangular matrix A. If UPLO = 'U', the +* leading N-by-N upper triangular part of the array A contains +* the upper triangular matrix, and the strictly lower +* triangular part of A is not referenced. If UPLO = 'L', the +* leading N-by-N lower triangular part of the array A contains +* the lower triangular matrix, and the strictly upper +* triangular part of A is not referenced. If DIAG = 'U', the +* diagonal elements of A are also not referenced and are +* assumed to be 1. +* On exit, the (triangular) inverse of the original matrix, in +* the same storage format. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: if INFO = i, A(i,i) is exactly zero. The triangular +* matrix is singular and its inverse can not be computed. +* +* ===================================================================== +* +* .. Parameters .. + COMPLEX*16 ONE, ZERO + PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ), + $ ZERO = ( 0.0D+0, 0.0D+0 ) ) +* .. +* .. Local Scalars .. + LOGICAL NOUNIT, UPPER + INTEGER J, JB, NB, NN +* .. +* .. External Functions .. + LOGICAL LSAME + INTEGER ILAENV + EXTERNAL LSAME, ILAENV +* .. +* .. External Subroutines .. + EXTERNAL XERBLA, ZTRMM, ZTRSM, ZTRTI2 +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 + UPPER = LSAME( UPLO, 'U' ) + NOUNIT = LSAME( DIAG, 'N' ) + IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN + INFO = -1 + ELSE IF( .NOT.NOUNIT .AND. .NOT.LSAME( DIAG, 'U' ) ) THEN + INFO = -2 + ELSE IF( N.LT.0 ) THEN + INFO = -3 + ELSE IF( LDA.LT.MAX( 1, N ) ) THEN + INFO = -5 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'ZTRTRI', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 ) + $ RETURN +* +* Check for singularity if non-unit. +* + IF( NOUNIT ) THEN + DO 10 INFO = 1, N + IF( A( INFO, INFO ).EQ.ZERO ) + $ RETURN + 10 CONTINUE + INFO = 0 + END IF +* +* Determine the block size for this environment. +* + NB = ILAENV( 1, 'ZTRTRI', UPLO // DIAG, N, -1, -1, -1 ) + IF( NB.LE.1 .OR. NB.GE.N ) THEN +* +* Use unblocked code +* + CALL ZTRTI2( UPLO, DIAG, N, A, LDA, INFO ) + ELSE +* +* Use blocked code +* + IF( UPPER ) THEN +* +* Compute inverse of upper triangular matrix +* + DO 20 J = 1, N, NB + JB = MIN( NB, N-J+1 ) +* +* Compute rows 1:j-1 of current block column +* + CALL ZTRMM( 'Left', 'Upper', 'No transpose', DIAG, J-1, + $ JB, ONE, A, LDA, A( 1, J ), LDA ) + CALL ZTRSM( 'Right', 'Upper', 'No transpose', DIAG, J-1, + $ JB, -ONE, A( J, J ), LDA, A( 1, J ), LDA ) +* +* Compute inverse of current diagonal block +* + CALL ZTRTI2( 'Upper', DIAG, JB, A( J, J ), LDA, INFO ) + 20 CONTINUE + ELSE +* +* Compute inverse of lower triangular matrix +* + NN = ( ( N-1 ) / NB )*NB + 1 + DO 30 J = NN, 1, -NB + JB = MIN( NB, N-J+1 ) + IF( J+JB.LE.N ) THEN +* +* Compute rows j+jb:n of current block column +* + CALL ZTRMM( 'Left', 'Lower', 'No transpose', DIAG, + $ N-J-JB+1, JB, ONE, A( J+JB, J+JB ), LDA, + $ A( J+JB, J ), LDA ) + CALL ZTRSM( 'Right', 'Lower', 'No transpose', DIAG, + $ N-J-JB+1, JB, -ONE, A( J, J ), LDA, + $ A( J+JB, J ), LDA ) + END IF +* +* Compute inverse of current diagonal block +* + CALL ZTRTI2( 'Lower', DIAG, JB, A( J, J ), LDA, INFO ) + 30 CONTINUE + END IF + END IF +* + RETURN +* +* End of ZTRTRI +* + END diff --git a/dep/lbfgs/CMakeLists.txt b/dep/lbfgs/CMakeLists.txt new file mode 100644 index 00000000..5fd109da --- /dev/null +++ b/dep/lbfgs/CMakeLists.txt @@ -0,0 +1,13 @@ + +enable_language(Fortran) + +add_library(deplbfgs lbfgsDR.c lbfgs_routines.f) +include_directories("../../cpp/lib/include") + +INSTALL(TARGETS deplbfgs DESTINATION lib) + +SET(lbfgs_HEADERS + lbfgs_routines.h + ) + +INSTALL(FILES ${lbfgs_HEADERS} DESTINATION include/dep) diff --git a/dep/lbfgs/LICENSE b/dep/lbfgs/LICENSE new file mode 100644 index 00000000..c8ece6d7 --- /dev/null +++ b/dep/lbfgs/LICENSE @@ -0,0 +1,54 @@ +Licensing information, downloaded 3/7/13 from http://users.eecs.northwestern.edu/~nocedal/lbfgsb.html + +L-BFGS-B +======== +Software for Large-scale Bound-constrained Optimization L-BFGS-B is a limited-memory +quasi-Newton code for bound-constrained optimization, i.e. for problems where the only +constraints are of the form l<= x <= u. The current release is version 3.0. The +distribution file was last changed on 02/08/11. + +(If you have an optimization problem with general constraints, try KNITRO® ) +Downloading and Installing L-BFGS-B + + Condition for Use: This software is freely available, but we expect that all + publications describing work using this software , or all commercial products using + it, quote at least one of the references given below. This software is released under + the "New BSD License" (aka "Modified BSD License" or "3-clause license"). + +You are welcome to grab the full Unix distribution, containing source code, Makefiles and User Guide. + +L-BFGS-B was upgraded on August 2, 2011 from version Lbfgsb.2.1 to version Lbfgsb.3.0 +(see reference 3. below). + +Click here to download L-BFGS-B version Lbfgsb.2.1 + +Click here to download L-BFGS-B version Lbfgsb.3.0 + +Both versions can be installed using the same commands: + +Save the gz file in a fresh subdirectory on your system. To install, first type + + gunzip Lbfgsb.m.n.tar.gz + +to produce a file Lbfgsb.m.n.tar. Then, type + + tar -xvf Lbfgsb.m.n.tar + +to create the directory Lbfgsb.m.n containing the source code, Makefiles and User Guide. +Authors + + Ciyou Zhu, Richard Byrd, Jorge Nocedal and Jose Luis Morales. + +Test results comparing L-BFGS-B (version Lbfgsb.2.1) and MINOS can be found here + +References +========== + R. H. Byrd, P. Lu and J. Nocedal. A Limited Memory Algorithm for Bound Constrained + Optimization, (1995), SIAM Journal on Scientific and Statistical Computing , 16, 5, pp. 1190-1208. + C. Zhu, R. H. Byrd and J. Nocedal. L-BFGS-B: Algorithm 778: L-BFGS-B, FORTRAN + routines for large scale bound constrained optimization (1997), ACM Transactions + on Mathematical Software, Vol 23, Num. 4, pp. 550 - 560. + J.L. Morales and J. Nocedal. L-BFGS-B: Remark on Algorithm 778: L-BFGS-B, FORTRAN + routines for large scale bound constrained optimization (2011), to appear in ACM + Transactions on Mathematical Software. + diff --git a/dep/lbfgs/lbfgsDR.c b/dep/lbfgs/lbfgsDR.c new file mode 100644 index 00000000..40a51dcd --- /dev/null +++ b/dep/lbfgs/lbfgsDR.c @@ -0,0 +1,214 @@ +/* + interface for lbfgs library. + + customized from driver2.f code downloaded with the library + + References: + + [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited + memory algorithm for bound constrained optimization'', + SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. + + [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN + Subroutines for Large Scale Bound Constrained Optimization'' + Tech. Report, NAM-11, EECS Department, Northwestern University, + 1994. + + */ +#include +#include +#include +#include + +#include "lbfgs_routines.h" +void macheps() ; +void gradfnum(int n, double *x, double *xp, double (* func)(int, double *, void*), + double *g, void *userdata) ; + +#define CSIZE 60 +#define GRADSMALL 1.e-15 +#define MAXFEVAL 100000 + +static double lbfgs_rt, lbfgs_at ; + +int lbfgsDR(int n, int m, double *x, int *nbd, double *l, double *u, + double (* func)(int, double *, void*), + void (* gradf)(int, double *, double *, void*), + void* userdata) +{ + + char task[CSIZE],csave[CSIZE] ; + unsigned int lsave[4] ; + + int iprint, *iwa, isave[44], lenwa ; + double f, factr, pgtol, *g, *xp, dsave[29], *wa ; + + int i, lcont ; + + int ans = 0 ; + + lenwa = 2*m*n + 5*n + 12*m*m + 12*m ; + + iwa = (int *)malloc(3*n* sizeof(int) ) ; + wa = (double *)malloc(lenwa*sizeof(double)) ; + g = (double *)malloc(n *sizeof(double)) ; + xp = (double *)malloc(n *sizeof(double)) ; + + + /* We suppress the default output. */ + iprint = -1 ; + + /* + We suppress both code-supplied stopping tests because the + user is providing his own stopping criteria. + */ + factr = 0.0 ; + pgtol = 0.0 ; + + /* We start the iteration by initializing task. */ + memset(task,32,CSIZE) ; /* put spaces (ascii code 32 in task) */ + sprintf(task,"START") ; + + /* Compute machine epsilon */ + macheps() ; + printf("Machine eps rt=%le, at=%le\n",lbfgs_rt,lbfgs_at); + + /* the beginning of the loop */ + do + { + + lcont = 0 ; + setulb_(&n, &m, x, l, u, nbd, &f, g, &factr, &pgtol, wa, iwa, task, + &iprint, csave, lsave, isave, dsave) ; + //printf("%s\n",task) ; + if ( strncmp(task,"FG",2) == 0 ) + { + + /* + the minimization routine has returned to request the + function f and gradient g values at the current x. + */ + + /* Compute function value f for the sample problem. */ + f = func(n,x,userdata) ; + + /* Compute gradient g for the sample problem. */ + if ( gradf == NULL ){ + gradfnum(n,x,xp,func,g,userdata) ; + } + else{ + gradf(n, x, g, userdata) ; + } + /* go back to the minimization routine. */ + lcont = 1 ; + } + if ( strncmp(task,"NEW_X",5) == 0 ) + { + /* + the minimization routine has returned with a new iterate. + At this point have the opportunity of stopping the iteration + or observing the values of certain parameters + + First are two examples of stopping tests. + + Note: task(1:4) must be assigned the value 'STOP' to terminate + the iteration and ensure that the final results are + printed in the default format. The rest of the character + string TASK may be used to store other information. + + 1) Terminate if the total number of f and g evaluations + exceeds MAXFEVAL. + */ + if ( isave[33] >= MAXFEVAL ) + sprintf(task,"STOP: TOTAL NO. of f AND g EVALUATIONS EXCEEDS LIMIT") ; + + /* + 2) Terminate if |proj g|/(1+|f|) < GRADSMALL, where + "proj g" denoted the projected gradient + */ + if ( dsave[12] <= GRADSMALL * ( 1.0 + fabs(f) ) ) + sprintf(task,"STOP: THE PROJECTED GRADIENT IS SUFFICIENTLY SMALL"); + + /* + We now wish to print the following information at each + iteration (indexes correspond to fortran): + + 1) the current iteration number, isave(30), + 2) the total number of f and g evaluations, isave(34), + 3) the value of the objective function f, + 4) the norm of the projected gradient, dsve(13) + + See the comments at the end of driver1 for a description + of the variables isave and dsave. + */ + + printf("Iterate %d nfg = %d f = %e |proj g| = %e\n",isave[29],isave[33],f, + dsave[12]) ; + + /* + If the run is to be terminated, we print also the information + contained in task as well as the final value of x. + */ + if ( strncmp(task,"STOP",4) == 0 ) + { + printf("%s\n",task) ; + printf("Final X = ") ; + for ( i=0; i= 0 is specified by the user. The iteration +c will stop when +c +c (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch +c +c where epsmch is the machine precision, which is automatically +c generated by the code. Typical values for factr: 1.d+12 for +c low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely +c high accuracy. +c On exit factr is unchanged. +c +c pgtol is a double precision variable. +c On entry pgtol >= 0 is specified by the user. The iteration +c will stop when +c +c max{|proj g_i | i = 1, ..., n} <= pgtol +c +c where pg_i is the ith component of the projected gradient. +c On exit pgtol is unchanged. +c +c wa is a double precision working array of length +c (2mmax + 5)nmax + 12mmax^2 + 12mmax. +c +c iwa is an integer working array of length 3nmax. +c +c task is a working string of characters of length 60 indicating +c the current job when entering and quitting this subroutine. +c +c iprint is an integer variable that must be set by the user. +c It controls the frequency and type of output generated: +c iprint<0 no output is generated; +c iprint=0 print only one line at the last iteration; +c 0100 print details of every iteration including x and g; +c When iprint > 0, the file iterate.dat will be created to +c summarize the iteration. +c +c csave is a working string of characters of length 60. +c +c lsave is a logical working array of dimension 4. +c On exit with 'task' = NEW_X, the following information is +c available: +c If lsave(1) = .true. then the initial X has been replaced by +c its projection in the feasible set; +c If lsave(2) = .true. then the problem is constrained; +c If lsave(3) = .true. then each variable has upper and lower +c bounds; +c +c isave is an integer working array of dimension 44. +c On exit with 'task' = NEW_X, the following information is +c available: +c isave(22) = the total number of intervals explored in the +c search of Cauchy points; +c isave(26) = the total number of skipped BFGS updates before +c the current iteration; +c isave(30) = the number of current iteration; +c isave(31) = the total number of BFGS updates prior the current +c iteration; +c isave(33) = the number of intervals explored in the search of +c Cauchy point in the current iteration; +c isave(34) = the total number of function and gradient +c evaluations; +c isave(36) = the number of function value or gradient +c evaluations in the current iteration; +c if isave(37) = 0 then the subspace argmin is within the box; +c if isave(37) = 1 then the subspace argmin is beyond the box; +c isave(38) = the number of free variables in the current +c iteration; +c isave(39) = the number of active constraints in the current +c iteration; +c n + 1 - isave(40) = the number of variables leaving the set of +c active constraints in the current iteration; +c isave(41) = the number of variables entering the set of active +c constraints in the current iteration. +c +c dsave is a double precision working array of dimension 29. +c On exit with 'task' = NEW_X, the following information is +c available: +c dsave(1) = current 'theta' in the BFGS matrix; +c dsave(2) = f(x) in the previous iteration; +c dsave(3) = factr*epsmch; +c dsave(4) = 2-norm of the line search direction vector; +c dsave(5) = the machine precision epsmch generated by the code; +c dsave(7) = the accumulated time spent on searching for +c Cauchy points; +c dsave(8) = the accumulated time spent on +c subspace minimization; +c dsave(9) = the accumulated time spent on line search; +c dsave(11) = the slope of the line search function at +c the current point of line search; +c dsave(12) = the maximum relative step length imposed in +c line search; +c dsave(13) = the infinity norm of the projected gradient; +c dsave(14) = the relative step length in the line search; +c dsave(15) = the slope of the line search function at +c the starting point of the line search; +c dsave(16) = the square of the 2-norm of the line search +c direction vector. +c +c Subprograms called: +c +c L-BFGS-B Library ... mainlb. +c +c +c References: +c +c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited +c memory algorithm for bound constrained optimization'', +c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. +c +c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a +c limited memory FORTRAN code for solving bound constrained +c optimization problems'', Tech. Report, NAM-11, EECS Department, +c Northwestern University, 1994. +c +c (Postscript files of these papers are available via anonymous +c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ +c-jlm-jn + integer l1,l2,l3,lws,lr,lz,lt,ld,lxp,lsg,lwa,lyg, + + lsgo,lwy,lsy,lss,lyy,lwt,lwn,lsnd,lygo + if (task(1:5) .eq. 'START') then + isave(1) = m*n + isave(2) = m**2 + isave(3) = 4*m**2 + isave(4) = 1 + isave(5) = isave(4) + isave(1) + isave(6) = isave(5) + isave(1) + isave(7) = isave(6) + isave(2) + isave(8) = isave(7) + isave(2) + isave(9) = isave(8) + isave(2) + isave(10) = isave(9) + isave(2) + isave(11) = isave(10) + isave(3) + isave(12) = isave(11) + isave(3) + isave(13) = isave(12) + n + isave(14) = isave(13) + n + isave(15) = isave(14) + n + isave(16) = isave(15) + n +c-jlm-jn + isave(17) = isave(16) + n + isave(18) = isave(17) + 8*m + isave(19) = isave(18) + m + isave(20) = isave(19) + m + isave(21) = isave(20) + m + endif + l1 = isave(1) + l2 = isave(2) + l3 = isave(3) + lws = isave(4) + lwy = isave(5) + lsy = isave(6) + lss = isave(7) + lyy = isave(8) + lwt = isave(9) + lwn = isave(10) + lsnd = isave(11) + lz = isave(12) + lr = isave(13) + ld = isave(14) + lt = isave(15) + lxp = isave(16) +c-jlm-jn + lwa = isave(17) + lsg = isave(18) + lsgo = isave(19) + lyg = isave(20) + lygo = isave(21) + + call mainlb(n,m,x,l,u,nbd,f,g,factr,pgtol, + + wa(lws),wa(lwy),wa(lsy),wa(lss),wa(lyy),wa(lwt), + + wa(lwn),wa(lsnd),wa(lz),wa(lr),wa(ld),wa(lt),wa(lxp), + + wa(lwa),wa(lsg),wa(lsgo),wa(lyg),wa(lygo), + + iwa(1),iwa(n+1),iwa(2*n+1),task,iprint, + + csave,lsave,isave(22),dsave) + + return + + end + +c======================= The end of setulb ============================= + + subroutine mainlb(n, m, x, l, u, nbd, f, g, factr, pgtol, ws, wy, + + sy, ss, yy, wt, wn, snd, z, r, d, t, xp, wa, sg, + + sgo, yg, ygo, index, iwhere, indx2, task, + + iprint, csave, lsave, isave, dsave) + + character*60 task, csave + logical lsave(4) + integer n, m, iprint, nbd(n), index(n), + + iwhere(n), indx2(n), isave(23) + double precision f, factr, pgtol, + + x(n), l(n), u(n), g(n), z(n), r(n), d(n), t(n), +c-jlm-jn + + xp(n), + + wa(8*m), sg(m), sgo(m), yg(m), ygo(m), + + ws(n, m), wy(n, m), sy(m, m), ss(m, m), yy(m, m), + + wt(m, m), wn(2*m, 2*m), snd(2*m, 2*m), dsave(29) + +c ************ +c +c Subroutine mainlb +c +c This subroutine solves bound constrained optimization problems by +c using the compact formula of the limited memory BFGS updates. +c +c n is an integer variable. +c On entry n is the number of variables. +c On exit n is unchanged. +c +c m is an integer variable. +c On entry m is the maximum number of variable metric +c corrections allowed in the limited memory matrix. +c On exit m is unchanged. +c +c x is a double precision array of dimension n. +c On entry x is an approximation to the solution. +c On exit x is the current approximation. +c +c l is a double precision array of dimension n. +c On entry l is the lower bound of x. +c On exit l is unchanged. +c +c u is a double precision array of dimension n. +c On entry u is the upper bound of x. +c On exit u is unchanged. +c +c nbd is an integer array of dimension n. +c On entry nbd represents the type of bounds imposed on the +c variables, and must be specified as follows: +c nbd(i)=0 if x(i) is unbounded, +c 1 if x(i) has only a lower bound, +c 2 if x(i) has both lower and upper bounds, +c 3 if x(i) has only an upper bound. +c On exit nbd is unchanged. +c +c f is a double precision variable. +c On first entry f is unspecified. +c On final exit f is the value of the function at x. +c +c g is a double precision array of dimension n. +c On first entry g is unspecified. +c On final exit g is the value of the gradient at x. +c +c factr is a double precision variable. +c On entry factr >= 0 is specified by the user. The iteration +c will stop when +c +c (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch +c +c where epsmch is the machine precision, which is automatically +c generated by the code. +c On exit factr is unchanged. +c +c pgtol is a double precision variable. +c On entry pgtol >= 0 is specified by the user. The iteration +c will stop when +c +c max{|proj g_i | i = 1, ..., n} <= pgtol +c +c where pg_i is the ith component of the projected gradient. +c On exit pgtol is unchanged. +c +c ws, wy, sy, and wt are double precision working arrays used to +c store the following information defining the limited memory +c BFGS matrix: +c ws, of dimension n x m, stores S, the matrix of s-vectors; +c wy, of dimension n x m, stores Y, the matrix of y-vectors; +c sy, of dimension m x m, stores S'Y; +c ss, of dimension m x m, stores S'S; +c yy, of dimension m x m, stores Y'Y; +c wt, of dimension m x m, stores the Cholesky factorization +c of (theta*S'S+LD^(-1)L'); see eq. +c (2.26) in [3]. +c +c wn is a double precision working array of dimension 2m x 2m +c used to store the LEL^T factorization of the indefinite matrix +c K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] +c [L_a -R_z theta*S'AA'S ] +c +c where E = [-I 0] +c [ 0 I] +c +c snd is a double precision working array of dimension 2m x 2m +c used to store the lower triangular part of +c N = [Y' ZZ'Y L_a'+R_z'] +c [L_a +R_z S'AA'S ] +c +c z(n),r(n),d(n),t(n), xp(n),wa(8*m) are double precision working arrays. +c z is used at different times to store the Cauchy point and +c the Newton point. +c xp is used to safeguard the projected Newton direction +c +c sg(m),sgo(m),yg(m),ygo(m) are double precision working arrays. +c +c index is an integer working array of dimension n. +c In subroutine freev, index is used to store the free and fixed +c variables at the Generalized Cauchy Point (GCP). +c +c iwhere is an integer working array of dimension n used to record +c the status of the vector x for GCP computation. +c iwhere(i)=0 or -3 if x(i) is free and has bounds, +c 1 if x(i) is fixed at l(i), and l(i) .ne. u(i) +c 2 if x(i) is fixed at u(i), and u(i) .ne. l(i) +c 3 if x(i) is always fixed, i.e., u(i)=x(i)=l(i) +c -1 if x(i) is always free, i.e., no bounds on it. +c +c indx2 is an integer working array of dimension n. +c Within subroutine cauchy, indx2 corresponds to the array iorder. +c In subroutine freev, a list of variables entering and leaving +c the free set is stored in indx2, and it is passed on to +c subroutine formk with this information. +c +c task is a working string of characters of length 60 indicating +c the current job when entering and leaving this subroutine. +c +c iprint is an INTEGER variable that must be set by the user. +c It controls the frequency and type of output generated: +c iprint<0 no output is generated; +c iprint=0 print only one line at the last iteration; +c 0100 print details of every iteration including x and g; +c When iprint > 0, the file iterate.dat will be created to +c summarize the iteration. +c +c csave is a working string of characters of length 60. +c +c lsave is a logical working array of dimension 4. +c +c isave is an integer working array of dimension 23. +c +c dsave is a double precision working array of dimension 29. +c +c +c Subprograms called +c +c L-BFGS-B Library ... cauchy, subsm, lnsrlb, formk, +c +c errclb, prn1lb, prn2lb, prn3lb, active, projgr, +c +c freev, cmprlb, matupd, formt. +c +c Minpack2 Library ... timer +c +c Linpack Library ... dcopy, ddot. +c +c +c References: +c +c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited +c memory algorithm for bound constrained optimization'', +c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. +c +c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN +c Subroutines for Large Scale Bound Constrained Optimization'' +c Tech. Report, NAM-11, EECS Department, Northwestern University, +c 1994. +c +c [3] R. Byrd, J. Nocedal and R. Schnabel "Representations of +c Quasi-Newton Matrices and their use in Limited Memory Methods'', +c Mathematical Programming 63 (1994), no. 4, pp. 129-156. +c +c (Postscript files of these papers are available via anonymous +c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + logical prjctd,cnstnd,boxed,updatd,wrk + character*3 word + integer i,k,nintol,itfile,iback,nskip, + + head,col,iter,itail,iupdat, + + nint,nfgv,info,ifun, + + iword,nfree,nact,ileave,nenter + double precision theta,fold,ddot,dr,rr,tol, + + xstep,sbgnrm,ddum,dnorm,dtd,epsmch, + + cpu1,cpu2,cachyt,sbtime,lnscht,time1,time2, + + gd,gdold,stp,stpmx,time + double precision one,zero,dpmeps + parameter (one=1.0d0,zero=0.0d0) + + if (task(1:5) .eq. 'START') then + + epsmch = dpmeps() + + call timer(time1) + +c Initialize counters and scalars when task='START'. + +c for the limited memory BFGS matrices: + col = 0 + head = 1 + theta = one + iupdat = 0 + updatd = .false. + +c for operation counts: + iter = 0 + nfgv = 0 + nint = 0 + nintol = 0 + nskip = 0 + nfree = n + +c for stopping tolerance: + tol = factr*epsmch + +c for measuring running time: + cachyt = 0 + sbtime = 0 + lnscht = 0 + +c 'word' records the status of subspace solutions. + word = '---' + +c 'info' records the termination information. + info = 0 + + if (iprint .ge. 1) then +c open a summary file 'iterate.dat' + open (8, file = 'iterate.dat', status = 'unknown') + itfile = 8 + endif + +c Check the input arguments for errors. + + call errclb(n,m,factr,l,u,nbd,task,info,k) + if (task(1:5) .eq. 'ERROR') then + call prn3lb(n,x,f,task,iprint,info,itfile, + + iter,nfgv,nintol,nskip,nact,sbgnrm, + + zero,nint,word,iback,stp,xstep,k, + + cachyt,sbtime,lnscht) + return + endif + + call prn1lb(n,m,l,u,x,iprint,itfile,epsmch) + +c Initialize iwhere & project x onto the feasible set. + + call active(n,l,u,nbd,x,iwhere,iprint,prjctd,cnstnd,boxed) + +c The end of the initialization. + + else +c restore local variables. + + prjctd = lsave(1) + cnstnd = lsave(2) + boxed = lsave(3) + updatd = lsave(4) + + nintol = isave(1) + itfile = isave(3) + iback = isave(4) + nskip = isave(5) + head = isave(6) + col = isave(7) + itail = isave(8) + iter = isave(9) + iupdat = isave(10) + nint = isave(12) + nfgv = isave(13) + info = isave(14) + ifun = isave(15) + iword = isave(16) + nfree = isave(17) + nact = isave(18) + ileave = isave(19) + nenter = isave(20) + + theta = dsave(1) + fold = dsave(2) + tol = dsave(3) + dnorm = dsave(4) + epsmch = dsave(5) + cpu1 = dsave(6) + cachyt = dsave(7) + sbtime = dsave(8) + lnscht = dsave(9) + time1 = dsave(10) + gd = dsave(11) + stpmx = dsave(12) + sbgnrm = dsave(13) + stp = dsave(14) + gdold = dsave(15) + dtd = dsave(16) + +c After returning from the driver go to the point where execution +c is to resume. + + if (task(1:5) .eq. 'FG_LN') goto 666 + if (task(1:5) .eq. 'NEW_X') goto 777 + if (task(1:5) .eq. 'FG_ST') goto 111 + if (task(1:4) .eq. 'STOP') then + if (task(7:9) .eq. 'CPU') then +c restore the previous iterate. + call dcopy(n,t,1,x,1) + call dcopy(n,r,1,g,1) + f = fold + endif + goto 999 + endif + endif + +c Compute f0 and g0. + + task = 'FG_START' +c return to the driver to calculate f and g; reenter at 111. + goto 1000 + 111 continue + nfgv = 1 + +c Compute the infinity norm of the (-) projected gradient. + + call projgr(n,l,u,nbd,x,g,sbgnrm) + + if (iprint .ge. 1) then + write (6,1002) iter,f,sbgnrm + write (itfile,1003) iter,nfgv,sbgnrm,f + endif + if (sbgnrm .le. pgtol) then +c terminate the algorithm. + task = 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL' + goto 999 + endif + +c ----------------- the beginning of the loop -------------------------- + + 222 continue + if (iprint .ge. 99) write (6,1001) iter + 1 + iword = -1 +c + if (.not. cnstnd .and. col .gt. 0) then +c skip the search for GCP. + call dcopy(n,x,1,z,1) + wrk = updatd + nint = 0 + goto 333 + endif + +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c +c Compute the Generalized Cauchy Point (GCP). +c +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + call timer(cpu1) + call cauchy(n,x,l,u,nbd,g,indx2,iwhere,t,d,z, + + m,wy,ws,sy,wt,theta,col,head, + + wa(1),wa(2*m+1),wa(4*m+1),wa(6*m+1),nint, + + sg,yg,iprint,sbgnrm,info,epsmch) + + if (info .ne. 0) then +c singular triangular system detected; refresh the lbfgs memory. + if(iprint .ge. 1) write (6, 1005) + info = 0 + col = 0 + head = 1 + theta = one + iupdat = 0 + updatd = .false. + call timer(cpu2) + cachyt = cachyt + cpu2 - cpu1 + goto 222 + endif + call timer(cpu2) + cachyt = cachyt + cpu2 - cpu1 + nintol = nintol + nint + +c Count the entering and leaving variables for iter > 0; +c find the index set of free and active variables at the GCP. + + call freev(n,nfree,index,nenter,ileave,indx2, + + iwhere,wrk,updatd,cnstnd,iprint,iter) + nact = n - nfree + + 333 continue + +c If there are no free variables or B=theta*I, then +c skip the subspace minimization. + + if (nfree .eq. 0 .or. col .eq. 0) goto 555 + +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c +c Subspace minimization. +c +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + call timer(cpu1) + +c Form the LEL^T factorization of the indefinite +c matrix K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] +c [L_a -R_z theta*S'AA'S ] +c where E = [-I 0] +c [ 0 I] + + if (wrk) call formk(n,nfree,index,nenter,ileave,indx2,iupdat, + + updatd,wn,snd,m,ws,wy,sy,theta,col,head,info) + if (info .ne. 0) then +c nonpositive definiteness in Cholesky factorization; +c refresh the lbfgs memory and restart the iteration. + if(iprint .ge. 1) write (6, 1006) + info = 0 + col = 0 + head = 1 + theta = one + iupdat = 0 + updatd = .false. + call timer(cpu2) + sbtime = sbtime + cpu2 - cpu1 + goto 222 + endif + +c compute r=-Z'B(xcp-xk)-Z'g (using wa(2m+1)=W'(xcp-x) +c from 'cauchy'). + call cmprlb(n,m,x,g,ws,wy,sy,wt,z,r,wa,index, + + theta,col,head,nfree,cnstnd,info) + if (info .ne. 0) goto 444 + +c-jlm-jn call the direct method. + + call subsm(n,m,nfree,index,l,u,nbd,z,r,xp,ws,wy, + + sy, wt, theta, x, g, + + col,head,iword,wa,wn,iprint, info) + 444 continue + if (info .ne. 0) then +c singular triangular system detected; +c refresh the lbfgs memory and restart the iteration. + if(iprint .ge. 1) write (6, 1005) + info = 0 + col = 0 + head = 1 + theta = one + iupdat = 0 + updatd = .false. + call timer(cpu2) + sbtime = sbtime + cpu2 - cpu1 + goto 222 + endif + + call timer(cpu2) + sbtime = sbtime + cpu2 - cpu1 + 555 continue + +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c +c Line search and optimality tests. +c +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + +c Generate the search direction d:=z-x. + + do 40 i = 1, n + d(i) = z(i) - x(i) + 40 continue + call timer(cpu1) + 666 continue + call lnsrlb(n,l,u,nbd,x,f,fold,gd,gdold,g,d,r,t,z,stp,dnorm, + + dtd,xstep,stpmx,iter,ifun,iback,nfgv,info,task, + + boxed,cnstnd,csave,isave(22),dsave(17)) + if (info .ne. 0 .or. iback .ge. 20) then +c restore the previous iterate. + call dcopy(n,t,1,x,1) + call dcopy(n,r,1,g,1) + f = fold + if (col .eq. 0) then +c abnormal termination. + if (info .eq. 0) then + info = -9 +c restore the actual number of f and g evaluations etc. + nfgv = nfgv - 1 + ifun = ifun - 1 + iback = iback - 1 + endif + task = 'ABNORMAL_TERMINATION_IN_LNSRCH' + iter = iter + 1 + goto 999 + else +c refresh the lbfgs memory and restart the iteration. + if(iprint .ge. 1) write (6, 1008) + if (info .eq. 0) nfgv = nfgv - 1 + info = 0 + col = 0 + head = 1 + theta = one + iupdat = 0 + updatd = .false. + task = 'RESTART_FROM_LNSRCH' + call timer(cpu2) + lnscht = lnscht + cpu2 - cpu1 + goto 222 + endif + else if (task(1:5) .eq. 'FG_LN') then +c return to the driver for calculating f and g; reenter at 666. + goto 1000 + else +c calculate and print out the quantities related to the new X. + call timer(cpu2) + lnscht = lnscht + cpu2 - cpu1 + iter = iter + 1 + +c Compute the infinity norm of the projected (-)gradient. + + call projgr(n,l,u,nbd,x,g,sbgnrm) + +c Print iteration information. + + call prn2lb(n,x,f,g,iprint,itfile,iter,nfgv,nact, + + sbgnrm,nint,word,iword,iback,stp,xstep) + goto 1000 + endif + 777 continue + +c Test for termination. + + if (sbgnrm .le. pgtol) then +c terminate the algorithm. + task = 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL' + goto 999 + endif + + ddum = max(abs(fold), abs(f), one) + if ((fold - f) .le. tol*ddum) then +c terminate the algorithm. +c print *, (fold-f) +c print *, tol +c print *, ddum + task = 'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH' + if (iback .ge. 10) info = -5 +c i.e., to issue a warning if iback>10 in the line search. + goto 999 + endif + +c Compute d=newx-oldx, r=newg-oldg, rr=y'y and dr=y's. + + do 42 i = 1, n + r(i) = g(i) - r(i) + 42 continue + rr = ddot(n,r,1,r,1) + if (stp .eq. one) then + dr = gd - gdold + ddum = -gdold + else + dr = (gd - gdold)*stp + call dscal(n,stp,d,1) + ddum = -gdold*stp + endif + + if (dr .le. epsmch*ddum) then +c skip the L-BFGS update. + nskip = nskip + 1 + updatd = .false. + if (iprint .ge. 1) write (6,1004) dr, ddum + goto 888 + endif + +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c +c Update the L-BFGS matrix. +c +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + updatd = .true. + iupdat = iupdat + 1 + +c Update matrices WS and WY and form the middle matrix in B. + + call matupd(n,m,ws,wy,sy,ss,d,r,itail, + + iupdat,col,head,theta,rr,dr,stp,dtd) + +c Form the upper half of the pds T = theta*SS + L*D^(-1)*L'; +c Store T in the upper triangular of the array wt; +c Cholesky factorize T to J*J' with +c J' stored in the upper triangular of wt. + + call formt(m,wt,sy,ss,col,theta,info) + + if (info .ne. 0) then +c nonpositive definiteness in Cholesky factorization; +c refresh the lbfgs memory and restart the iteration. + if(iprint .ge. 1) write (6, 1007) + info = 0 + col = 0 + head = 1 + theta = one + iupdat = 0 + updatd = .false. + goto 222 + endif + +c Now the inverse of the middle matrix in B is + +c [ D^(1/2) O ] [ -D^(1/2) D^(-1/2)*L' ] +c [ -L*D^(-1/2) J ] [ 0 J' ] + + 888 continue + +c -------------------- the end of the loop ----------------------------- + + goto 222 + 999 continue + call timer(time2) + time = time2 - time1 + call prn3lb(n,x,f,task,iprint,info,itfile, + + iter,nfgv,nintol,nskip,nact,sbgnrm, + + time,nint,word,iback,stp,xstep,k, + + cachyt,sbtime,lnscht) + 1000 continue + +c Save local variables. + + lsave(1) = prjctd + lsave(2) = cnstnd + lsave(3) = boxed + lsave(4) = updatd + + isave(1) = nintol + isave(3) = itfile + isave(4) = iback + isave(5) = nskip + isave(6) = head + isave(7) = col + isave(8) = itail + isave(9) = iter + isave(10) = iupdat + isave(12) = nint + isave(13) = nfgv + isave(14) = info + isave(15) = ifun + isave(16) = iword + isave(17) = nfree + isave(18) = nact + isave(19) = ileave + isave(20) = nenter + + dsave(1) = theta + dsave(2) = fold + dsave(3) = tol + dsave(4) = dnorm + dsave(5) = epsmch + dsave(6) = cpu1 + dsave(7) = cachyt + dsave(8) = sbtime + dsave(9) = lnscht + dsave(10) = time1 + dsave(11) = gd + dsave(12) = stpmx + dsave(13) = sbgnrm + dsave(14) = stp + dsave(15) = gdold + dsave(16) = dtd + + 1001 format (//,'ITERATION ',i5) + 1002 format + + (/,'At iterate',i5,4x,'f= ',1p,d12.5,4x,'|proj g|= ',1p,d12.5) + 1003 format (2(1x,i4),5x,'-',5x,'-',3x,'-',5x,'-',5x,'-',8x,'-',3x, + + 1p,2(1x,d10.3)) + 1004 format (' ys=',1p,e10.3,' -gs=',1p,e10.3,' BFGS update SKIPPED') + 1005 format (/, + +' Singular triangular system detected;',/, + +' refresh the lbfgs memory and restart the iteration.') + 1006 format (/, + +' Nonpositive definiteness in Cholesky factorization in formk;',/, + +' refresh the lbfgs memory and restart the iteration.') + 1007 format (/, + +' Nonpositive definiteness in Cholesky factorization in formt;',/, + +' refresh the lbfgs memory and restart the iteration.') + 1008 format (/, + +' Bad direction in the line search;',/, + +' refresh the lbfgs memory and restart the iteration.') + + return + + end + +c======================= The end of mainlb ============================= + + subroutine active(n, l, u, nbd, x, iwhere, iprint, + + prjctd, cnstnd, boxed) + + logical prjctd, cnstnd, boxed + integer n, iprint, nbd(n), iwhere(n) + double precision x(n), l(n), u(n) + +c ************ +c +c Subroutine active +c +c This subroutine initializes iwhere and projects the initial x to +c the feasible set if necessary. +c +c iwhere is an integer array of dimension n. +c On entry iwhere is unspecified. +c On exit iwhere(i)=-1 if x(i) has no bounds +c 3 if l(i)=u(i) +c 0 otherwise. +c In cauchy, iwhere is given finer gradations. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer nbdd,i + double precision zero + parameter (zero=0.0d0) + +c Initialize nbdd, prjctd, cnstnd and boxed. + + nbdd = 0 + prjctd = .false. + cnstnd = .false. + boxed = .true. + +c Project the initial x to the easible set if necessary. + + do 10 i = 1, n + if (nbd(i) .gt. 0) then + if (nbd(i) .le. 2 .and. x(i) .le. l(i)) then + if (x(i) .lt. l(i)) then + prjctd = .true. + x(i) = l(i) + endif + nbdd = nbdd + 1 + else if (nbd(i) .ge. 2 .and. x(i) .ge. u(i)) then + if (x(i) .gt. u(i)) then + prjctd = .true. + x(i) = u(i) + endif + nbdd = nbdd + 1 + endif + endif + 10 continue + +c Initialize iwhere and assign values to cnstnd and boxed. + + do 20 i = 1, n + if (nbd(i) .ne. 2) boxed = .false. + if (nbd(i) .eq. 0) then +c this variable is always free + iwhere(i) = -1 + +c otherwise set x(i)=mid(x(i), u(i), l(i)). + else + cnstnd = .true. + if (nbd(i) .eq. 2 .and. u(i) - l(i) .le. zero) then +c this variable is always fixed + iwhere(i) = 3 + else + iwhere(i) = 0 + endif + endif + 20 continue + + if (iprint .ge. 0) then + if (prjctd) write (6,*) + + 'The initial X is infeasible. Restart with its projection.' + if (.not. cnstnd) + + write (6,*) 'This problem is unconstrained.' + endif + + if (iprint .gt. 0) write (6,1001) nbdd + + 1001 format (/,'At X0 ',i9,' variables are exactly at the bounds') + + return + + end + +c======================= The end of active ============================= + + subroutine bmv(m, sy, wt, col, v, p, info) + + integer m, col, info + double precision sy(m, m), wt(m, m), v(2*col), p(2*col) + +c ************ +c +c Subroutine bmv +c +c This subroutine computes the product of the 2m x 2m middle matrix +c in the compact L-BFGS formula of B and a 2m vector v; +c it returns the product in p. +c +c m is an integer variable. +c On entry m is the maximum number of variable metric corrections +c used to define the limited memory matrix. +c On exit m is unchanged. +c +c sy is a double precision array of dimension m x m. +c On entry sy specifies the matrix S'Y. +c On exit sy is unchanged. +c +c wt is a double precision array of dimension m x m. +c On entry wt specifies the upper triangular matrix J' which is +c the Cholesky factor of (thetaS'S+LD^(-1)L'). +c On exit wt is unchanged. +c +c col is an integer variable. +c On entry col specifies the number of s-vectors (or y-vectors) +c stored in the compact L-BFGS formula. +c On exit col is unchanged. +c +c v is a double precision array of dimension 2col. +c On entry v specifies vector v. +c On exit v is unchanged. +c +c p is a double precision array of dimension 2col. +c On entry p is unspecified. +c On exit p is the product Mv. +c +c info is an integer variable. +c On entry info is unspecified. +c On exit info = 0 for normal return, +c = nonzero for abnormal return when the system +c to be solved by dtrsl is singular. +c +c Subprograms called: +c +c Linpack ... dtrsl. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i,k,i2 + double precision sum + + if (col .eq. 0) return + +c PART I: solve [ D^(1/2) O ] [ p1 ] = [ v1 ] +c [ -L*D^(-1/2) J ] [ p2 ] [ v2 ]. + +c solve Jp2=v2+LD^(-1)v1. + p(col + 1) = v(col + 1) + do 20 i = 2, col + i2 = col + i + sum = 0.0d0 + do 10 k = 1, i - 1 + sum = sum + sy(i,k)*v(k)/sy(k,k) + 10 continue + p(i2) = v(i2) + sum + 20 continue +c Solve the triangular system + call dtrsl(wt,m,col,p(col+1),11,info) + if (info .ne. 0) return + +c solve D^(1/2)p1=v1. + do 30 i = 1, col + p(i) = v(i)/sqrt(sy(i,i)) + 30 continue + +c PART II: solve [ -D^(1/2) D^(-1/2)*L' ] [ p1 ] = [ p1 ] +c [ 0 J' ] [ p2 ] [ p2 ]. + +c solve J^Tp2=p2. + call dtrsl(wt,m,col,p(col+1),01,info) + if (info .ne. 0) return + +c compute p1=-D^(-1/2)(p1-D^(-1/2)L'p2) +c =-D^(-1/2)p1+D^(-1)L'p2. + do 40 i = 1, col + p(i) = -p(i)/sqrt(sy(i,i)) + 40 continue + do 60 i = 1, col + sum = 0.d0 + do 50 k = i + 1, col + sum = sum + sy(k,i)*p(col+k)/sy(i,i) + 50 continue + p(i) = p(i) + sum + 60 continue + + return + + end + +c======================== The end of bmv =============================== + + subroutine cauchy(n, x, l, u, nbd, g, iorder, iwhere, t, d, xcp, + + m, wy, ws, sy, wt, theta, col, head, p, c, wbp, + + v, nint, sg, yg, iprint, sbgnrm, info, epsmch) + + integer n, m, head, col, nint, iprint, info, + + nbd(n), iorder(n), iwhere(n) + double precision theta, epsmch, + + x(n), l(n), u(n), g(n), t(n), d(n), xcp(n), + + sg(m), yg(m), wy(n, col), ws(n, col), sy(m, m), + + wt(m, m), p(2*m), c(2*m), wbp(2*m), v(2*m) + +c ************ +c +c Subroutine cauchy +c +c For given x, l, u, g (with sbgnrm > 0), and a limited memory +c BFGS matrix B defined in terms of matrices WY, WS, WT, and +c scalars head, col, and theta, this subroutine computes the +c generalized Cauchy point (GCP), defined as the first local +c minimizer of the quadratic +c +c Q(x + s) = g's + 1/2 s'Bs +c +c along the projected gradient direction P(x-tg,l,u). +c The routine returns the GCP in xcp. +c +c n is an integer variable. +c On entry n is the dimension of the problem. +c On exit n is unchanged. +c +c x is a double precision array of dimension n. +c On entry x is the starting point for the GCP computation. +c On exit x is unchanged. +c +c l is a double precision array of dimension n. +c On entry l is the lower bound of x. +c On exit l is unchanged. +c +c u is a double precision array of dimension n. +c On entry u is the upper bound of x. +c On exit u is unchanged. +c +c nbd is an integer array of dimension n. +c On entry nbd represents the type of bounds imposed on the +c variables, and must be specified as follows: +c nbd(i)=0 if x(i) is unbounded, +c 1 if x(i) has only a lower bound, +c 2 if x(i) has both lower and upper bounds, and +c 3 if x(i) has only an upper bound. +c On exit nbd is unchanged. +c +c g is a double precision array of dimension n. +c On entry g is the gradient of f(x). g must be a nonzero vector. +c On exit g is unchanged. +c +c iorder is an integer working array of dimension n. +c iorder will be used to store the breakpoints in the piecewise +c linear path and free variables encountered. On exit, +c iorder(1),...,iorder(nleft) are indices of breakpoints +c which have not been encountered; +c iorder(nleft+1),...,iorder(nbreak) are indices of +c encountered breakpoints; and +c iorder(nfree),...,iorder(n) are indices of variables which +c have no bound constraits along the search direction. +c +c iwhere is an integer array of dimension n. +c On entry iwhere indicates only the permanently fixed (iwhere=3) +c or free (iwhere= -1) components of x. +c On exit iwhere records the status of the current x variables. +c iwhere(i)=-3 if x(i) is free and has bounds, but is not moved +c 0 if x(i) is free and has bounds, and is moved +c 1 if x(i) is fixed at l(i), and l(i) .ne. u(i) +c 2 if x(i) is fixed at u(i), and u(i) .ne. l(i) +c 3 if x(i) is always fixed, i.e., u(i)=x(i)=l(i) +c -1 if x(i) is always free, i.e., it has no bounds. +c +c t is a double precision working array of dimension n. +c t will be used to store the break points. +c +c d is a double precision array of dimension n used to store +c the Cauchy direction P(x-tg)-x. +c +c xcp is a double precision array of dimension n used to return the +c GCP on exit. +c +c m is an integer variable. +c On entry m is the maximum number of variable metric corrections +c used to define the limited memory matrix. +c On exit m is unchanged. +c +c ws, wy, sy, and wt are double precision arrays. +c On entry they store information that defines the +c limited memory BFGS matrix: +c ws(n,m) stores S, a set of s-vectors; +c wy(n,m) stores Y, a set of y-vectors; +c sy(m,m) stores S'Y; +c wt(m,m) stores the +c Cholesky factorization of (theta*S'S+LD^(-1)L'). +c On exit these arrays are unchanged. +c +c theta is a double precision variable. +c On entry theta is the scaling factor specifying B_0 = theta I. +c On exit theta is unchanged. +c +c col is an integer variable. +c On entry col is the actual number of variable metric +c corrections stored so far. +c On exit col is unchanged. +c +c head is an integer variable. +c On entry head is the location of the first s-vector (or y-vector) +c in S (or Y). +c On exit col is unchanged. +c +c p is a double precision working array of dimension 2m. +c p will be used to store the vector p = W^(T)d. +c +c c is a double precision working array of dimension 2m. +c c will be used to store the vector c = W^(T)(xcp-x). +c +c wbp is a double precision working array of dimension 2m. +c wbp will be used to store the row of W corresponding +c to a breakpoint. +c +c v is a double precision working array of dimension 2m. +c +c nint is an integer variable. +c On exit nint records the number of quadratic segments explored +c in searching for the GCP. +c +c sg and yg are double precision arrays of dimension m. +c On entry sg and yg store S'g and Y'g correspondingly. +c On exit they are unchanged. +c +c iprint is an INTEGER variable that must be set by the user. +c It controls the frequency and type of output generated: +c iprint<0 no output is generated; +c iprint=0 print only one line at the last iteration; +c 0100 print details of every iteration including x and g; +c When iprint > 0, the file iterate.dat will be created to +c summarize the iteration. +c +c sbgnrm is a double precision variable. +c On entry sbgnrm is the norm of the projected gradient at x. +c On exit sbgnrm is unchanged. +c +c info is an integer variable. +c On entry info is 0. +c On exit info = 0 for normal return, +c = nonzero for abnormal return when the the system +c used in routine bmv is singular. +c +c Subprograms called: +c +c L-BFGS-B Library ... hpsolb, bmv. +c +c Linpack ... dscal dcopy, daxpy. +c +c +c References: +c +c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited +c memory algorithm for bound constrained optimization'', +c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. +c +c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN +c Subroutines for Large Scale Bound Constrained Optimization'' +c Tech. Report, NAM-11, EECS Department, Northwestern University, +c 1994. +c +c (Postscript files of these papers are available via anonymous +c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + logical xlower,xupper,bnded + integer i,j,col2,nfree,nbreak,pointr, + + ibp,nleft,ibkmin,iter + double precision f1,f2,dt,dtm,tsum,dibp,zibp,dibp2,bkmin, + + tu,tl,wmc,wmp,wmw,ddot,tj,tj0,neggi,sbgnrm, + + f2_org + double precision one,zero + parameter (one=1.0d0,zero=0.0d0) + +c Check the status of the variables, reset iwhere(i) if necessary; +c compute the Cauchy direction d and the breakpoints t; initialize +c the derivative f1 and the vector p = W'd (for theta = 1). + + if (sbgnrm .le. zero) then + if (iprint .ge. 0) write (6,*) 'Subgnorm = 0. GCP = X.' + call dcopy(n,x,1,xcp,1) + return + endif + bnded = .true. + nfree = n + 1 + nbreak = 0 + ibkmin = 0 + bkmin = zero + col2 = 2*col + f1 = zero + if (iprint .ge. 99) write (6,3010) + +c We set p to zero and build it up as we determine d. + + do 20 i = 1, col2 + p(i) = zero + 20 continue + +c In the following loop we determine for each variable its bound +c status and its breakpoint, and update p accordingly. +c Smallest breakpoint is identified. + + do 50 i = 1, n + + neggi = -g(i) + if (iwhere(i) .ne. 3 .and. iwhere(i) .ne. -1) then +c if x(i) is not a constant and has bounds, +c compute the difference between x(i) and its bounds. + if (nbd(i) .le. 2) tl = x(i) - l(i) + if (nbd(i) .ge. 2) tu = u(i) - x(i) + +c If a variable is close enough to a bound +c we treat it as at bound. + xlower = nbd(i) .le. 2 .and. tl .le. zero + xupper = nbd(i) .ge. 2 .and. tu .le. zero + +c reset iwhere(i). + iwhere(i) = 0 + if (xlower) then + if (neggi .le. zero) iwhere(i) = 1 + else if (xupper) then + if (neggi .ge. zero) iwhere(i) = 2 + else + if (abs(neggi) .le. zero) iwhere(i) = -3 + endif + endif + + pointr = head + if (iwhere(i) .ne. 0 .and. iwhere(i) .ne. -1) then + d(i) = zero + else + d(i) = neggi + f1 = f1 - neggi*neggi +c calculate p := p - W'e_i* (g_i). + + do 40 j = 1, col + p(j) = p(j) + wy(i,pointr)* neggi + p(col + j) = p(col + j) + ws(i,pointr)*neggi + pointr = mod(pointr,m) + 1 + 40 continue + + if (nbd(i) .le. 2 .and. nbd(i) .ne. 0 + + .and. neggi .lt. zero) then +c x(i) + d(i) is bounded; compute t(i). + nbreak = nbreak + 1 + iorder(nbreak) = i + t(nbreak) = tl/(-neggi) + if (nbreak .eq. 1 .or. t(nbreak) .lt. bkmin) then + bkmin = t(nbreak) + ibkmin = nbreak + endif + else if (nbd(i) .ge. 2 .and. neggi .gt. zero) then +c x(i) + d(i) is bounded; compute t(i). + nbreak = nbreak + 1 + iorder(nbreak) = i + t(nbreak) = tu/neggi + if (nbreak .eq. 1 .or. t(nbreak) .lt. bkmin) then + bkmin = t(nbreak) + ibkmin = nbreak + endif + else +c x(i) + d(i) is not bounded. + nfree = nfree - 1 + iorder(nfree) = i + if (abs(neggi) .gt. zero) bnded = .false. + endif + endif + 50 continue + +c The indices of the nonzero components of d are now stored +c in iorder(1),...,iorder(nbreak) and iorder(nfree),...,iorder(n). +c The smallest of the nbreak breakpoints is in t(ibkmin)=bkmin. + + if (theta .ne. one) then +c complete the initialization of p for theta not= one. + call dscal(col,theta,p(col+1),1) + endif + +c Initialize GCP xcp = x. + + call dcopy(n,x,1,xcp,1) + + if (nbreak .eq. 0 .and. nfree .eq. n + 1) then +c is a zero vector, return with the initial xcp as GCP. + if (iprint .gt. 100) write (6,1010) (xcp(i), i = 1, n) + return + endif + +c Initialize c = W'(xcp - x) = 0. + + do 60 j = 1, col2 + c(j) = zero + 60 continue + +c Initialize derivative f2. + + f2 = -theta*f1 + f2_org = f2 + if (col .gt. 0) then + call bmv(m,sy,wt,col,p,v,info) + if (info .ne. 0) return + f2 = f2 - ddot(col2,v,1,p,1) + endif + dtm = -f1/f2 + tsum = zero + nint = 1 + if (iprint .ge. 99) + + write (6,*) 'There are ',nbreak,' breakpoints ' + +c If there are no breakpoints, locate the GCP and return. + + if (nbreak .eq. 0) goto 888 + + nleft = nbreak + iter = 1 + + + tj = zero + +c------------------- the beginning of the loop ------------------------- + + 777 continue + +c Find the next smallest breakpoint; +c compute dt = t(nleft) - t(nleft + 1). + + tj0 = tj + if (iter .eq. 1) then +c Since we already have the smallest breakpoint we need not do +c heapsort yet. Often only one breakpoint is used and the +c cost of heapsort is avoided. + tj = bkmin + ibp = iorder(ibkmin) + else + if (iter .eq. 2) then +c Replace the already used smallest breakpoint with the +c breakpoint numbered nbreak > nlast, before heapsort call. + if (ibkmin .ne. nbreak) then + t(ibkmin) = t(nbreak) + iorder(ibkmin) = iorder(nbreak) + endif +c Update heap structure of breakpoints +c (if iter=2, initialize heap). + endif + call hpsolb(nleft,t,iorder,iter-2) + tj = t(nleft) + ibp = iorder(nleft) + endif + + dt = tj - tj0 + + if (dt .ne. zero .and. iprint .ge. 100) then + write (6,4011) nint,f1,f2 + write (6,5010) dt + write (6,6010) dtm + endif + +c If a minimizer is within this interval, locate the GCP and return. + + if (dtm .lt. dt) goto 888 + +c Otherwise fix one variable and +c reset the corresponding component of d to zero. + + tsum = tsum + dt + nleft = nleft - 1 + iter = iter + 1 + dibp = d(ibp) + d(ibp) = zero + if (dibp .gt. zero) then + zibp = u(ibp) - x(ibp) + xcp(ibp) = u(ibp) + iwhere(ibp) = 2 + else + zibp = l(ibp) - x(ibp) + xcp(ibp) = l(ibp) + iwhere(ibp) = 1 + endif + if (iprint .ge. 100) write (6,*) 'Variable ',ibp,' is fixed.' + if (nleft .eq. 0 .and. nbreak .eq. n) then +c all n variables are fixed, +c return with xcp as GCP. + dtm = dt + goto 999 + endif + +c Update the derivative information. + + nint = nint + 1 + dibp2 = dibp**2 + +c Update f1 and f2. + +c temporarily set f1 and f2 for col=0. + f1 = f1 + dt*f2 + dibp2 - theta*dibp*zibp + f2 = f2 - theta*dibp2 + + if (col .gt. 0) then +c update c = c + dt*p. + call daxpy(col2,dt,p,1,c,1) + +c choose wbp, +c the row of W corresponding to the breakpoint encountered. + pointr = head + do 70 j = 1,col + wbp(j) = wy(ibp,pointr) + wbp(col + j) = theta*ws(ibp,pointr) + pointr = mod(pointr,m) + 1 + 70 continue + +c compute (wbp)Mc, (wbp)Mp, and (wbp)M(wbp)'. + call bmv(m,sy,wt,col,wbp,v,info) + if (info .ne. 0) return + wmc = ddot(col2,c,1,v,1) + wmp = ddot(col2,p,1,v,1) + wmw = ddot(col2,wbp,1,v,1) + +c update p = p - dibp*wbp. + call daxpy(col2,-dibp,wbp,1,p,1) + +c complete updating f1 and f2 while col > 0. + f1 = f1 + dibp*wmc + f2 = f2 + 2.0d0*dibp*wmp - dibp2*wmw + endif + + f2 = max(epsmch*f2_org,f2) + if (nleft .gt. 0) then + dtm = -f1/f2 + goto 777 +c to repeat the loop for unsearched intervals. + else if(bnded) then + f1 = zero + f2 = zero + dtm = zero + else + dtm = -f1/f2 + endif + +c------------------- the end of the loop ------------------------------- + + 888 continue + if (iprint .ge. 99) then + write (6,*) + write (6,*) 'GCP found in this segment' + write (6,4010) nint,f1,f2 + write (6,6010) dtm + endif + if (dtm .le. zero) dtm = zero + tsum = tsum + dtm + +c Move free variables (i.e., the ones w/o breakpoints) and +c the variables whose breakpoints haven't been reached. + + call daxpy(n,tsum,d,1,xcp,1) + + 999 continue + +c Update c = c + dtm*p = W'(x^c - x) +c which will be used in computing r = Z'(B(x^c - x) + g). + + if (col .gt. 0) call daxpy(col2,dtm,p,1,c,1) + if (iprint .gt. 100) write (6,1010) (xcp(i),i = 1,n) + if (iprint .ge. 99) write (6,2010) + + 1010 format ('Cauchy X = ',/,(4x,1p,6(1x,d11.4))) + 2010 format (/,'---------------- exit CAUCHY----------------------',/) + 3010 format (/,'---------------- CAUCHY entered-------------------') + 4010 format ('Piece ',i3,' --f1, f2 at start point ',1p,2(1x,d11.4)) + 4011 format (/,'Piece ',i3,' --f1, f2 at start point ', + + 1p,2(1x,d11.4)) + 5010 format ('Distance to the next break point = ',1p,d11.4) + 6010 format ('Distance to the stationary point = ',1p,d11.4) + + return + + end + +c====================== The end of cauchy ============================== + + subroutine cmprlb(n, m, x, g, ws, wy, sy, wt, z, r, wa, index, + + theta, col, head, nfree, cnstnd, info) + + logical cnstnd + integer n, m, col, head, nfree, info, index(n) + double precision theta, + + x(n), g(n), z(n), r(n), wa(4*m), + + ws(n, m), wy(n, m), sy(m, m), wt(m, m) + +c ************ +c +c Subroutine cmprlb +c +c This subroutine computes r=-Z'B(xcp-xk)-Z'g by using +c wa(2m+1)=W'(xcp-x) from subroutine cauchy. +c +c Subprograms called: +c +c L-BFGS-B Library ... bmv. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i,j,k,pointr + double precision a1,a2 + + if (.not. cnstnd .and. col .gt. 0) then + do 26 i = 1, n + r(i) = -g(i) + 26 continue + else + do 30 i = 1, nfree + k = index(i) + r(i) = -theta*(z(k) - x(k)) - g(k) + 30 continue + call bmv(m,sy,wt,col,wa(2*m+1),wa(1),info) + if (info .ne. 0) then + info = -8 + return + endif + pointr = head + do 34 j = 1, col + a1 = wa(j) + a2 = theta*wa(col + j) + do 32 i = 1, nfree + k = index(i) + r(i) = r(i) + wy(k,pointr)*a1 + ws(k,pointr)*a2 + 32 continue + pointr = mod(pointr,m) + 1 + 34 continue + endif + + return + + end + +c======================= The end of cmprlb ============================= + + subroutine errclb(n, m, factr, l, u, nbd, task, info, k) + + character*60 task + integer n, m, info, k, nbd(n) + double precision factr, l(n), u(n) + +c ************ +c +c Subroutine errclb +c +c This subroutine checks the validity of the input data. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i + double precision one,zero + parameter (one=1.0d0,zero=0.0d0) + +c Check the input arguments for errors. + + if (n .le. 0) task = 'ERROR: N .LE. 0' + if (m .le. 0) task = 'ERROR: M .LE. 0' + if (factr .lt. zero) task = 'ERROR: FACTR .LT. 0' + +c Check the validity of the arrays nbd(i), u(i), and l(i). + + do 10 i = 1, n + if (nbd(i) .lt. 0 .or. nbd(i) .gt. 3) then +c return + task = 'ERROR: INVALID NBD' + info = -6 + k = i + endif + if (nbd(i) .eq. 2) then + if (l(i) .gt. u(i)) then +c return + task = 'ERROR: NO FEASIBLE SOLUTION' + info = -7 + k = i + endif + endif + 10 continue + + return + + end + +c======================= The end of errclb ============================= + + subroutine formk(n, nsub, ind, nenter, ileave, indx2, iupdat, + + updatd, wn, wn1, m, ws, wy, sy, theta, col, + + head, info) + + integer n, nsub, m, col, head, nenter, ileave, iupdat, + + info, ind(n), indx2(n) + double precision theta, wn(2*m, 2*m), wn1(2*m, 2*m), + + ws(n, m), wy(n, m), sy(m, m) + logical updatd + +c ************ +c +c Subroutine formk +c +c This subroutine forms the LEL^T factorization of the indefinite +c +c matrix K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] +c [L_a -R_z theta*S'AA'S ] +c where E = [-I 0] +c [ 0 I] +c The matrix K can be shown to be equal to the matrix M^[-1]N +c occurring in section 5.1 of [1], as well as to the matrix +c Mbar^[-1] Nbar in section 5.3. +c +c n is an integer variable. +c On entry n is the dimension of the problem. +c On exit n is unchanged. +c +c nsub is an integer variable +c On entry nsub is the number of subspace variables in free set. +c On exit nsub is not changed. +c +c ind is an integer array of dimension nsub. +c On entry ind specifies the indices of subspace variables. +c On exit ind is unchanged. +c +c nenter is an integer variable. +c On entry nenter is the number of variables entering the +c free set. +c On exit nenter is unchanged. +c +c ileave is an integer variable. +c On entry indx2(ileave),...,indx2(n) are the variables leaving +c the free set. +c On exit ileave is unchanged. +c +c indx2 is an integer array of dimension n. +c On entry indx2(1),...,indx2(nenter) are the variables entering +c the free set, while indx2(ileave),...,indx2(n) are the +c variables leaving the free set. +c On exit indx2 is unchanged. +c +c iupdat is an integer variable. +c On entry iupdat is the total number of BFGS updates made so far. +c On exit iupdat is unchanged. +c +c updatd is a logical variable. +c On entry 'updatd' is true if the L-BFGS matrix is updatd. +c On exit 'updatd' is unchanged. +c +c wn is a double precision array of dimension 2m x 2m. +c On entry wn is unspecified. +c On exit the upper triangle of wn stores the LEL^T factorization +c of the 2*col x 2*col indefinite matrix +c [-D -Y'ZZ'Y/theta L_a'-R_z' ] +c [L_a -R_z theta*S'AA'S ] +c +c wn1 is a double precision array of dimension 2m x 2m. +c On entry wn1 stores the lower triangular part of +c [Y' ZZ'Y L_a'+R_z'] +c [L_a+R_z S'AA'S ] +c in the previous iteration. +c On exit wn1 stores the corresponding updated matrices. +c The purpose of wn1 is just to store these inner products +c so they can be easily updated and inserted into wn. +c +c m is an integer variable. +c On entry m is the maximum number of variable metric corrections +c used to define the limited memory matrix. +c On exit m is unchanged. +c +c ws, wy, sy, and wtyy are double precision arrays; +c theta is a double precision variable; +c col is an integer variable; +c head is an integer variable. +c On entry they store the information defining the +c limited memory BFGS matrix: +c ws(n,m) stores S, a set of s-vectors; +c wy(n,m) stores Y, a set of y-vectors; +c sy(m,m) stores S'Y; +c wtyy(m,m) stores the Cholesky factorization +c of (theta*S'S+LD^(-1)L') +c theta is the scaling factor specifying B_0 = theta I; +c col is the number of variable metric corrections stored; +c head is the location of the 1st s- (or y-) vector in S (or Y). +c On exit they are unchanged. +c +c info is an integer variable. +c On entry info is unspecified. +c On exit info = 0 for normal return; +c = -1 when the 1st Cholesky factorization failed; +c = -2 when the 2st Cholesky factorization failed. +c +c Subprograms called: +c +c Linpack ... dcopy, dpofa, dtrsl. +c +c +c References: +c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited +c memory algorithm for bound constrained optimization'', +c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. +c +c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a +c limited memory FORTRAN code for solving bound constrained +c optimization problems'', Tech. Report, NAM-11, EECS Department, +c Northwestern University, 1994. +c +c (Postscript files of these papers are available via anonymous +c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer m2,ipntr,jpntr,iy,is,jy,js,is1,js1,k1,i,k, + + col2,pbegin,pend,dbegin,dend,upcl + double precision ddot,temp1,temp2,temp3,temp4 + double precision one,zero + parameter (one=1.0d0,zero=0.0d0) + +c Form the lower triangular part of +c WN1 = [Y' ZZ'Y L_a'+R_z'] +c [L_a+R_z S'AA'S ] +c where L_a is the strictly lower triangular part of S'AA'Y +c R_z is the upper triangular part of S'ZZ'Y. + + if (updatd) then + if (iupdat .gt. m) then +c shift old part of WN1. + do 10 jy = 1, m - 1 + js = m + jy + call dcopy(m-jy,wn1(jy+1,jy+1),1,wn1(jy,jy),1) + call dcopy(m-jy,wn1(js+1,js+1),1,wn1(js,js),1) + call dcopy(m-1,wn1(m+2,jy+1),1,wn1(m+1,jy),1) + 10 continue + endif + +c put new rows in blocks (1,1), (2,1) and (2,2). + pbegin = 1 + pend = nsub + dbegin = nsub + 1 + dend = n + iy = col + is = m + col + ipntr = head + col - 1 + if (ipntr .gt. m) ipntr = ipntr - m + jpntr = head + do 20 jy = 1, col + js = m + jy + temp1 = zero + temp2 = zero + temp3 = zero +c compute element jy of row 'col' of Y'ZZ'Y + do 15 k = pbegin, pend + k1 = ind(k) + temp1 = temp1 + wy(k1,ipntr)*wy(k1,jpntr) + 15 continue +c compute elements jy of row 'col' of L_a and S'AA'S + do 16 k = dbegin, dend + k1 = ind(k) + temp2 = temp2 + ws(k1,ipntr)*ws(k1,jpntr) + temp3 = temp3 + ws(k1,ipntr)*wy(k1,jpntr) + 16 continue + wn1(iy,jy) = temp1 + wn1(is,js) = temp2 + wn1(is,jy) = temp3 + jpntr = mod(jpntr,m) + 1 + 20 continue + +c put new column in block (2,1). + jy = col + jpntr = head + col - 1 + if (jpntr .gt. m) jpntr = jpntr - m + ipntr = head + do 30 i = 1, col + is = m + i + temp3 = zero +c compute element i of column 'col' of R_z + do 25 k = pbegin, pend + k1 = ind(k) + temp3 = temp3 + ws(k1,ipntr)*wy(k1,jpntr) + 25 continue + ipntr = mod(ipntr,m) + 1 + wn1(is,jy) = temp3 + 30 continue + upcl = col - 1 + else + upcl = col + endif + +c modify the old parts in blocks (1,1) and (2,2) due to changes +c in the set of free variables. + ipntr = head + do 45 iy = 1, upcl + is = m + iy + jpntr = head + do 40 jy = 1, iy + js = m + jy + temp1 = zero + temp2 = zero + temp3 = zero + temp4 = zero + do 35 k = 1, nenter + k1 = indx2(k) + temp1 = temp1 + wy(k1,ipntr)*wy(k1,jpntr) + temp2 = temp2 + ws(k1,ipntr)*ws(k1,jpntr) + 35 continue + do 36 k = ileave, n + k1 = indx2(k) + temp3 = temp3 + wy(k1,ipntr)*wy(k1,jpntr) + temp4 = temp4 + ws(k1,ipntr)*ws(k1,jpntr) + 36 continue + wn1(iy,jy) = wn1(iy,jy) + temp1 - temp3 + wn1(is,js) = wn1(is,js) - temp2 + temp4 + jpntr = mod(jpntr,m) + 1 + 40 continue + ipntr = mod(ipntr,m) + 1 + 45 continue + +c modify the old parts in block (2,1). + ipntr = head + do 60 is = m + 1, m + upcl + jpntr = head + do 55 jy = 1, upcl + temp1 = zero + temp3 = zero + do 50 k = 1, nenter + k1 = indx2(k) + temp1 = temp1 + ws(k1,ipntr)*wy(k1,jpntr) + 50 continue + do 51 k = ileave, n + k1 = indx2(k) + temp3 = temp3 + ws(k1,ipntr)*wy(k1,jpntr) + 51 continue + if (is .le. jy + m) then + wn1(is,jy) = wn1(is,jy) + temp1 - temp3 + else + wn1(is,jy) = wn1(is,jy) - temp1 + temp3 + endif + jpntr = mod(jpntr,m) + 1 + 55 continue + ipntr = mod(ipntr,m) + 1 + 60 continue + +c Form the upper triangle of WN = [D+Y' ZZ'Y/theta -L_a'+R_z' ] +c [-L_a +R_z S'AA'S*theta] + + m2 = 2*m + do 70 iy = 1, col + is = col + iy + is1 = m + iy + do 65 jy = 1, iy + js = col + jy + js1 = m + jy + wn(jy,iy) = wn1(iy,jy)/theta + wn(js,is) = wn1(is1,js1)*theta + 65 continue + do 66 jy = 1, iy - 1 + wn(jy,is) = -wn1(is1,jy) + 66 continue + do 67 jy = iy, col + wn(jy,is) = wn1(is1,jy) + 67 continue + wn(iy,iy) = wn(iy,iy) + sy(iy,iy) + 70 continue + +c Form the upper triangle of WN= [ LL' L^-1(-L_a'+R_z')] +c [(-L_a +R_z)L'^-1 S'AA'S*theta ] + +c first Cholesky factor (1,1) block of wn to get LL' +c with L' stored in the upper triangle of wn. + call dpofa(wn,m2,col,info) + if (info .ne. 0) then + info = -1 + return + endif +c then form L^-1(-L_a'+R_z') in the (1,2) block. + col2 = 2*col + do 71 js = col+1 ,col2 + call dtrsl(wn,m2,col,wn(1,js),11,info) + 71 continue + +c Form S'AA'S*theta + (L^-1(-L_a'+R_z'))'L^-1(-L_a'+R_z') in the +c upper triangle of (2,2) block of wn. + + + do 72 is = col+1, col2 + do 74 js = is, col2 + wn(is,js) = wn(is,js) + ddot(col,wn(1,is),1,wn(1,js),1) + 74 continue + 72 continue + +c Cholesky factorization of (2,2) block of wn. + + call dpofa(wn(col+1,col+1),m2,col,info) + if (info .ne. 0) then + info = -2 + return + endif + + return + + end + +c======================= The end of formk ============================== + + subroutine formt(m, wt, sy, ss, col, theta, info) + + integer m, col, info + double precision theta, wt(m, m), sy(m, m), ss(m, m) + +c ************ +c +c Subroutine formt +c +c This subroutine forms the upper half of the pos. def. and symm. +c T = theta*SS + L*D^(-1)*L', stores T in the upper triangle +c of the array wt, and performs the Cholesky factorization of T +c to produce J*J', with J' stored in the upper triangle of wt. +c +c Subprograms called: +c +c Linpack ... dpofa. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i,j,k,k1 + double precision ddum + double precision zero + parameter (zero=0.0d0) + + +c Form the upper half of T = theta*SS + L*D^(-1)*L', +c store T in the upper triangle of the array wt. + + do 52 j = 1, col + wt(1,j) = theta*ss(1,j) + 52 continue + do 55 i = 2, col + do 54 j = i, col + k1 = min(i,j) - 1 + ddum = zero + do 53 k = 1, k1 + ddum = ddum + sy(i,k)*sy(j,k)/sy(k,k) + 53 continue + wt(i,j) = ddum + theta*ss(i,j) + 54 continue + 55 continue + +c Cholesky factorize T to J*J' with +c J' stored in the upper triangle of wt. + + call dpofa(wt,m,col,info) + if (info .ne. 0) then + info = -3 + endif + + return + + end + +c======================= The end of formt ============================== + + subroutine freev(n, nfree, index, nenter, ileave, indx2, + + iwhere, wrk, updatd, cnstnd, iprint, iter) + + integer n, nfree, nenter, ileave, iprint, iter, + + index(n), indx2(n), iwhere(n) + logical wrk, updatd, cnstnd + +c ************ +c +c Subroutine freev +c +c This subroutine counts the entering and leaving variables when +c iter > 0, and finds the index set of free and active variables +c at the GCP. +c +c cnstnd is a logical variable indicating whether bounds are present +c +c index is an integer array of dimension n +c for i=1,...,nfree, index(i) are the indices of free variables +c for i=nfree+1,...,n, index(i) are the indices of bound variables +c On entry after the first iteration, index gives +c the free variables at the previous iteration. +c On exit it gives the free variables based on the determination +c in cauchy using the array iwhere. +c +c indx2 is an integer array of dimension n +c On entry indx2 is unspecified. +c On exit with iter>0, indx2 indicates which variables +c have changed status since the previous iteration. +c For i= 1,...,nenter, indx2(i) have changed from bound to free. +c For i= ileave+1,...,n, indx2(i) have changed from free to bound. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer iact,i,k + + nenter = 0 + ileave = n + 1 + if (iter .gt. 0 .and. cnstnd) then +c count the entering and leaving variables. + do 20 i = 1, nfree + k = index(i) + if (iwhere(k) .gt. 0) then + ileave = ileave - 1 + indx2(ileave) = k + if (iprint .ge. 100) write (6,*) + + 'Variable ',k,' leaves the set of free variables' + endif + 20 continue + do 22 i = 1 + nfree, n + k = index(i) + if (iwhere(k) .le. 0) then + nenter = nenter + 1 + indx2(nenter) = k + if (iprint .ge. 100) write (6,*) + + 'Variable ',k,' enters the set of free variables' + endif + 22 continue + if (iprint .ge. 99) write (6,*) + + n+1-ileave,' variables leave; ',nenter,' variables enter' + endif + wrk = (ileave .lt. n+1) .or. (nenter .gt. 0) .or. updatd + +c Find the index set of free and active variables at the GCP. + + nfree = 0 + iact = n + 1 + do 24 i = 1, n + if (iwhere(i) .le. 0) then + nfree = nfree + 1 + index(nfree) = i + else + iact = iact - 1 + index(iact) = i + endif + 24 continue + if (iprint .ge. 99) write (6,*) + + nfree,' variables are free at GCP ',iter + 1 + + return + + end + +c======================= The end of freev ============================== + + subroutine hpsolb(n, t, iorder, iheap) + integer iheap, n, iorder(n) + double precision t(n) + +c ************ +c +c Subroutine hpsolb +c +c This subroutine sorts out the least element of t, and puts the +c remaining elements of t in a heap. +c +c n is an integer variable. +c On entry n is the dimension of the arrays t and iorder. +c On exit n is unchanged. +c +c t is a double precision array of dimension n. +c On entry t stores the elements to be sorted, +c On exit t(n) stores the least elements of t, and t(1) to t(n-1) +c stores the remaining elements in the form of a heap. +c +c iorder is an integer array of dimension n. +c On entry iorder(i) is the index of t(i). +c On exit iorder(i) is still the index of t(i), but iorder may be +c permuted in accordance with t. +c +c iheap is an integer variable specifying the task. +c On entry iheap should be set as follows: +c iheap .eq. 0 if t(1) to t(n) is not in the form of a heap, +c iheap .ne. 0 if otherwise. +c On exit iheap is unchanged. +c +c +c References: +c Algorithm 232 of CACM (J. W. J. Williams): HEAPSORT. +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c ************ + + integer i,j,k,indxin,indxou + double precision ddum,out + + if (iheap .eq. 0) then + +c Rearrange the elements t(1) to t(n) to form a heap. + + do 20 k = 2, n + ddum = t(k) + indxin = iorder(k) + +c Add ddum to the heap. + i = k + 10 continue + if (i.gt.1) then + j = i/2 + if (ddum .lt. t(j)) then + t(i) = t(j) + iorder(i) = iorder(j) + i = j + goto 10 + endif + endif + t(i) = ddum + iorder(i) = indxin + 20 continue + endif + +c Assign to 'out' the value of t(1), the least member of the heap, +c and rearrange the remaining members to form a heap as +c elements 1 to n-1 of t. + + if (n .gt. 1) then + i = 1 + out = t(1) + indxou = iorder(1) + ddum = t(n) + indxin = iorder(n) + +c Restore the heap + 30 continue + j = i+i + if (j .le. n-1) then + if (t(j+1) .lt. t(j)) j = j+1 + if (t(j) .lt. ddum ) then + t(i) = t(j) + iorder(i) = iorder(j) + i = j + goto 30 + endif + endif + t(i) = ddum + iorder(i) = indxin + +c Put the least member in t(n). + + t(n) = out + iorder(n) = indxou + endif + + return + + end + +c====================== The end of hpsolb ============================== + + subroutine lnsrlb(n, l, u, nbd, x, f, fold, gd, gdold, g, d, r, t, + + z, stp, dnorm, dtd, xstep, stpmx, iter, ifun, + + iback, nfgv, info, task, boxed, cnstnd, csave, + + isave, dsave) + + character*60 task, csave + logical boxed, cnstnd + integer n, iter, ifun, iback, nfgv, info, + + nbd(n), isave(2) + double precision f, fold, gd, gdold, stp, dnorm, dtd, xstep, + + stpmx, x(n), l(n), u(n), g(n), d(n), r(n), t(n), + + z(n), dsave(13) +c ********** +c +c Subroutine lnsrlb +c +c This subroutine calls subroutine dcsrch from the Minpack2 library +c to perform the line search. Subroutine dscrch is safeguarded so +c that all trial points lie within the feasible region. +c +c Subprograms called: +c +c Minpack2 Library ... dcsrch. +c +c Linpack ... dtrsl, ddot. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ********** + + integer i + double precision ddot,a1,a2 + double precision one,zero,big + parameter (one=1.0d0,zero=0.0d0,big=1.0d+10) + double precision ftol,gtol,xtol + parameter (ftol=1.0d-3,gtol=0.9d0,xtol=0.1d0) + + if (task(1:5) .eq. 'FG_LN') goto 556 + + dtd = ddot(n,d,1,d,1) + dnorm = sqrt(dtd) + +c Determine the maximum step length. + + stpmx = big + if (cnstnd) then + if (iter .eq. 0) then + stpmx = one + else + do 43 i = 1, n + a1 = d(i) + if (nbd(i) .ne. 0) then + if (a1 .lt. zero .and. nbd(i) .le. 2) then + a2 = l(i) - x(i) + if (a2 .ge. zero) then + stpmx = zero + else if (a1*stpmx .lt. a2) then + stpmx = a2/a1 + endif + else if (a1 .gt. zero .and. nbd(i) .ge. 2) then + a2 = u(i) - x(i) + if (a2 .le. zero) then + stpmx = zero + else if (a1*stpmx .gt. a2) then + stpmx = a2/a1 + endif + endif + endif + 43 continue + endif + endif + + if (iter .eq. 0 .and. .not. boxed) then + stp = min(one/dnorm, stpmx) + else + stp = one + endif + + call dcopy(n,x,1,t,1) + call dcopy(n,g,1,r,1) + fold = f + ifun = 0 + iback = 0 + csave = 'START' + 556 continue + gd = ddot(n,g,1,d,1) + if (ifun .eq. 0) then + gdold=gd + if (gd .ge. zero) then +c the directional derivative >=0. +c Line search is impossible. + write(6,*)' ascent direction in projection gd = ', gd + info = -4 + return + endif + endif + + call dcsrch(f,gd,stp,ftol,gtol,xtol,zero,stpmx,csave,isave,dsave) + + xstep = stp*dnorm + if (csave(1:4) .ne. 'CONV' .and. csave(1:4) .ne. 'WARN') then + task = 'FG_LNSRCH' + ifun = ifun + 1 + nfgv = nfgv + 1 + iback = ifun - 1 + if (stp .eq. one) then + call dcopy(n,z,1,x,1) + else + do 41 i = 1, n + x(i) = stp*d(i) + t(i) + 41 continue + endif + else + task = 'NEW_X' + endif + + return + + end + +c======================= The end of lnsrlb ============================= + + subroutine matupd(n, m, ws, wy, sy, ss, d, r, itail, + + iupdat, col, head, theta, rr, dr, stp, dtd) + + integer n, m, itail, iupdat, col, head + double precision theta, rr, dr, stp, dtd, d(n), r(n), + + ws(n, m), wy(n, m), sy(m, m), ss(m, m) + +c ************ +c +c Subroutine matupd +c +c This subroutine updates matrices WS and WY, and forms the +c middle matrix in B. +c +c Subprograms called: +c +c Linpack ... dcopy, ddot. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer j,pointr + double precision ddot + double precision one + parameter (one=1.0d0) + +c Set pointers for matrices WS and WY. + + if (iupdat .le. m) then + col = iupdat + itail = mod(head+iupdat-2,m) + 1 + else + itail = mod(itail,m) + 1 + head = mod(head,m) + 1 + endif + +c Update matrices WS and WY. + + call dcopy(n,d,1,ws(1,itail),1) + call dcopy(n,r,1,wy(1,itail),1) + +c Set theta=yy/ys. + + theta = rr/dr + +c Form the middle matrix in B. + +c update the upper triangle of SS, +c and the lower triangle of SY: + if (iupdat .gt. m) then +c move old information + do 50 j = 1, col - 1 + call dcopy(j,ss(2,j+1),1,ss(1,j),1) + call dcopy(col-j,sy(j+1,j+1),1,sy(j,j),1) + 50 continue + endif +c add new information: the last row of SY +c and the last column of SS: + pointr = head + do 51 j = 1, col - 1 + sy(col,j) = ddot(n,d,1,wy(1,pointr),1) + ss(j,col) = ddot(n,ws(1,pointr),1,d,1) + pointr = mod(pointr,m) + 1 + 51 continue + if (stp .eq. one) then + ss(col,col) = dtd + else + ss(col,col) = stp*stp*dtd + endif + sy(col,col) = dr + + return + + end + +c======================= The end of matupd ============================= + + subroutine prn1lb(n, m, l, u, x, iprint, itfile, epsmch) + + integer n, m, iprint, itfile + double precision epsmch, x(n), l(n), u(n) + +c ************ +c +c Subroutine prn1lb +c +c This subroutine prints the input data, initial point, upper and +c lower bounds of each variable, machine precision, as well as +c the headings of the output. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i + + if (iprint .ge. 0) then + write (6,7001) epsmch + write (6,*) 'N = ',n,' M = ',m + if (iprint .ge. 1) then + write (itfile,2001) epsmch + write (itfile,*)'N = ',n,' M = ',m + write (itfile,9001) + if (iprint .gt. 100) then + write (6,1004) 'L =',(l(i),i = 1,n) + write (6,1004) 'X0 =',(x(i),i = 1,n) + write (6,1004) 'U =',(u(i),i = 1,n) + endif + endif + endif + + 1004 format (/,a4, 1p, 6(1x,d11.4),/,(4x,1p,6(1x,d11.4))) + 2001 format ('RUNNING THE L-BFGS-B CODE',/,/, + + 'it = iteration number',/, + + 'nf = number of function evaluations',/, + + 'nint = number of segments explored during the Cauchy search',/, + + 'nact = number of active bounds at the generalized Cauchy point' + + ,/, + + 'sub = manner in which the subspace minimization terminated:' + + ,/,' con = converged, bnd = a bound was reached',/, + + 'itls = number of iterations performed in the line search',/, + + 'stepl = step length used',/, + + 'tstep = norm of the displacement (total step)',/, + + 'projg = norm of the projected gradient',/, + + 'f = function value',/,/, + + ' * * *',/,/, + + 'Machine precision =',1p,d10.3) + 7001 format ('RUNNING THE L-BFGS-B CODE',/,/, + + ' * * *',/,/, + + 'Machine precision =',1p,d10.3) + 9001 format (/,3x,'it',3x,'nf',2x,'nint',2x,'nact',2x,'sub',2x,'itls', + + 2x,'stepl',4x,'tstep',5x,'projg',8x,'f') + + return + + end + +c======================= The end of prn1lb ============================= + + subroutine prn2lb(n, x, f, g, iprint, itfile, iter, nfgv, nact, + + sbgnrm, nint, word, iword, iback, stp, xstep) + + character*3 word + integer n, iprint, itfile, iter, nfgv, nact, nint, + + iword, iback + double precision f, sbgnrm, stp, xstep, x(n), g(n) + +c ************ +c +c Subroutine prn2lb +c +c This subroutine prints out new information after a successful +c line search. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i,imod + +c 'word' records the status of subspace solutions. + if (iword .eq. 0) then +c the subspace minimization converged. + word = 'con' + else if (iword .eq. 1) then +c the subspace minimization stopped at a bound. + word = 'bnd' + else if (iword .eq. 5) then +c the truncated Newton step has been used. + word = 'TNT' + else + word = '---' + endif + if (iprint .ge. 99) then + write (6,*) 'LINE SEARCH',iback,' times; norm of step = ',xstep + write (6,2001) iter,f,sbgnrm + if (iprint .gt. 100) then + write (6,1004) 'X =',(x(i), i = 1, n) + write (6,1004) 'G =',(g(i), i = 1, n) + endif + else if (iprint .gt. 0) then + imod = mod(iter,iprint) + if (imod .eq. 0) write (6,2001) iter,f,sbgnrm + endif + if (iprint .ge. 1) write (itfile,3001) + + iter,nfgv,nint,nact,word,iback,stp,xstep,sbgnrm,f + + 1004 format (/,a4, 1p, 6(1x,d11.4),/,(4x,1p,6(1x,d11.4))) + 2001 format + + (/,'At iterate',i5,4x,'f= ',1p,d12.5,4x,'|proj g|= ',1p,d12.5) + 3001 format(2(1x,i4),2(1x,i5),2x,a3,1x,i4,1p,2(2x,d8.1),1p,2(1x,d10.3)) + + return + + end + +c======================= The end of prn2lb ============================= + + subroutine prn3lb(n, x, f, task, iprint, info, itfile, + + iter, nfgv, nintol, nskip, nact, sbgnrm, + + time, nint, word, iback, stp, xstep, k, + + cachyt, sbtime, lnscht) + + character*60 task + character*3 word + integer n, iprint, info, itfile, iter, nfgv, nintol, + + nskip, nact, nint, iback, k + double precision f, sbgnrm, time, stp, xstep, cachyt, sbtime, + + lnscht, x(n) + +c ************ +c +c Subroutine prn3lb +c +c This subroutine prints out information when either a built-in +c convergence test is satisfied or when an error message is +c generated. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i + + if (task(1:5) .eq. 'ERROR') goto 999 + + if (iprint .ge. 0) then + write (6,3003) + write (6,3004) + write(6,3005) n,iter,nfgv,nintol,nskip,nact,sbgnrm,f + if (iprint .ge. 100) then + write (6,1004) 'X =',(x(i),i = 1,n) + endif + if (iprint .ge. 1) write (6,*) ' F =',f + endif + 999 continue + if (iprint .ge. 0) then + write (6,3009) task + if (info .ne. 0) then + if (info .eq. -1) write (6,9011) + if (info .eq. -2) write (6,9012) + if (info .eq. -3) write (6,9013) + if (info .eq. -4) write (6,9014) + if (info .eq. -5) write (6,9015) + if (info .eq. -6) write (6,*)' Input nbd(',k,') is invalid.' + if (info .eq. -7) + + write (6,*)' l(',k,') > u(',k,'). No feasible solution.' + if (info .eq. -8) write (6,9018) + if (info .eq. -9) write (6,9019) + endif + if (iprint .ge. 1) write (6,3007) cachyt,sbtime,lnscht + write (6,3008) time + if (iprint .ge. 1) then + if (info .eq. -4 .or. info .eq. -9) then + write (itfile,3002) + + iter,nfgv,nint,nact,word,iback,stp,xstep + endif + write (itfile,3009) task + if (info .ne. 0) then + if (info .eq. -1) write (itfile,9011) + if (info .eq. -2) write (itfile,9012) + if (info .eq. -3) write (itfile,9013) + if (info .eq. -4) write (itfile,9014) + if (info .eq. -5) write (itfile,9015) + if (info .eq. -8) write (itfile,9018) + if (info .eq. -9) write (itfile,9019) + endif + write (itfile,3008) time + endif + endif + + 1004 format (/,a4, 1p, 6(1x,d11.4),/,(4x,1p,6(1x,d11.4))) + 3002 format(2(1x,i4),2(1x,i5),2x,a3,1x,i4,1p,2(2x,d8.1),6x,'-',10x,'-') + 3003 format (/, + + ' * * *',/,/, + + 'Tit = total number of iterations',/, + + 'Tnf = total number of function evaluations',/, + + 'Tnint = total number of segments explored during', + + ' Cauchy searches',/, + + 'Skip = number of BFGS updates skipped',/, + + 'Nact = number of active bounds at final generalized', + + ' Cauchy point',/, + + 'Projg = norm of the final projected gradient',/, + + 'F = final function value',/,/, + + ' * * *') + 3004 format (/,3x,'N',4x,'Tit',5x,'Tnf',2x,'Tnint',2x, + + 'Skip',2x,'Nact',5x,'Projg',8x,'F') + 3005 format (i5,2(1x,i6),(1x,i6),(2x,i4),(1x,i5),1p,2(2x,d10.3)) + 3006 format (i5,2(1x,i4),2(1x,i6),(1x,i4),(1x,i5),7x,'-',10x,'-') + 3007 format (/,' Cauchy time',1p,e10.3,' seconds.',/ + + ' Subspace minimization time',1p,e10.3,' seconds.',/ + + ' Line search time',1p,e10.3,' seconds.') + 3008 format (/,' Total User time',1p,e10.3,' seconds.',/) + 3009 format (/,a60) + 9011 format (/, + +' Matrix in 1st Cholesky factorization in formk is not Pos. Def.') + 9012 format (/, + +' Matrix in 2st Cholesky factorization in formk is not Pos. Def.') + 9013 format (/, + +' Matrix in the Cholesky factorization in formt is not Pos. Def.') + 9014 format (/, + +' Derivative >= 0, backtracking line search impossible.',/, + +' Previous x, f and g restored.',/, + +' Possible causes: 1 error in function or gradient evaluation;',/, + +' 2 rounding errors dominate computation.') + 9015 format (/, + +' Warning: more than 10 function and gradient',/, + +' evaluations in the last line search. Termination',/, + +' may possibly be caused by a bad search direction.') + 9018 format (/,' The triangular system is singular.') + 9019 format (/, + +' Line search cannot locate an adequate point after 20 function',/ + +,' and gradient evaluations. Previous x, f and g restored.',/, + +' Possible causes: 1 error in function or gradient evaluation;',/, + +' 2 rounding error dominate computation.') + + return + + end + +c======================= The end of prn3lb ============================= + + subroutine projgr(n, l, u, nbd, x, g, sbgnrm) + + integer n, nbd(n) + double precision sbgnrm, x(n), l(n), u(n), g(n) + +c ************ +c +c Subroutine projgr +c +c This subroutine computes the infinity norm of the projected +c gradient. +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer i + double precision gi + double precision one,zero + parameter (one=1.0d0,zero=0.0d0) + + sbgnrm = zero + do 15 i = 1, n + gi = g(i) + if (nbd(i) .ne. 0) then + if (gi .lt. zero) then + if (nbd(i) .ge. 2) gi = max((x(i)-u(i)),gi) + else + if (nbd(i) .le. 2) gi = min((x(i)-l(i)),gi) + endif + endif + sbgnrm = max(sbgnrm,abs(gi)) + 15 continue + + return + + end + +c======================= The end of projgr ============================= + + subroutine subsm ( n, m, nsub, ind, l, u, nbd, x, d, xp, ws, wy, + + sy, wt, theta, xx, gg, + + col, head, iword, wv, wn, iprint, info ) + + integer n, m, nsub, col, head, iword, iprint, info, + + ind(nsub), nbd(n) + double precision theta, + + l(n), u(n), x(n), d(n), xp(n), xx(n), gg(n), + + ws(n, m), wy(n, m), sy(m,m), wt(m,m), + + wv(2*m), wn(2*m, 2*m) + +c ********************************************************************** +c +c This routine contains the major changes in the updated version. +c The changes are described in the accompanying paper +c +c Jose Luis Morales, Jorge Nocedal +c "Remark On Algorithm 78: L-BFGS-B: Fortran Subroutines for Large-Scale +c Bound Constrained Optimization". Decemmber 27, 2010. +c +c J.L. Morales Departamento de Matematicas, +c Instituto Tecnologico Autonomo de Mexico +c Mexico D.F. +c +c J, Nocedal Department of Electrical Engineering and +c Computer Science. +c Northwestern University. Evanston, IL. USA +c +c January 17, 2011 +c +c ********************************************************************** +c +c +c Subroutine subsm +c +c Given xcp, l, u, r, an index set that specifies +c the active set at xcp, and an l-BFGS matrix B +c (in terms of WY, WS, SY, WT, head, col, and theta), +c this subroutine computes an approximate solution +c of the subspace problem +c +c (P) min Q(x) = r'(x-xcp) + 1/2 (x-xcp)' B (x-xcp) +c +c subject to l<=x<=u +c x_i=xcp_i for all i in A(xcp) +c +c along the subspace unconstrained Newton direction +c +c d = -(Z'BZ)^(-1) r. +c +c The formula for the Newton direction, given the L-BFGS matrix +c and the Sherman-Morrison formula, is +c +c d = (1/theta)r + (1/theta*2) Z'WK^(-1)W'Z r. +c +c where +c K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] +c [L_a -R_z theta*S'AA'S ] +c +c Note that this procedure for computing d differs +c from that described in [1]. One can show that the matrix K is +c equal to the matrix M^[-1]N in that paper. +c +c n is an integer variable. +c On entry n is the dimension of the problem. +c On exit n is unchanged. +c +c m is an integer variable. +c On entry m is the maximum number of variable metric corrections +c used to define the limited memory matrix. +c On exit m is unchanged. +c +c nsub is an integer variable. +c On entry nsub is the number of free variables. +c On exit nsub is unchanged. +c +c ind is an integer array of dimension nsub. +c On entry ind specifies the coordinate indices of free variables. +c On exit ind is unchanged. +c +c l is a double precision array of dimension n. +c On entry l is the lower bound of x. +c On exit l is unchanged. +c +c u is a double precision array of dimension n. +c On entry u is the upper bound of x. +c On exit u is unchanged. +c +c nbd is a integer array of dimension n. +c On entry nbd represents the type of bounds imposed on the +c variables, and must be specified as follows: +c nbd(i)=0 if x(i) is unbounded, +c 1 if x(i) has only a lower bound, +c 2 if x(i) has both lower and upper bounds, and +c 3 if x(i) has only an upper bound. +c On exit nbd is unchanged. +c +c x is a double precision array of dimension n. +c On entry x specifies the Cauchy point xcp. +c On exit x(i) is the minimizer of Q over the subspace of +c free variables. +c +c d is a double precision array of dimension n. +c On entry d is the reduced gradient of Q at xcp. +c On exit d is the Newton direction of Q. +c +c xp is a double precision array of dimension n. +c used to safeguard the projected Newton direction +c +c xx is a double precision array of dimension n +c On entry it holds the current iterate +c On output it is unchanged + +c gg is a double precision array of dimension n +c On entry it holds the gradient at the current iterate +c On output it is unchanged +c +c ws and wy are double precision arrays; +c theta is a double precision variable; +c col is an integer variable; +c head is an integer variable. +c On entry they store the information defining the +c limited memory BFGS matrix: +c ws(n,m) stores S, a set of s-vectors; +c wy(n,m) stores Y, a set of y-vectors; +c theta is the scaling factor specifying B_0 = theta I; +c col is the number of variable metric corrections stored; +c head is the location of the 1st s- (or y-) vector in S (or Y). +c On exit they are unchanged. +c +c iword is an integer variable. +c On entry iword is unspecified. +c On exit iword specifies the status of the subspace solution. +c iword = 0 if the solution is in the box, +c 1 if some bound is encountered. +c +c wv is a double precision working array of dimension 2m. +c +c wn is a double precision array of dimension 2m x 2m. +c On entry the upper triangle of wn stores the LEL^T factorization +c of the indefinite matrix +c +c K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] +c [L_a -R_z theta*S'AA'S ] +c where E = [-I 0] +c [ 0 I] +c On exit wn is unchanged. +c +c iprint is an INTEGER variable that must be set by the user. +c It controls the frequency and type of output generated: +c iprint<0 no output is generated; +c iprint=0 print only one line at the last iteration; +c 0100 print details of every iteration including x and g; +c When iprint > 0, the file iterate.dat will be created to +c summarize the iteration. +c +c info is an integer variable. +c On entry info is unspecified. +c On exit info = 0 for normal return, +c = nonzero for abnormal return +c when the matrix K is ill-conditioned. +c +c Subprograms called: +c +c Linpack dtrsl. +c +c +c References: +c +c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited +c memory algorithm for bound constrained optimization'', +c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. +c +c +c +c * * * +c +c NEOS, November 1994. (Latest revision June 1996.) +c Optimization Technology Center. +c Argonne National Laboratory and Northwestern University. +c Written by +c Ciyou Zhu +c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. +c +c +c ************ + + integer pointr,m2,col2,ibd,jy,js,i,j,k + double precision alpha, xk, dk, temp1, temp2 + double precision one,zero + parameter (one=1.0d0,zero=0.0d0) +c + double precision dd_p + + if (nsub .le. 0) return + if (iprint .ge. 99) write (6,1001) + +c Compute wv = W'Zd. + + pointr = head + do 20 i = 1, col + temp1 = zero + temp2 = zero + do 10 j = 1, nsub + k = ind(j) + temp1 = temp1 + wy(k,pointr)*d(j) + temp2 = temp2 + ws(k,pointr)*d(j) + 10 continue + wv(i) = temp1 + wv(col + i) = theta*temp2 + pointr = mod(pointr,m) + 1 + 20 continue + +c Compute wv:=K^(-1)wv. + + m2 = 2*m + col2 = 2*col + call dtrsl(wn,m2,col2,wv,11,info) + if (info .ne. 0) return + do 25 i = 1, col + wv(i) = -wv(i) + 25 continue + call dtrsl(wn,m2,col2,wv,01,info) + if (info .ne. 0) return + +c Compute d = (1/theta)d + (1/theta**2)Z'W wv. + + pointr = head + do 40 jy = 1, col + js = col + jy + do 30 i = 1, nsub + k = ind(i) + d(i) = d(i) + wy(k,pointr)*wv(jy)/theta + + + ws(k,pointr)*wv(js) + 30 continue + pointr = mod(pointr,m) + 1 + 40 continue + + call dscal( nsub, one/theta, d, 1 ) +c +c----------------------------------------------------------------- +c Let us try the projection, d is the Newton direction + + iword = 0 + + call dcopy ( n, x, 1, xp, 1 ) +c + do 50 i=1, nsub + k = ind(i) + dk = d(i) + xk = x(k) + if ( nbd(k) .ne. 0 ) then +c + if ( nbd(k).eq.1 ) then ! lower bounds only + x(k) = max( l(k), xk + dk ) + if ( x(k).eq.l(k) ) iword = 1 + else +c + if ( nbd(k).eq.2 ) then ! upper and lower bounds + xk = max( l(k), xk + dk ) + x(k) = min( u(k), xk ) + if ( x(k).eq.l(k) .or. x(k).eq.u(k) ) iword = 1 + else +c + if ( nbd(k).eq.3 ) then ! upper bounds only + x(k) = min( u(k), xk + dk ) + if ( x(k).eq.u(k) ) iword = 1 + end if + end if + end if +c + else ! free variables + x(k) = xk + dk + end if + 50 continue +c + if ( iword.eq.0 ) then + go to 911 + end if +c +c check sign of the directional derivative +c + dd_p = zero + do 55 i=1, n + dd_p = dd_p + (x(i) - xx(i))*gg(i) + 55 continue + if ( dd_p .gt.zero ) then + call dcopy( n, xp, 1, x, 1 ) + write(6,*) ' Positive directional derivative ' + else + go to 911 + endif +c +c----------------------------------------------------------------- +c + alpha = one + temp1 = alpha + ibd = 0 + do 60 i = 1, nsub + k = ind(i) + dk = d(i) + if (nbd(k) .ne. 0) then + if (dk .lt. zero .and. nbd(k) .le. 2) then + temp2 = l(k) - x(k) + if (temp2 .ge. zero) then + temp1 = zero + else if (dk*alpha .lt. temp2) then + temp1 = temp2/dk + endif + else if (dk .gt. zero .and. nbd(k) .ge. 2) then + temp2 = u(k) - x(k) + if (temp2 .le. zero) then + temp1 = zero + else if (dk*alpha .gt. temp2) then + temp1 = temp2/dk + endif + endif + if (temp1 .lt. alpha) then + alpha = temp1 + ibd = i + endif + endif + 60 continue + + if (alpha .lt. one) then + dk = d(ibd) + k = ind(ibd) + if (dk .gt. zero) then + x(k) = u(k) + d(ibd) = zero + else if (dk .lt. zero) then + x(k) = l(k) + d(ibd) = zero + endif + endif + do 70 i = 1, nsub + k = ind(i) + x(k) = x(k) + alpha*d(i) + 70 continue +cccccc + 911 continue + + if (iprint .ge. 99) write (6,1004) + + 1001 format (/,'----------------SUBSM entered-----------------',/) + 1002 format ( 'ALPHA = ',f8.5,' backtrack to the BOX') + 1003 format ('Subspace solution X = ',/,(4x,1p,6(1x,d11.4))) + 1004 format (/,'----------------exit SUBSM --------------------',/) + + return + + end +c====================== The end of subsm =============================== + + subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax, + + task,isave,dsave) + character*(*) task + integer isave(2) + double precision f,g,stp,ftol,gtol,xtol,stpmin,stpmax + double precision dsave(13) +c ********** +c +c Subroutine dcsrch +c +c This subroutine finds a step that satisfies a sufficient +c decrease condition and a curvature condition. +c +c Each call of the subroutine updates an interval with +c endpoints stx and sty. The interval is initially chosen +c so that it contains a minimizer of the modified function +c +c psi(stp) = f(stp) - f(0) - ftol*stp*f'(0). +c +c If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the +c interval is chosen so that it contains a minimizer of f. +c +c The algorithm is designed to find a step that satisfies +c the sufficient decrease condition +c +c f(stp) <= f(0) + ftol*stp*f'(0), +c +c and the curvature condition +c +c abs(f'(stp)) <= gtol*abs(f'(0)). +c +c If ftol is less than gtol and if, for example, the function +c is bounded below, then there is always a step which satisfies +c both conditions. +c +c If no step can be found that satisfies both conditions, then +c the algorithm stops with a warning. In this case stp only +c satisfies the sufficient decrease condition. +c +c A typical invocation of dcsrch has the following outline: +c +c task = 'START' +c 10 continue +c call dcsrch( ... ) +c if (task .eq. 'FG') then +c Evaluate the function and the gradient at stp +c goto 10 +c end if +c +c NOTE: The user must no alter work arrays between calls. +c +c The subroutine statement is +c +c subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax, +c task,isave,dsave) +c where +c +c f is a double precision variable. +c On initial entry f is the value of the function at 0. +c On subsequent entries f is the value of the +c function at stp. +c On exit f is the value of the function at stp. +c +c g is a double precision variable. +c On initial entry g is the derivative of the function at 0. +c On subsequent entries g is the derivative of the +c function at stp. +c On exit g is the derivative of the function at stp. +c +c stp is a double precision variable. +c On entry stp is the current estimate of a satisfactory +c step. On initial entry, a positive initial estimate +c must be provided. +c On exit stp is the current estimate of a satisfactory step +c if task = 'FG'. If task = 'CONV' then stp satisfies +c the sufficient decrease and curvature condition. +c +c ftol is a double precision variable. +c On entry ftol specifies a nonnegative tolerance for the +c sufficient decrease condition. +c On exit ftol is unchanged. +c +c gtol is a double precision variable. +c On entry gtol specifies a nonnegative tolerance for the +c curvature condition. +c On exit gtol is unchanged. +c +c xtol is a double precision variable. +c On entry xtol specifies a nonnegative relative tolerance +c for an acceptable step. The subroutine exits with a +c warning if the relative difference between sty and stx +c is less than xtol. +c On exit xtol is unchanged. +c +c stpmin is a double precision variable. +c On entry stpmin is a nonnegative lower bound for the step. +c On exit stpmin is unchanged. +c +c stpmax is a double precision variable. +c On entry stpmax is a nonnegative upper bound for the step. +c On exit stpmax is unchanged. +c +c task is a character variable of length at least 60. +c On initial entry task must be set to 'START'. +c On exit task indicates the required action: +c +c If task(1:2) = 'FG' then evaluate the function and +c derivative at stp and call dcsrch again. +c +c If task(1:4) = 'CONV' then the search is successful. +c +c If task(1:4) = 'WARN' then the subroutine is not able +c to satisfy the convergence conditions. The exit value of +c stp contains the best point found during the search. +c +c If task(1:5) = 'ERROR' then there is an error in the +c input arguments. +c +c On exit with convergence, a warning or an error, the +c variable task contains additional information. +c +c isave is an integer work array of dimension 2. +c +c dsave is a double precision work array of dimension 13. +c +c Subprograms called +c +c MINPACK-2 ... dcstep +c +c MINPACK-1 Project. June 1983. +c Argonne National Laboratory. +c Jorge J. More' and David J. Thuente. +c +c MINPACK-2 Project. October 1993. +c Argonne National Laboratory and University of Minnesota. +c Brett M. Averick, Richard G. Carter, and Jorge J. More'. +c +c ********** + double precision zero,p5,p66 + parameter(zero=0.0d0,p5=0.5d0,p66=0.66d0) + double precision xtrapl,xtrapu + parameter(xtrapl=1.1d0,xtrapu=4.0d0) + + logical brackt + integer stage + double precision finit,ftest,fm,fx,fxm,fy,fym,ginit,gtest, + + gm,gx,gxm,gy,gym,stx,sty,stmin,stmax,width,width1 + +c Initialization block. + + if (task(1:5) .eq. 'START') then + +c Check the input arguments for errors. + + if (stp .lt. stpmin) task = 'ERROR: STP .LT. STPMIN' + if (stp .gt. stpmax) task = 'ERROR: STP .GT. STPMAX' + if (g .ge. zero) task = 'ERROR: INITIAL G .GE. ZERO' + if (ftol .lt. zero) task = 'ERROR: FTOL .LT. ZERO' + if (gtol .lt. zero) task = 'ERROR: GTOL .LT. ZERO' + if (xtol .lt. zero) task = 'ERROR: XTOL .LT. ZERO' + if (stpmin .lt. zero) task = 'ERROR: STPMIN .LT. ZERO' + if (stpmax .lt. stpmin) task = 'ERROR: STPMAX .LT. STPMIN' + +c Exit if there are errors on input. + + if (task(1:5) .eq. 'ERROR') return + +c Initialize local variables. + + brackt = .false. + stage = 1 + finit = f + ginit = g + gtest = ftol*ginit + width = stpmax - stpmin + width1 = width/p5 + +c The variables stx, fx, gx contain the values of the step, +c function, and derivative at the best step. +c The variables sty, fy, gy contain the value of the step, +c function, and derivative at sty. +c The variables stp, f, g contain the values of the step, +c function, and derivative at stp. + + stx = zero + fx = finit + gx = ginit + sty = zero + fy = finit + gy = ginit + stmin = zero + stmax = stp + xtrapu*stp + task = 'FG' + + goto 1000 + + else + +c Restore local variables. + + if (isave(1) .eq. 1) then + brackt = .true. + else + brackt = .false. + endif + stage = isave(2) + ginit = dsave(1) + gtest = dsave(2) + gx = dsave(3) + gy = dsave(4) + finit = dsave(5) + fx = dsave(6) + fy = dsave(7) + stx = dsave(8) + sty = dsave(9) + stmin = dsave(10) + stmax = dsave(11) + width = dsave(12) + width1 = dsave(13) + + endif + +c If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the +c algorithm enters the second stage. + + ftest = finit + stp*gtest + if (stage .eq. 1 .and. f .le. ftest .and. g .ge. zero) + + stage = 2 + +c Test for warnings. + + if (brackt .and. (stp .le. stmin .or. stp .ge. stmax)) + + task = 'WARNING: ROUNDING ERRORS PREVENT PROGRESS' + if (brackt .and. stmax - stmin .le. xtol*stmax) + + task = 'WARNING: XTOL TEST SATISFIED' + if (stp .eq. stpmax .and. f .le. ftest .and. g .le. gtest) + + task = 'WARNING: STP = STPMAX' + if (stp .eq. stpmin .and. (f .gt. ftest .or. g .ge. gtest)) + + task = 'WARNING: STP = STPMIN' + +c Test for convergence. + + if (f .le. ftest .and. abs(g) .le. gtol*(-ginit)) + + task = 'CONVERGENCE' + +c Test for termination. + + if (task(1:4) .eq. 'WARN' .or. task(1:4) .eq. 'CONV') goto 1000 + +c A modified function is used to predict the step during the +c first stage if a lower function value has been obtained but +c the decrease is not sufficient. + + if (stage .eq. 1 .and. f .le. fx .and. f .gt. ftest) then + +c Define the modified function and derivative values. + + fm = f - stp*gtest + fxm = fx - stx*gtest + fym = fy - sty*gtest + gm = g - gtest + gxm = gx - gtest + gym = gy - gtest + +c Call dcstep to update stx, sty, and to compute the new step. + + call dcstep(stx,fxm,gxm,sty,fym,gym,stp,fm,gm, + + brackt,stmin,stmax) + +c Reset the function and derivative values for f. + + fx = fxm + stx*gtest + fy = fym + sty*gtest + gx = gxm + gtest + gy = gym + gtest + + else + +c Call dcstep to update stx, sty, and to compute the new step. + + call dcstep(stx,fx,gx,sty,fy,gy,stp,f,g, + + brackt,stmin,stmax) + + endif + +c Decide if a bisection step is needed. + + if (brackt) then + if (abs(sty-stx) .ge. p66*width1) stp = stx + p5*(sty - stx) + width1 = width + width = abs(sty-stx) + endif + +c Set the minimum and maximum steps allowed for stp. + + if (brackt) then + stmin = min(stx,sty) + stmax = max(stx,sty) + else + stmin = stp + xtrapl*(stp - stx) + stmax = stp + xtrapu*(stp - stx) + endif + +c Force the step to be within the bounds stpmax and stpmin. + + stp = max(stp,stpmin) + stp = min(stp,stpmax) + +c If further progress is not possible, let stp be the best +c point obtained during the search. + + if (brackt .and. (stp .le. stmin .or. stp .ge. stmax) + + .or. (brackt .and. stmax-stmin .le. xtol*stmax)) stp = stx + +c Obtain another function and derivative. + + task = 'FG' + + 1000 continue + +c Save local variables. + + if (brackt) then + isave(1) = 1 + else + isave(1) = 0 + endif + isave(2) = stage + dsave(1) = ginit + dsave(2) = gtest + dsave(3) = gx + dsave(4) = gy + dsave(5) = finit + dsave(6) = fx + dsave(7) = fy + dsave(8) = stx + dsave(9) = sty + dsave(10) = stmin + dsave(11) = stmax + dsave(12) = width + dsave(13) = width1 + + end + +c====================== The end of dcsrch ============================== + + subroutine dcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt, + + stpmin,stpmax) + logical brackt + double precision stx,fx,dx,sty,fy,dy,stp,fp,dp,stpmin,stpmax +c ********** +c +c Subroutine dcstep +c +c This subroutine computes a safeguarded step for a search +c procedure and updates an interval that contains a step that +c satisfies a sufficient decrease and a curvature condition. +c +c The parameter stx contains the step with the least function +c value. If brackt is set to .true. then a minimizer has +c been bracketed in an interval with endpoints stx and sty. +c The parameter stp contains the current step. +c The subroutine assumes that if brackt is set to .true. then +c +c min(stx,sty) < stp < max(stx,sty), +c +c and that the derivative at stx is negative in the direction +c of the step. +c +c The subroutine statement is +c +c subroutine dcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt, +c stpmin,stpmax) +c +c where +c +c stx is a double precision variable. +c On entry stx is the best step obtained so far and is an +c endpoint of the interval that contains the minimizer. +c On exit stx is the updated best step. +c +c fx is a double precision variable. +c On entry fx is the function at stx. +c On exit fx is the function at stx. +c +c dx is a double precision variable. +c On entry dx is the derivative of the function at +c stx. The derivative must be negative in the direction of +c the step, that is, dx and stp - stx must have opposite +c signs. +c On exit dx is the derivative of the function at stx. +c +c sty is a double precision variable. +c On entry sty is the second endpoint of the interval that +c contains the minimizer. +c On exit sty is the updated endpoint of the interval that +c contains the minimizer. +c +c fy is a double precision variable. +c On entry fy is the function at sty. +c On exit fy is the function at sty. +c +c dy is a double precision variable. +c On entry dy is the derivative of the function at sty. +c On exit dy is the derivative of the function at the exit sty. +c +c stp is a double precision variable. +c On entry stp is the current step. If brackt is set to .true. +c then on input stp must be between stx and sty. +c On exit stp is a new trial step. +c +c fp is a double precision variable. +c On entry fp is the function at stp +c On exit fp is unchanged. +c +c dp is a double precision variable. +c On entry dp is the the derivative of the function at stp. +c On exit dp is unchanged. +c +c brackt is an logical variable. +c On entry brackt specifies if a minimizer has been bracketed. +c Initially brackt must be set to .false. +c On exit brackt specifies if a minimizer has been bracketed. +c When a minimizer is bracketed brackt is set to .true. +c +c stpmin is a double precision variable. +c On entry stpmin is a lower bound for the step. +c On exit stpmin is unchanged. +c +c stpmax is a double precision variable. +c On entry stpmax is an upper bound for the step. +c On exit stpmax is unchanged. +c +c MINPACK-1 Project. June 1983 +c Argonne National Laboratory. +c Jorge J. More' and David J. Thuente. +c +c MINPACK-2 Project. October 1993. +c Argonne National Laboratory and University of Minnesota. +c Brett M. Averick and Jorge J. More'. +c +c ********** + double precision zero,p66,two,three + parameter(zero=0.0d0,p66=0.66d0,two=2.0d0,three=3.0d0) + + double precision gamma,p,q,r,s,sgnd,stpc,stpf,stpq,theta + + sgnd = dp*(dx/abs(dx)) + +c First case: A higher function value. The minimum is bracketed. +c If the cubic step is closer to stx than the quadratic step, the +c cubic step is taken, otherwise the average of the cubic and +c quadratic steps is taken. + + if (fp .gt. fx) then + theta = three*(fx - fp)/(stp - stx) + dx + dp + s = max(abs(theta),abs(dx),abs(dp)) + gamma = s*sqrt((theta/s)**2 - (dx/s)*(dp/s)) + if (stp .lt. stx) gamma = -gamma + p = (gamma - dx) + theta + q = ((gamma - dx) + gamma) + dp + r = p/q + stpc = stx + r*(stp - stx) + stpq = stx + ((dx/((fx - fp)/(stp - stx) + dx))/two)* + + (stp - stx) + if (abs(stpc-stx) .lt. abs(stpq-stx)) then + stpf = stpc + else + stpf = stpc + (stpq - stpc)/two + endif + brackt = .true. + +c Second case: A lower function value and derivatives of opposite +c sign. The minimum is bracketed. If the cubic step is farther from +c stp than the secant step, the cubic step is taken, otherwise the +c secant step is taken. + + else if (sgnd .lt. zero) then + theta = three*(fx - fp)/(stp - stx) + dx + dp + s = max(abs(theta),abs(dx),abs(dp)) + gamma = s*sqrt((theta/s)**2 - (dx/s)*(dp/s)) + if (stp .gt. stx) gamma = -gamma + p = (gamma - dp) + theta + q = ((gamma - dp) + gamma) + dx + r = p/q + stpc = stp + r*(stx - stp) + stpq = stp + (dp/(dp - dx))*(stx - stp) + if (abs(stpc-stp) .gt. abs(stpq-stp)) then + stpf = stpc + else + stpf = stpq + endif + brackt = .true. + +c Third case: A lower function value, derivatives of the same sign, +c and the magnitude of the derivative decreases. + + else if (abs(dp) .lt. abs(dx)) then + +c The cubic step is computed only if the cubic tends to infinity +c in the direction of the step or if the minimum of the cubic +c is beyond stp. Otherwise the cubic step is defined to be the +c secant step. + + theta = three*(fx - fp)/(stp - stx) + dx + dp + s = max(abs(theta),abs(dx),abs(dp)) + +c The case gamma = 0 only arises if the cubic does not tend +c to infinity in the direction of the step. + + gamma = s*sqrt(max(zero,(theta/s)**2-(dx/s)*(dp/s))) + if (stp .gt. stx) gamma = -gamma + p = (gamma - dp) + theta + q = (gamma + (dx - dp)) + gamma + r = p/q + if (r .lt. zero .and. gamma .ne. zero) then + stpc = stp + r*(stx - stp) + else if (stp .gt. stx) then + stpc = stpmax + else + stpc = stpmin + endif + stpq = stp + (dp/(dp - dx))*(stx - stp) + + if (brackt) then + +c A minimizer has been bracketed. If the cubic step is +c closer to stp than the secant step, the cubic step is +c taken, otherwise the secant step is taken. + + if (abs(stpc-stp) .lt. abs(stpq-stp)) then + stpf = stpc + else + stpf = stpq + endif + if (stp .gt. stx) then + stpf = min(stp+p66*(sty-stp),stpf) + else + stpf = max(stp+p66*(sty-stp),stpf) + endif + else + +c A minimizer has not been bracketed. If the cubic step is +c farther from stp than the secant step, the cubic step is +c taken, otherwise the secant step is taken. + + if (abs(stpc-stp) .gt. abs(stpq-stp)) then + stpf = stpc + else + stpf = stpq + endif + stpf = min(stpmax,stpf) + stpf = max(stpmin,stpf) + endif + +c Fourth case: A lower function value, derivatives of the same sign, +c and the magnitude of the derivative does not decrease. If the +c minimum is not bracketed, the step is either stpmin or stpmax, +c otherwise the cubic step is taken. + + else + if (brackt) then + theta = three*(fp - fy)/(sty - stp) + dy + dp + s = max(abs(theta),abs(dy),abs(dp)) + gamma = s*sqrt((theta/s)**2 - (dy/s)*(dp/s)) + if (stp .gt. sty) gamma = -gamma + p = (gamma - dp) + theta + q = ((gamma - dp) + gamma) + dy + r = p/q + stpc = stp + r*(sty - stp) + stpf = stpc + else if (stp .gt. stx) then + stpf = stpmax + else + stpf = stpmin + endif + endif + +c Update the interval which contains a minimizer. + + if (fp .gt. fx) then + sty = stp + fy = fp + dy = dp + else + if (sgnd .lt. zero) then + sty = stx + fy = fx + dy = dx + endif + stx = stp + fx = fp + dx = dp + endif + +c Compute the new step. + + stp = stpf + + end + +c====================== The end of dcstep ============================== + + subroutine timer(ttime) + double precision ttime +c ********* +c +c Subroutine timer +c +c This subroutine is used to determine user time. In a typical +c application, the user time for a code segment requires calls +c to subroutine timer to determine the initial and final time. +c +c The subroutine statement is +c +c subroutine timer(ttime) +c +c where +c +c ttime is an output variable which specifies the user time. +c +c Argonne National Laboratory and University of Minnesota. +c MINPACK-2 Project. +c +c Modified October 1990 by Brett M. Averick. +c +c ********** + real temp + real tarray(2) + real etime + +c The first element of the array tarray specifies user time + + temp = etime(tarray) + + ttime = dble(tarray(1)) + + return + + end + +c====================== The end of timer =============================== + +c====================== The end of dnrm2 =============================== + + double precision function dpmeps() +c ********** +c +c Subroutine dpeps +c +c This subroutine computes the machine precision parameter +c dpmeps as the smallest floating point number such that +c 1 + dpmeps differs from 1. +c +c This subroutine is based on the subroutine machar described in +c +c W. J. Cody, +c MACHAR: A subroutine to dynamically determine machine parameters, +c ACM Transactions on Mathematical Software, 14, 1988, pages 303-311. +c +c The subroutine statement is: +c +c subroutine dpeps(dpmeps) +c +c where +c +c dpmeps is a double precision variable. +c On entry dpmeps need not be specified. +c On exit dpmeps is the machine precision. +c +c MINPACK-2 Project. February 1991. +c Argonne National Laboratory and University of Minnesota. +c Brett M. Averick. +c +c ******* + integer i,ibeta,irnd,it,itemp,negep + double precision a,b,beta,betain,betah,temp,tempa,temp1, + + zero,one,two + data zero,one,two /0.0d0,1.0d0,2.0d0/ + +c determine ibeta, beta ala malcolm. + + a = one + b = one + 10 continue + a = a + a + temp = a + one + temp1 = temp - a + if (temp1 - one .eq. zero) go to 10 + 20 continue + b = b + b + temp = a + b + itemp = int(temp - a) + if (itemp .eq. 0) go to 20 + ibeta = itemp + beta = dble(ibeta) + +c determine it, irnd. + + it = 0 + b = one + 30 continue + it = it + 1 + b = b * beta + temp = b + one + temp1 = temp - b + if (temp1 - one .eq. zero) go to 30 + irnd = 0 + betah = beta/two + temp = a + betah + if (temp - a .ne. zero) irnd = 1 + tempa = a + beta + temp = tempa + betah + if ((irnd .eq. 0) .and. (temp - tempa .ne. zero)) irnd = 2 + +c determine dpmeps. + + negep = it + 3 + betain = one/beta + a = one + do 40 i = 1, negep + a = a*betain + 40 continue + 50 continue + temp = one + a + if (temp - one .ne. zero) go to 60 + a = a*beta + go to 50 + 60 continue + dpmeps = a + if ((ibeta .eq. 2) .or. (irnd .eq. 0)) go to 70 + a = (a*(one + a))/two + temp = one + a + if (temp - one .ne. zero) dpmeps = a + + 70 return + + end + +c====================== The end of dpmeps ============================== + +c====================== The end of daxpy =============================== + + +c====================== The end of ddot ================================ + + subroutine dpofa(a,lda,n,info) + integer lda,n,info + double precision a(lda,1) +c +c dpofa factors a double precision symmetric positive definite +c matrix. +c +c dpofa is usually called by dpoco, but it can be called +c directly with a saving in time if rcond is not needed. +c (time for dpoco) = (1 + 18/n)*(time for dpofa) . +c +c on entry +c +c a double precision(lda, n) +c the symmetric matrix to be factored. only the +c diagonal and upper triangle are used. +c +c lda integer +c the leading dimension of the array a . +c +c n integer +c the order of the matrix a . +c +c on return +c +c a an upper triangular matrix r so that a = trans(r)*r +c where trans(r) is the transpose. +c the strict lower triangle is unaltered. +c if info .ne. 0 , the factorization is not complete. +c +c info integer +c = 0 for normal return. +c = k signals an error condition. the leading minor +c of order k is not positive definite. +c +c linpack. this version dated 08/14/78 . +c cleve moler, university of new mexico, argonne national lab. +c +c subroutines and functions +c +c blas ddot +c fortran sqrt +c +c internal variables +c + double precision ddot,t + double precision s + integer j,jm1,k +c begin block with ...exits to 40 +c +c + do 30 j = 1, n + info = j + s = 0.0d0 + jm1 = j - 1 + if (jm1 .lt. 1) go to 20 + do 10 k = 1, jm1 + t = a(k,j) - ddot(k-1,a(1,k),1,a(1,j),1) + t = t/a(k,k) + a(k,j) = t + s = s + t*t + 10 continue + 20 continue + s = a(j,j) - s +c ......exit + if (s .le. 0.0d0) go to 40 + a(j,j) = sqrt(s) + 30 continue + info = 0 + 40 continue + return + end + +c====================== The end of dpofa =============================== + + +c====================== The end of dscal =============================== + + subroutine dtrsl(t,ldt,n,b,job,info) + integer ldt,n,job,info + double precision t(ldt,1),b(1) +c +c +c dtrsl solves systems of the form +c +c t * x = b +c or +c trans(t) * x = b +c +c where t is a triangular matrix of order n. here trans(t) +c denotes the transpose of the matrix t. +c +c on entry +c +c t double precision(ldt,n) +c t contains the matrix of the system. the zero +c elements of the matrix are not referenced, and +c the corresponding elements of the array can be +c used to store other information. +c +c ldt integer +c ldt is the leading dimension of the array t. +c +c n integer +c n is the order of the system. +c +c b double precision(n). +c b contains the right hand side of the system. +c +c job integer +c job specifies what kind of system is to be solved. +c if job is +c +c 00 solve t*x=b, t lower triangular, +c 01 solve t*x=b, t upper triangular, +c 10 solve trans(t)*x=b, t lower triangular, +c 11 solve trans(t)*x=b, t upper triangular. +c +c on return +c +c b b contains the solution, if info .eq. 0. +c otherwise b is unaltered. +c +c info integer +c info contains zero if the system is nonsingular. +c otherwise info contains the index of +c the first zero diagonal element of t. +c +c linpack. this version dated 08/14/78 . +c g. w. stewart, university of maryland, argonne national lab. +c +c subroutines and functions +c +c blas daxpy,ddot +c fortran mod +c +c internal variables +c + double precision ddot,temp + integer case,j,jj +c +c begin block permitting ...exits to 150 +c +c check for zero diagonal elements. +c + do 10 info = 1, n +c ......exit + if (t(info,info) .eq. 0.0d0) go to 150 + 10 continue + info = 0 +c +c determine the task and go to it. +c + case = 1 + if (mod(job,10) .ne. 0) case = 2 + if (mod(job,100)/10 .ne. 0) case = case + 2 + go to (20,50,80,110), case +c +c solve t*x=b for t lower triangular +c + 20 continue + b(1) = b(1)/t(1,1) + if (n .lt. 2) go to 40 + do 30 j = 2, n + temp = -b(j-1) + call daxpy(n-j+1,temp,t(j,j-1),1,b(j),1) + b(j) = b(j)/t(j,j) + 30 continue + 40 continue + go to 140 +c +c solve t*x=b for t upper triangular. +c + 50 continue + b(n) = b(n)/t(n,n) + if (n .lt. 2) go to 70 + do 60 jj = 2, n + j = n - jj + 1 + temp = -b(j+1) + call daxpy(j,temp,t(1,j+1),1,b(1),1) + b(j) = b(j)/t(j,j) + 60 continue + 70 continue + go to 140 +c +c solve trans(t)*x=b for t lower triangular. +c + 80 continue + b(n) = b(n)/t(n,n) + if (n .lt. 2) go to 100 + do 90 jj = 2, n + j = n - jj + 1 + b(j) = b(j) - ddot(jj-1,t(j+1,j),1,b(j+1),1) + b(j) = b(j)/t(j,j) + 90 continue + 100 continue + go to 140 +c +c solve trans(t)*x=b for t upper triangular. +c + 110 continue + b(1) = b(1)/t(1,1) + if (n .lt. 2) go to 130 + do 120 j = 2, n + b(j) = b(j) - ddot(j-1,t(1,j),1,b(1),1) + b(j) = b(j)/t(j,j) + 120 continue + 130 continue + 140 continue + 150 continue + return + end + +c====================== The end of dtrsl =============================== + + diff --git a/dep/lbfgs/lbfgs_routines.h b/dep/lbfgs/lbfgs_routines.h new file mode 100644 index 00000000..d876b9ca --- /dev/null +++ b/dep/lbfgs/lbfgs_routines.h @@ -0,0 +1,24 @@ +#ifndef LBFGS_H_Seen +#define LBFGS_H_Seen + +#include "ftndefs.h" + +/* This is a C library, not C++ */ +#ifdef __cplusplus +extern "C" +{ +#endif +int lbfgsDR(int n, int m, double *x, int *nbd, double *l, double *u, + double (* func)(int, double *, void*), + void (* gradf)(int, double *, double *, void*), + void* userdata) ; +#ifdef __cplusplus +} +#endif + +extern FTN_FUNC void FTN_NAME(setulb)( + int *, int *, double *, double *, double *, int *, + double *, double *, double *, double *, double *, int *, + char *, int *, char *, unsigned int *, int *, double *); + +#endif /* lbfgs */ diff --git a/dep/slatec/CMakeLists.txt b/dep/slatec/CMakeLists.txt new file mode 100644 index 00000000..5b7600c8 --- /dev/null +++ b/dep/slatec/CMakeLists.txt @@ -0,0 +1,13 @@ + +enable_language(Fortran) + +FILE(GLOB slsrc "*.f") +add_library(depslatec ${slsrc}) + +INSTALL(TARGETS depslatec DESTINATION lib) + +SET(slatec_HEADERS + depslatec.h + ) + +INSTALL(FILES ${slatec_HEADERS} DESTINATION include/dep) diff --git a/dep/slatec/depslatec.h b/dep/slatec/depslatec.h new file mode 100644 index 00000000..5202332c --- /dev/null +++ b/dep/slatec/depslatec.h @@ -0,0 +1,20 @@ +#ifndef SLATEC_H +#define SLATEC_H + +#include "ftndefs.h" + + +// Some typedefs for the function callbacks in its arguments +typedef void (*f77_matvecprod)(int*, double*, double*, int*, + int*, int*, double*, int*); +typedef void (*f77_precond)(int*, double*, double*, int*, + int*, int*, double*, int*, double*, int*); + +// Preconditioned GMRES iterative sparse Ax=b solver +// see dgmres.f for details +extern FTN_FUNC void FTN_NAME(dgmres)(int*, double*, double*, int*, int*, int*, + double*, int*, f77_matvecprod, f77_precond, + int*, double*, int*, int*, double*, int*, int*, double*, double*, + double*, int*, int*, int*, double*, int*); + +#endif /* SLATEC_H */ diff --git a/dep/slatec/dgbfa.f b/dep/slatec/dgbfa.f new file mode 100644 index 00000000..a8a0d6d4 --- /dev/null +++ b/dep/slatec/dgbfa.f @@ -0,0 +1,187 @@ +*DECK DGBFA + SUBROUTINE DGBFA (ABD, LDA, N, ML, MU, IPVT, INFO) +C***BEGIN PROLOGUE DGBFA +C***PURPOSE Factor a band matrix using Gaussian elimination. +C***LIBRARY SLATEC (LINPACK) +C***CATEGORY D2A2 +C***TYPE DOUBLE PRECISION (SGBFA-S, DGBFA-D, CGBFA-C) +C***KEYWORDS BANDED, LINEAR ALGEBRA, LINPACK, MATRIX FACTORIZATION +C***AUTHOR Moler, C. B., (U. of New Mexico) +C***DESCRIPTION +C +C DGBFA factors a double precision band matrix by elimination. +C +C DGBFA is usually called by DGBCO, but it can be called +C directly with a saving in time if RCOND is not needed. +C +C On Entry +C +C ABD DOUBLE PRECISION(LDA, N) +C contains the matrix in band storage. The columns +C of the matrix are stored in the columns of ABD and +C the diagonals of the matrix are stored in rows +C ML+1 through 2*ML+MU+1 of ABD . +C See the comments below for details. +C +C LDA INTEGER +C the leading dimension of the array ABD . +C LDA must be .GE. 2*ML + MU + 1 . +C +C N INTEGER +C the order of the original matrix. +C +C ML INTEGER +C number of diagonals below the main diagonal. +C 0 .LE. ML .LT. N . +C +C MU INTEGER +C number of diagonals above the main diagonal. +C 0 .LE. MU .LT. N . +C More efficient if ML .LE. MU . +C On Return +C +C ABD an upper triangular matrix in band storage and +C the multipliers which were used to obtain it. +C The factorization can be written A = L*U where +C L is a product of permutation and unit lower +C triangular matrices and U is upper triangular. +C +C IPVT INTEGER(N) +C an integer vector of pivot indices. +C +C INFO INTEGER +C = 0 normal value. +C = K if U(K,K) .EQ. 0.0 . This is not an error +C condition for this subroutine, but it does +C indicate that DGBSL will divide by zero if +C called. Use RCOND in DGBCO for a reliable +C indication of singularity. +C +C Band Storage +C +C If A is a band matrix, the following program segment +C will set up the input. +C +C ML = (band width below the diagonal) +C MU = (band width above the diagonal) +C M = ML + MU + 1 +C DO 20 J = 1, N +C I1 = MAX(1, J-MU) +C I2 = MIN(N, J+ML) +C DO 10 I = I1, I2 +C K = I - J + M +C ABD(K,J) = A(I,J) +C 10 CONTINUE +C 20 CONTINUE +C +C This uses rows ML+1 through 2*ML+MU+1 of ABD . +C In addition, the first ML rows in ABD are used for +C elements generated during the triangularization. +C The total number of rows needed in ABD is 2*ML+MU+1 . +C The ML+MU by ML+MU upper left triangle and the +C ML by ML lower right triangle are not referenced. +C +C***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. +C Stewart, LINPACK Users' Guide, SIAM, 1979. +C***ROUTINES CALLED DAXPY, DSCAL, IDAMAX +C***REVISION HISTORY (YYMMDD) +C 780814 DATE WRITTEN +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890831 Modified array declarations. (WRB) +C 890831 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900326 Removed duplicate information from DESCRIPTION section. +C (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE DGBFA + INTEGER LDA,N,ML,MU,IPVT(*),INFO + DOUBLE PRECISION ABD(LDA,*) +C + DOUBLE PRECISION T + INTEGER I,IDAMAX,I0,J,JU,JZ,J0,J1,K,KP1,L,LM,M,MM,NM1 +C +C***FIRST EXECUTABLE STATEMENT DGBFA + M = ML + MU + 1 + INFO = 0 +C +C ZERO INITIAL FILL-IN COLUMNS +C + J0 = MU + 2 + J1 = MIN(N,M) - 1 + IF (J1 .LT. J0) GO TO 30 + DO 20 JZ = J0, J1 + I0 = M + 1 - JZ + DO 10 I = I0, ML + ABD(I,JZ) = 0.0D0 + 10 CONTINUE + 20 CONTINUE + 30 CONTINUE + JZ = J1 + JU = 0 +C +C GAUSSIAN ELIMINATION WITH PARTIAL PIVOTING +C + NM1 = N - 1 + IF (NM1 .LT. 1) GO TO 130 + DO 120 K = 1, NM1 + KP1 = K + 1 +C +C ZERO NEXT FILL-IN COLUMN +C + JZ = JZ + 1 + IF (JZ .GT. N) GO TO 50 + IF (ML .LT. 1) GO TO 50 + DO 40 I = 1, ML + ABD(I,JZ) = 0.0D0 + 40 CONTINUE + 50 CONTINUE +C +C FIND L = PIVOT INDEX +C + LM = MIN(ML,N-K) + L = IDAMAX(LM+1,ABD(M,K),1) + M - 1 + IPVT(K) = L + K - M +C +C ZERO PIVOT IMPLIES THIS COLUMN ALREADY TRIANGULARIZED +C + IF (ABD(L,K) .EQ. 0.0D0) GO TO 100 +C +C INTERCHANGE IF NECESSARY +C + IF (L .EQ. M) GO TO 60 + T = ABD(L,K) + ABD(L,K) = ABD(M,K) + ABD(M,K) = T + 60 CONTINUE +C +C COMPUTE MULTIPLIERS +C + T = -1.0D0/ABD(M,K) + CALL DSCAL(LM,T,ABD(M+1,K),1) +C +C ROW ELIMINATION WITH COLUMN INDEXING +C + JU = MIN(MAX(JU,MU+IPVT(K)),N) + MM = M + IF (JU .LT. KP1) GO TO 90 + DO 80 J = KP1, JU + L = L - 1 + MM = MM - 1 + T = ABD(L,J) + IF (L .EQ. MM) GO TO 70 + ABD(L,J) = ABD(MM,J) + ABD(MM,J) = T + 70 CONTINUE + CALL DAXPY(LM,T,ABD(M+1,K),1,ABD(MM+1,J),1) + 80 CONTINUE + 90 CONTINUE + GO TO 110 + 100 CONTINUE + INFO = K + 110 CONTINUE + 120 CONTINUE + 130 CONTINUE + IPVT(N) = N + IF (ABD(M,N) .EQ. 0.0D0) INFO = N + RETURN + END diff --git a/dep/slatec/dgbsl.f b/dep/slatec/dgbsl.f new file mode 100644 index 00000000..ff73ad64 --- /dev/null +++ b/dep/slatec/dgbsl.f @@ -0,0 +1,149 @@ +*DECK DGBSL + SUBROUTINE DGBSL (ABD, LDA, N, ML, MU, IPVT, B, JOB) +C***BEGIN PROLOGUE DGBSL +C***PURPOSE Solve the real band system A*X=B or TRANS(A)*X=B using +C the factors computed by DGBCO or DGBFA. +C***LIBRARY SLATEC (LINPACK) +C***CATEGORY D2A2 +C***TYPE DOUBLE PRECISION (SGBSL-S, DGBSL-D, CGBSL-C) +C***KEYWORDS BANDED, LINEAR ALGEBRA, LINPACK, MATRIX, SOLVE +C***AUTHOR Moler, C. B., (U. of New Mexico) +C***DESCRIPTION +C +C DGBSL solves the double precision band system +C A * X = B or TRANS(A) * X = B +C using the factors computed by DGBCO or DGBFA. +C +C On Entry +C +C ABD DOUBLE PRECISION(LDA, N) +C the output from DGBCO or DGBFA. +C +C LDA INTEGER +C the leading dimension of the array ABD . +C +C N INTEGER +C the order of the original matrix. +C +C ML INTEGER +C number of diagonals below the main diagonal. +C +C MU INTEGER +C number of diagonals above the main diagonal. +C +C IPVT INTEGER(N) +C the pivot vector from DGBCO or DGBFA. +C +C B DOUBLE PRECISION(N) +C the right hand side vector. +C +C JOB INTEGER +C = 0 to solve A*X = B , +C = nonzero to solve TRANS(A)*X = B , where +C TRANS(A) is the transpose. +C +C On Return +C +C B the solution vector X . +C +C Error Condition +C +C A division by zero will occur if the input factor contains a +C zero on the diagonal. Technically this indicates singularity +C but it is often caused by improper arguments or improper +C setting of LDA . It will not occur if the subroutines are +C called correctly and if DGBCO has set RCOND .GT. 0.0 +C or DGBFA has set INFO .EQ. 0 . +C +C To compute INVERSE(A) * C where C is a matrix +C with P columns +C CALL DGBCO(ABD,LDA,N,ML,MU,IPVT,RCOND,Z) +C IF (RCOND is too small) GO TO ... +C DO 10 J = 1, P +C CALL DGBSL(ABD,LDA,N,ML,MU,IPVT,C(1,J),0) +C 10 CONTINUE +C +C***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. +C Stewart, LINPACK Users' Guide, SIAM, 1979. +C***ROUTINES CALLED DAXPY, DDOT +C***REVISION HISTORY (YYMMDD) +C 780814 DATE WRITTEN +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890831 Modified array declarations. (WRB) +C 890831 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900326 Removed duplicate information from DESCRIPTION section. +C (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE DGBSL + INTEGER LDA,N,ML,MU,IPVT(*),JOB + DOUBLE PRECISION ABD(LDA,*),B(*) +C + DOUBLE PRECISION DDOT,T + INTEGER K,KB,L,LA,LB,LM,M,NM1 +C***FIRST EXECUTABLE STATEMENT DGBSL + M = MU + ML + 1 + NM1 = N - 1 + IF (JOB .NE. 0) GO TO 50 +C +C JOB = 0 , SOLVE A * X = B +C FIRST SOLVE L*Y = B +C + IF (ML .EQ. 0) GO TO 30 + IF (NM1 .LT. 1) GO TO 30 + DO 20 K = 1, NM1 + LM = MIN(ML,N-K) + L = IPVT(K) + T = B(L) + IF (L .EQ. K) GO TO 10 + B(L) = B(K) + B(K) = T + 10 CONTINUE + CALL DAXPY(LM,T,ABD(M+1,K),1,B(K+1),1) + 20 CONTINUE + 30 CONTINUE +C +C NOW SOLVE U*X = Y +C + DO 40 KB = 1, N + K = N + 1 - KB + B(K) = B(K)/ABD(M,K) + LM = MIN(K,M) - 1 + LA = M - LM + LB = K - LM + T = -B(K) + CALL DAXPY(LM,T,ABD(LA,K),1,B(LB),1) + 40 CONTINUE + GO TO 100 + 50 CONTINUE +C +C JOB = NONZERO, SOLVE TRANS(A) * X = B +C FIRST SOLVE TRANS(U)*Y = B +C + DO 60 K = 1, N + LM = MIN(K,M) - 1 + LA = M - LM + LB = K - LM + T = DDOT(LM,ABD(LA,K),1,B(LB),1) + B(K) = (B(K) - T)/ABD(M,K) + 60 CONTINUE +C +C NOW SOLVE TRANS(L)*X = Y +C + IF (ML .EQ. 0) GO TO 90 + IF (NM1 .LT. 1) GO TO 90 + DO 80 KB = 1, NM1 + K = N - KB + LM = MIN(ML,N-K) + B(K) = B(K) + DDOT(LM,ABD(M+1,K),1,B(K+1),1) + L = IPVT(K) + IF (L .EQ. K) GO TO 70 + T = B(L) + B(L) = B(K) + B(K) = T + 70 CONTINUE + 80 CONTINUE + 90 CONTINUE + 100 CONTINUE + RETURN + END diff --git a/dep/slatec/dgeco.f b/dep/slatec/dgeco.f new file mode 100644 index 00000000..3f56183c --- /dev/null +++ b/dep/slatec/dgeco.f @@ -0,0 +1,207 @@ +*DECK DGECO + SUBROUTINE DGECO (A, LDA, N, IPVT, RCOND, Z) +C***BEGIN PROLOGUE DGECO +C***PURPOSE Factor a matrix using Gaussian elimination and estimate +C the condition number of the matrix. +C***LIBRARY SLATEC (LINPACK) +C***CATEGORY D2A1 +C***TYPE DOUBLE PRECISION (SGECO-S, DGECO-D, CGECO-C) +C***KEYWORDS CONDITION NUMBER, GENERAL MATRIX, LINEAR ALGEBRA, LINPACK, +C MATRIX FACTORIZATION +C***AUTHOR Moler, C. B., (U. of New Mexico) +C***DESCRIPTION +C +C DGECO factors a double precision matrix by Gaussian elimination +C and estimates the condition of the matrix. +C +C If RCOND is not needed, DGEFA is slightly faster. +C To solve A*X = B , follow DGECO by DGESL. +C To compute INVERSE(A)*C , follow DGECO by DGESL. +C To compute DETERMINANT(A) , follow DGECO by DGEDI. +C To compute INVERSE(A) , follow DGECO by DGEDI. +C +C On Entry +C +C A DOUBLE PRECISION(LDA, N) +C the matrix to be factored. +C +C LDA INTEGER +C the leading dimension of the array A . +C +C N INTEGER +C the order of the matrix A . +C +C On Return +C +C A an upper triangular matrix and the multipliers +C which were used to obtain it. +C The factorization can be written A = L*U where +C L is a product of permutation and unit lower +C triangular matrices and U is upper triangular. +C +C IPVT INTEGER(N) +C an INTEGER vector of pivot indices. +C +C RCOND DOUBLE PRECISION +C an estimate of the reciprocal condition of A . +C For the system A*X = B , relative perturbations +C in A and B of size EPSILON may cause +C relative perturbations in X of size EPSILON/RCOND . +C If RCOND is so small that the logical expression +C 1.0 + RCOND .EQ. 1.0 +C is true, then A may be singular to working +C precision. In particular, RCOND is zero if +C exact singularity is detected or the estimate +C underflows. +C +C Z DOUBLE PRECISION(N) +C a work vector whose contents are usually unimportant. +C If A is close to a singular matrix, then Z is +C an approximate null vector in the sense that +C NORM(A*Z) = RCOND*NORM(A)*NORM(Z) . +C +C***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. +C Stewart, LINPACK Users' Guide, SIAM, 1979. +C***ROUTINES CALLED DASUM, DAXPY, DDOT, DGEFA, DSCAL +C***REVISION HISTORY (YYMMDD) +C 780814 DATE WRITTEN +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890831 Modified array declarations. (WRB) +C 890831 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900326 Removed duplicate information from DESCRIPTION section. +C (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE DGECO + INTEGER LDA,N,IPVT(*) + DOUBLE PRECISION A(LDA,*),Z(*) + DOUBLE PRECISION RCOND +C + DOUBLE PRECISION DDOT,EK,T,WK,WKM + DOUBLE PRECISION ANORM,S,DASUM,SM,YNORM + INTEGER INFO,J,K,KB,KP1,L +C +C COMPUTE 1-NORM OF A +C +C***FIRST EXECUTABLE STATEMENT DGECO + ANORM = 0.0D0 + DO 10 J = 1, N + ANORM = MAX(ANORM,DASUM(N,A(1,J),1)) + 10 CONTINUE +C +C FACTOR +C + CALL DGEFA(A,LDA,N,IPVT,INFO) +C +C RCOND = 1/(NORM(A)*(ESTIMATE OF NORM(INVERSE(A)))) . +C ESTIMATE = NORM(Z)/NORM(Y) WHERE A*Z = Y AND TRANS(A)*Y = E . +C TRANS(A) IS THE TRANSPOSE OF A . THE COMPONENTS OF E ARE +C CHOSEN TO CAUSE MAXIMUM LOCAL GROWTH IN THE ELEMENTS OF W WHERE +C TRANS(U)*W = E . THE VECTORS ARE FREQUENTLY RESCALED TO AVOID +C OVERFLOW. +C +C SOLVE TRANS(U)*W = E +C + EK = 1.0D0 + DO 20 J = 1, N + Z(J) = 0.0D0 + 20 CONTINUE + DO 100 K = 1, N + IF (Z(K) .NE. 0.0D0) EK = SIGN(EK,-Z(K)) + IF (ABS(EK-Z(K)) .LE. ABS(A(K,K))) GO TO 30 + S = ABS(A(K,K))/ABS(EK-Z(K)) + CALL DSCAL(N,S,Z,1) + EK = S*EK + 30 CONTINUE + WK = EK - Z(K) + WKM = -EK - Z(K) + S = ABS(WK) + SM = ABS(WKM) + IF (A(K,K) .EQ. 0.0D0) GO TO 40 + WK = WK/A(K,K) + WKM = WKM/A(K,K) + GO TO 50 + 40 CONTINUE + WK = 1.0D0 + WKM = 1.0D0 + 50 CONTINUE + KP1 = K + 1 + IF (KP1 .GT. N) GO TO 90 + DO 60 J = KP1, N + SM = SM + ABS(Z(J)+WKM*A(K,J)) + Z(J) = Z(J) + WK*A(K,J) + S = S + ABS(Z(J)) + 60 CONTINUE + IF (S .GE. SM) GO TO 80 + T = WKM - WK + WK = WKM + DO 70 J = KP1, N + Z(J) = Z(J) + T*A(K,J) + 70 CONTINUE + 80 CONTINUE + 90 CONTINUE + Z(K) = WK + 100 CONTINUE + S = 1.0D0/DASUM(N,Z,1) + CALL DSCAL(N,S,Z,1) +C +C SOLVE TRANS(L)*Y = W +C + DO 120 KB = 1, N + K = N + 1 - KB + IF (K .LT. N) Z(K) = Z(K) + DDOT(N-K,A(K+1,K),1,Z(K+1),1) + IF (ABS(Z(K)) .LE. 1.0D0) GO TO 110 + S = 1.0D0/ABS(Z(K)) + CALL DSCAL(N,S,Z,1) + 110 CONTINUE + L = IPVT(K) + T = Z(L) + Z(L) = Z(K) + Z(K) = T + 120 CONTINUE + S = 1.0D0/DASUM(N,Z,1) + CALL DSCAL(N,S,Z,1) +C + YNORM = 1.0D0 +C +C SOLVE L*V = Y +C + DO 140 K = 1, N + L = IPVT(K) + T = Z(L) + Z(L) = Z(K) + Z(K) = T + IF (K .LT. N) CALL DAXPY(N-K,T,A(K+1,K),1,Z(K+1),1) + IF (ABS(Z(K)) .LE. 1.0D0) GO TO 130 + S = 1.0D0/ABS(Z(K)) + CALL DSCAL(N,S,Z,1) + YNORM = S*YNORM + 130 CONTINUE + 140 CONTINUE + S = 1.0D0/DASUM(N,Z,1) + CALL DSCAL(N,S,Z,1) + YNORM = S*YNORM +C +C SOLVE U*Z = V +C + DO 160 KB = 1, N + K = N + 1 - KB + IF (ABS(Z(K)) .LE. ABS(A(K,K))) GO TO 150 + S = ABS(A(K,K))/ABS(Z(K)) + CALL DSCAL(N,S,Z,1) + YNORM = S*YNORM + 150 CONTINUE + IF (A(K,K) .NE. 0.0D0) Z(K) = Z(K)/A(K,K) + IF (A(K,K) .EQ. 0.0D0) Z(K) = 1.0D0 + T = -Z(K) + CALL DAXPY(K-1,T,A(1,K),1,Z(1),1) + 160 CONTINUE +C MAKE ZNORM = 1.0 + S = 1.0D0/DASUM(N,Z,1) + CALL DSCAL(N,S,Z,1) + YNORM = S*YNORM +C + IF (ANORM .NE. 0.0D0) RCOND = YNORM/ANORM + IF (ANORM .EQ. 0.0D0) RCOND = 0.0D0 + RETURN + END diff --git a/dep/slatec/dgefa.f b/dep/slatec/dgefa.f new file mode 100644 index 00000000..57d9105d --- /dev/null +++ b/dep/slatec/dgefa.f @@ -0,0 +1,117 @@ +*DECK DGEFA + SUBROUTINE DGEFA (A, LDA, N, IPVT, INFO) +C***BEGIN PROLOGUE DGEFA +C***PURPOSE Factor a matrix using Gaussian elimination. +C***LIBRARY SLATEC (LINPACK) +C***CATEGORY D2A1 +C***TYPE DOUBLE PRECISION (SGEFA-S, DGEFA-D, CGEFA-C) +C***KEYWORDS GENERAL MATRIX, LINEAR ALGEBRA, LINPACK, +C MATRIX FACTORIZATION +C***AUTHOR Moler, C. B., (U. of New Mexico) +C***DESCRIPTION +C +C DGEFA factors a double precision matrix by Gaussian elimination. +C +C DGEFA is usually called by DGECO, but it can be called +C directly with a saving in time if RCOND is not needed. +C (Time for DGECO) = (1 + 9/N)*(Time for DGEFA) . +C +C On Entry +C +C A DOUBLE PRECISION(LDA, N) +C the matrix to be factored. +C +C LDA INTEGER +C the leading dimension of the array A . +C +C N INTEGER +C the order of the matrix A . +C +C On Return +C +C A an upper triangular matrix and the multipliers +C which were used to obtain it. +C The factorization can be written A = L*U where +C L is a product of permutation and unit lower +C triangular matrices and U is upper triangular. +C +C IPVT INTEGER(N) +C an integer vector of pivot indices. +C +C INFO INTEGER +C = 0 normal value. +C = K if U(K,K) .EQ. 0.0 . This is not an error +C condition for this subroutine, but it does +C indicate that DGESL or DGEDI will divide by zero +C if called. Use RCOND in DGECO for a reliable +C indication of singularity. +C +C***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. +C Stewart, LINPACK Users' Guide, SIAM, 1979. +C***ROUTINES CALLED DAXPY, DSCAL, IDAMAX +C***REVISION HISTORY (YYMMDD) +C 780814 DATE WRITTEN +C 890831 Modified array declarations. (WRB) +C 890831 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900326 Removed duplicate information from DESCRIPTION section. +C (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE DGEFA + INTEGER LDA,N,IPVT(*),INFO + DOUBLE PRECISION A(LDA,*) +C + DOUBLE PRECISION T + INTEGER IDAMAX,J,K,KP1,L,NM1 +C +C GAUSSIAN ELIMINATION WITH PARTIAL PIVOTING +C +C***FIRST EXECUTABLE STATEMENT DGEFA + INFO = 0 + NM1 = N - 1 + IF (NM1 .LT. 1) GO TO 70 + DO 60 K = 1, NM1 + KP1 = K + 1 +C +C FIND L = PIVOT INDEX +C + L = IDAMAX(N-K+1,A(K,K),1) + K - 1 + IPVT(K) = L +C +C ZERO PIVOT IMPLIES THIS COLUMN ALREADY TRIANGULARIZED +C + IF (A(L,K) .EQ. 0.0D0) GO TO 40 +C +C INTERCHANGE IF NECESSARY +C + IF (L .EQ. K) GO TO 10 + T = A(L,K) + A(L,K) = A(K,K) + A(K,K) = T + 10 CONTINUE +C +C COMPUTE MULTIPLIERS +C + T = -1.0D0/A(K,K) + CALL DSCAL(N-K,T,A(K+1,K),1) +C +C ROW ELIMINATION WITH COLUMN INDEXING +C + DO 30 J = KP1, N + T = A(L,J) + IF (L .EQ. K) GO TO 20 + A(L,J) = A(K,J) + A(K,J) = T + 20 CONTINUE + CALL DAXPY(N-K,T,A(K+1,K),1,A(K+1,J),1) + 30 CONTINUE + GO TO 50 + 40 CONTINUE + INFO = K + 50 CONTINUE + 60 CONTINUE + 70 CONTINUE + IPVT(N) = N + IF (A(N,N) .EQ. 0.0D0) INFO = N + RETURN + END diff --git a/dep/slatec/dgefs.f b/dep/slatec/dgefs.f new file mode 100644 index 00000000..3dc6fb0a --- /dev/null +++ b/dep/slatec/dgefs.f @@ -0,0 +1,165 @@ +*DECK DGEFS + SUBROUTINE DGEFS (A, LDA, N, V, ITASK, IND, WORK, IWORK) +C***BEGIN PROLOGUE DGEFS +C***PURPOSE Solve a general system of linear equations. +C***LIBRARY SLATEC +C***CATEGORY D2A1 +C***TYPE DOUBLE PRECISION (SGEFS-S, DGEFS-D, CGEFS-C) +C***KEYWORDS COMPLEX LINEAR EQUATIONS, GENERAL MATRIX, +C GENERAL SYSTEM OF LINEAR EQUATIONS +C***AUTHOR Voorhees, E. A., (LANL) +C***DESCRIPTION +C +C Subroutine DGEFS solves a general NxN system of double +C precision linear equations using LINPACK subroutines DGECO +C and DGESL. That is, if A is an NxN double precision matrix +C and if X and B are double precision N-vectors, then DGEFS +C solves the equation +C +C A*X=B. +C +C The matrix A is first factored into upper and lower tri- +C angular matrices U and L using partial pivoting. These +C factors and the pivoting information are used to find the +C solution vector X. An approximate condition number is +C calculated to provide a rough estimate of the number of +C digits of accuracy in the computed solution. +C +C If the equation A*X=B is to be solved for more than one vector +C B, the factoring of A does not need to be performed again and +C the option to only solve (ITASK.GT.1) will be faster for +C the succeeding solutions. In this case, the contents of A, +C LDA, N and IWORK must not have been altered by the user follow- +C ing factorization (ITASK=1). IND will not be changed by DGEFS +C in this case. +C +C Argument Description *** +C +C A DOUBLE PRECISION(LDA,N) +C on entry, the doubly subscripted array with dimension +C (LDA,N) which contains the coefficient matrix. +C on return, an upper triangular matrix U and the +C multipliers necessary to construct a matrix L +C so that A=L*U. +C LDA INTEGER +C the leading dimension of the array A. LDA must be great- +C er than or equal to N. (terminal error message IND=-1) +C N INTEGER +C the order of the matrix A. The first N elements of +C the array A are the elements of the first column of +C the matrix A. N must be greater than or equal to 1. +C (terminal error message IND=-2) +C V DOUBLE PRECISION(N) +C on entry, the singly subscripted array(vector) of di- +C mension N which contains the right hand side B of a +C system of simultaneous linear equations A*X=B. +C on return, V contains the solution vector, X . +C ITASK INTEGER +C If ITASK=1, the matrix A is factored and then the +C linear equation is solved. +C If ITASK .GT. 1, the equation is solved using the existing +C factored matrix A and IWORK. +C If ITASK .LT. 1, then terminal error message IND=-3 is +C printed. +C IND INTEGER +C GT. 0 IND is a rough estimate of the number of digits +C of accuracy in the solution, X. +C LT. 0 see error message corresponding to IND below. +C WORK DOUBLE PRECISION(N) +C a singly subscripted array of dimension at least N. +C IWORK INTEGER(N) +C a singly subscripted array of dimension at least N. +C +C Error Messages Printed *** +C +C IND=-1 terminal N is greater than LDA. +C IND=-2 terminal N is less than 1. +C IND=-3 terminal ITASK is less than 1. +C IND=-4 terminal The matrix A is computationally singular. +C A solution has not been computed. +C IND=-10 warning The solution has no apparent significance. +C The solution may be inaccurate or the matrix +C A may be poorly scaled. +C +C Note- The above terminal(*fatal*) error messages are +C designed to be handled by XERMSG in which +C LEVEL=1 (recoverable) and IFLAG=2 . LEVEL=0 +C for warning error messages from XERMSG. Unless +C the user provides otherwise, an error message +C will be printed followed by an abort. +C +C***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. +C Stewart, LINPACK Users' Guide, SIAM, 1979. +C***ROUTINES CALLED D1MACH, DGECO, DGESL, XERMSG +C***REVISION HISTORY (YYMMDD) +C 800326 DATE WRITTEN +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890831 Modified array declarations. (WRB) +C 890831 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ) +C 900510 Convert XERRWV calls to XERMSG calls. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE DGEFS +C + INTEGER LDA,N,ITASK,IND,IWORK(*) + DOUBLE PRECISION A(LDA,*),V(*),WORK(*),D1MACH + DOUBLE PRECISION RCOND + CHARACTER*8 XERN1, XERN2 +C***FIRST EXECUTABLE STATEMENT DGEFS + IF (LDA.LT.N) THEN + IND = -1 + WRITE (XERN1, '(I8)') LDA + WRITE (XERN2, '(I8)') N + CALL XERMSG ('SLATEC', 'DGEFS', 'LDA = ' // XERN1 // + * ' IS LESS THAN N = ' // XERN2, -1, 1) + RETURN + ENDIF +C + IF (N.LE.0) THEN + IND = -2 + WRITE (XERN1, '(I8)') N + CALL XERMSG ('SLATEC', 'DGEFS', 'N = ' // XERN1 // + * ' IS LESS THAN 1', -2, 1) + RETURN + ENDIF +C + IF (ITASK.LT.1) THEN + IND = -3 + WRITE (XERN1, '(I8)') ITASK + CALL XERMSG ('SLATEC', 'DGEFS', 'ITASK = ' // XERN1 // + * ' IS LESS THAN 1', -3, 1) + RETURN + ENDIF +C + IF (ITASK.EQ.1) THEN +C +C FACTOR MATRIX A INTO LU +C + CALL DGECO(A,LDA,N,IWORK,RCOND,WORK) +C +C CHECK FOR COMPUTATIONALLY SINGULAR MATRIX +C + IF (RCOND.EQ.0.0D0) THEN + IND = -4 + CALL XERMSG ('SLATEC', 'DGEFS', + * 'SINGULAR MATRIX A - NO SOLUTION', -4, 1) + RETURN + ENDIF +C +C COMPUTE IND (ESTIMATE OF NO. OF SIGNIFICANT DIGITS) +C AND CHECK FOR IND GREATER THAN ZERO +C + IND = -LOG10(D1MACH(4)/RCOND) + IF (IND.LE.0) THEN + IND=-10 + CALL XERMSG ('SLATEC', 'DGEFS', + * 'SOLUTION MAY HAVE NO SIGNIFICANCE', -10, 0) + ENDIF + ENDIF +C +C SOLVE AFTER FACTORING +C + CALL DGESL(A,LDA,N,IWORK,V,0) + RETURN + END diff --git a/dep/slatec/dgesl.f b/dep/slatec/dgesl.f new file mode 100644 index 00000000..0059359c --- /dev/null +++ b/dep/slatec/dgesl.f @@ -0,0 +1,131 @@ +*DECK DGESL + SUBROUTINE DGESL (A, LDA, N, IPVT, B, JOB) +C***BEGIN PROLOGUE DGESL +C***PURPOSE Solve the real system A*X=B or TRANS(A)*X=B using the +C factors computed by DGECO or DGEFA. +C***LIBRARY SLATEC (LINPACK) +C***CATEGORY D2A1 +C***TYPE DOUBLE PRECISION (SGESL-S, DGESL-D, CGESL-C) +C***KEYWORDS LINEAR ALGEBRA, LINPACK, MATRIX, SOLVE +C***AUTHOR Moler, C. B., (U. of New Mexico) +C***DESCRIPTION +C +C DGESL solves the double precision system +C A * X = B or TRANS(A) * X = B +C using the factors computed by DGECO or DGEFA. +C +C On Entry +C +C A DOUBLE PRECISION(LDA, N) +C the output from DGECO or DGEFA. +C +C LDA INTEGER +C the leading dimension of the array A . +C +C N INTEGER +C the order of the matrix A . +C +C IPVT INTEGER(N) +C the pivot vector from DGECO or DGEFA. +C +C B DOUBLE PRECISION(N) +C the right hand side vector. +C +C JOB INTEGER +C = 0 to solve A*X = B , +C = nonzero to solve TRANS(A)*X = B where +C TRANS(A) is the transpose. +C +C On Return +C +C B the solution vector X . +C +C Error Condition +C +C A division by zero will occur if the input factor contains a +C zero on the diagonal. Technically this indicates singularity +C but it is often caused by improper arguments or improper +C setting of LDA . It will not occur if the subroutines are +C called correctly and if DGECO has set RCOND .GT. 0.0 +C or DGEFA has set INFO .EQ. 0 . +C +C To compute INVERSE(A) * C where C is a matrix +C with P columns +C CALL DGECO(A,LDA,N,IPVT,RCOND,Z) +C IF (RCOND is too small) GO TO ... +C DO 10 J = 1, P +C CALL DGESL(A,LDA,N,IPVT,C(1,J),0) +C 10 CONTINUE +C +C***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. +C Stewart, LINPACK Users' Guide, SIAM, 1979. +C***ROUTINES CALLED DAXPY, DDOT +C***REVISION HISTORY (YYMMDD) +C 780814 DATE WRITTEN +C 890831 Modified array declarations. (WRB) +C 890831 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900326 Removed duplicate information from DESCRIPTION section. +C (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE DGESL + INTEGER LDA,N,IPVT(*),JOB + DOUBLE PRECISION A(LDA,*),B(*) +C + DOUBLE PRECISION DDOT,T + INTEGER K,KB,L,NM1 +C***FIRST EXECUTABLE STATEMENT DGESL + NM1 = N - 1 + IF (JOB .NE. 0) GO TO 50 +C +C JOB = 0 , SOLVE A * X = B +C FIRST SOLVE L*Y = B +C + IF (NM1 .LT. 1) GO TO 30 + DO 20 K = 1, NM1 + L = IPVT(K) + T = B(L) + IF (L .EQ. K) GO TO 10 + B(L) = B(K) + B(K) = T + 10 CONTINUE + CALL DAXPY(N-K,T,A(K+1,K),1,B(K+1),1) + 20 CONTINUE + 30 CONTINUE +C +C NOW SOLVE U*X = Y +C + DO 40 KB = 1, N + K = N + 1 - KB + B(K) = B(K)/A(K,K) + T = -B(K) + CALL DAXPY(K-1,T,A(1,K),1,B(1),1) + 40 CONTINUE + GO TO 100 + 50 CONTINUE +C +C JOB = NONZERO, SOLVE TRANS(A) * X = B +C FIRST SOLVE TRANS(U)*Y = B +C + DO 60 K = 1, N + T = DDOT(K-1,A(1,K),1,B(1),1) + B(K) = (B(K) - T)/A(K,K) + 60 CONTINUE +C +C NOW SOLVE TRANS(L)*X = Y +C + IF (NM1 .LT. 1) GO TO 90 + DO 80 KB = 1, NM1 + K = N - KB + B(K) = B(K) + DDOT(N-K,A(K+1,K),1,B(K+1),1) + L = IPVT(K) + IF (L .EQ. K) GO TO 70 + T = B(L) + B(L) = B(K) + B(K) = T + 70 CONTINUE + 80 CONTINUE + 90 CONTINUE + 100 CONTINUE + RETURN + END diff --git a/dep/slatec/dgmres.f b/dep/slatec/dgmres.f new file mode 100644 index 00000000..44d5ad99 --- /dev/null +++ b/dep/slatec/dgmres.f @@ -0,0 +1,553 @@ +*DECK DGMRES + SUBROUTINE DGMRES (N, B, X, NELT, IA, JA, A, ISYM, MATVEC, MSOLVE, + + ITOL, TOL, ITMAX, ITER, ERR, IERR, IUNIT, SB, SX, RGWK, LRGW, + + IGWK, LIGW, RWORK, IWORK) +C***BEGIN PROLOGUE DGMRES +C***PURPOSE Preconditioned GMRES iterative sparse Ax=b solver. +C This routine uses the generalized minimum residual +C (GMRES) method with preconditioning to solve +C non-symmetric linear systems of the form: Ax = b. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SGMRES-S, DGMRES-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C +C *Usage: +C INTEGER N, NELT, IA(NELT), JA(NELT), ISYM, ITOL, ITMAX +C INTEGER ITER, IERR, IUNIT, LRGW, IGWK(LIGW), LIGW +C INTEGER IWORK(USER DEFINED) +C DOUBLE PRECISION B(N), X(N), A(NELT), TOL, ERR, SB(N), SX(N) +C DOUBLE PRECISION RGWK(LRGW), RWORK(USER DEFINED) +C EXTERNAL MATVEC, MSOLVE +C +C CALL DGMRES(N, B, X, NELT, IA, JA, A, ISYM, MATVEC, MSOLVE, +C $ ITOL, TOL, ITMAX, ITER, ERR, IERR, IUNIT, SB, SX, +C $ RGWK, LRGW, IGWK, LIGW, RWORK, IWORK) +C +C *Arguments: +C N :IN Integer. +C Order of the Matrix. +C B :IN Double Precision B(N). +C Right-hand side vector. +C X :INOUT Double Precision X(N). +C On input X is your initial guess for the solution vector. +C On output X is the final approximate solution. +C NELT :IN Integer. +C Number of Non-Zeros stored in A. +C IA :IN Integer IA(NELT). +C JA :IN Integer JA(NELT). +C A :IN Double Precision A(NELT). +C These arrays contain the matrix data structure for A. +C It could take any form. See "Description", below, +C for more details. +C ISYM :IN Integer. +C Flag to indicate symmetric storage format. +C If ISYM=0, all non-zero entries of the matrix are stored. +C If ISYM=1, the matrix is symmetric, and only the upper +C or lower triangle of the matrix is stored. +C MATVEC :EXT External. +C Name of a routine which performs the matrix vector multiply +C Y = A*X given A and X. The name of the MATVEC routine must +C be declared external in the calling program. The calling +C sequence to MATVEC is: +C CALL MATVEC(N, X, Y, NELT, IA, JA, A, ISYM) +C where N is the number of unknowns, Y is the product A*X +C upon return, X is an input vector, and NELT is the number of +C non-zeros in the SLAP IA, JA, A storage for the matrix A. +C ISYM is a flag which, if non-zero, denotes that A is +C symmetric and only the lower or upper triangle is stored. +C MSOLVE :EXT External. +C Name of the routine which solves a linear system Mz = r for +C z given r with the preconditioning matrix M (M is supplied via +C RWORK and IWORK arrays. The name of the MSOLVE routine must +C be declared external in the calling program. The calling +C sequence to MSOLVE is: +C CALL MSOLVE(N, R, Z, NELT, IA, JA, A, ISYM, RWORK, IWORK) +C Where N is the number of unknowns, R is the right-hand side +C vector and Z is the solution upon return. NELT, IA, JA, A and +C ISYM are defined as above. RWORK is a double precision array +C that can be used to pass necessary preconditioning information +C and/or workspace to MSOLVE. IWORK is an integer work array +C for the same purpose as RWORK. +C ITOL :IN Integer. +C Flag to indicate the type of convergence criterion used. +C ITOL=0 Means the iteration stops when the test described +C below on the residual RL is satisfied. This is +C the "Natural Stopping Criteria" for this routine. +C Other values of ITOL cause extra, otherwise +C unnecessary, computation per iteration and are +C therefore much less efficient. See ISDGMR (the +C stop test routine) for more information. +C ITOL=1 Means the iteration stops when the first test +C described below on the residual RL is satisfied, +C and there is either right or no preconditioning +C being used. +C ITOL=2 Implies that the user is using left +C preconditioning, and the second stopping criterion +C below is used. +C ITOL=3 Means the iteration stops when the third test +C described below on Minv*Residual is satisfied, and +C there is either left or no preconditioning being +C used. +C ITOL=11 is often useful for checking and comparing +C different routines. For this case, the user must +C supply the "exact" solution or a very accurate +C approximation (one with an error much less than +C TOL) through a common block, +C COMMON /DSLBLK/ SOLN( ) +C If ITOL=11, iteration stops when the 2-norm of the +C difference between the iterative approximation and +C the user-supplied solution divided by the 2-norm +C of the user-supplied solution is less than TOL. +C Note that this requires the user to set up the +C "COMMON /DSLBLK/ SOLN(LENGTH)" in the calling +C routine. The routine with this declaration should +C be loaded before the stop test so that the correct +C length is used by the loader. This procedure is +C not standard Fortran and may not work correctly on +C your system (although it has worked on every +C system the authors have tried). If ITOL is not 11 +C then this common block is indeed standard Fortran. +C TOL :INOUT Double Precision. +C Convergence criterion, as described below. If TOL is set +C to zero on input, then a default value of 500*(the smallest +C positive magnitude, machine epsilon) is used. +C ITMAX :DUMMY Integer. +C Maximum number of iterations in most SLAP routines. In +C this routine this does not make sense. The maximum number +C of iterations here is given by ITMAX = MAXL*(NRMAX+1). +C See IGWK for definitions of MAXL and NRMAX. +C ITER :OUT Integer. +C Number of iterations required to reach convergence, or +C ITMAX if convergence criterion could not be achieved in +C ITMAX iterations. +C ERR :OUT Double Precision. +C Error estimate of error in final approximate solution, as +C defined by ITOL. Letting norm() denote the Euclidean +C norm, ERR is defined as follows.. +C +C If ITOL=0, then ERR = norm(SB*(B-A*X(L)))/norm(SB*B), +C for right or no preconditioning, and +C ERR = norm(SB*(M-inverse)*(B-A*X(L)))/ +C norm(SB*(M-inverse)*B), +C for left preconditioning. +C If ITOL=1, then ERR = norm(SB*(B-A*X(L)))/norm(SB*B), +C since right or no preconditioning +C being used. +C If ITOL=2, then ERR = norm(SB*(M-inverse)*(B-A*X(L)))/ +C norm(SB*(M-inverse)*B), +C since left preconditioning is being +C used. +C If ITOL=3, then ERR = Max |(Minv*(B-A*X(L)))(i)/x(i)| +C i=1,n +C If ITOL=11, then ERR = norm(SB*(X(L)-SOLN))/norm(SB*SOLN). +C IERR :OUT Integer. +C Return error flag. +C IERR = 0 => All went well. +C IERR = 1 => Insufficient storage allocated for +C RGWK or IGWK. +C IERR = 2 => Routine DGMRES failed to reduce the norm +C of the current residual on its last call, +C and so the iteration has stalled. In +C this case, X equals the last computed +C approximation. The user must either +C increase MAXL, or choose a different +C initial guess. +C IERR =-1 => Insufficient length for RGWK array. +C IGWK(6) contains the required minimum +C length of the RGWK array. +C IERR =-2 => Illegal value of ITOL, or ITOL and JPRE +C values are inconsistent. +C For IERR <= 2, RGWK(1) = RHOL, which is the norm on the +C left-hand-side of the relevant stopping test defined +C below associated with the residual for the current +C approximation X(L). +C IUNIT :IN Integer. +C Unit number on which to write the error at each iteration, +C if this is desired for monitoring convergence. If unit +C number is 0, no writing will occur. +C SB :IN Double Precision SB(N). +C Array of length N containing scale factors for the right +C hand side vector B. If JSCAL.eq.0 (see below), SB need +C not be supplied. +C SX :IN Double Precision SX(N). +C Array of length N containing scale factors for the solution +C vector X. If JSCAL.eq.0 (see below), SX need not be +C supplied. SB and SX can be the same array in the calling +C program if desired. +C RGWK :INOUT Double Precision RGWK(LRGW). +C Double Precision array used for workspace by DGMRES. +C On return, RGWK(1) = RHOL. See IERR for definition of RHOL. +C LRGW :IN Integer. +C Length of the double precision workspace, RGWK. +C LRGW >= 1 + N*(MAXL+6) + MAXL*(MAXL+3). +C See below for definition of MAXL. +C For the default values, RGWK has size at least 131 + 16*N. +C IGWK :INOUT Integer IGWK(LIGW). +C The following IGWK parameters should be set by the user +C before calling this routine. +C IGWK(1) = MAXL. Maximum dimension of Krylov subspace in +C which X - X0 is to be found (where, X0 is the initial +C guess). The default value of MAXL is 10. +C IGWK(2) = KMP. Maximum number of previous Krylov basis +C vectors to which each new basis vector is made orthogonal. +C The default value of KMP is MAXL. +C IGWK(3) = JSCAL. Flag indicating whether the scaling +C arrays SB and SX are to be used. +C JSCAL = 0 => SB and SX are not used and the algorithm +C will perform as if all SB(I) = 1 and SX(I) = 1. +C JSCAL = 1 => Only SX is used, and the algorithm +C performs as if all SB(I) = 1. +C JSCAL = 2 => Only SB is used, and the algorithm +C performs as if all SX(I) = 1. +C JSCAL = 3 => Both SB and SX are used. +C IGWK(4) = JPRE. Flag indicating whether preconditioning +C is being used. +C JPRE = 0 => There is no preconditioning. +C JPRE > 0 => There is preconditioning on the right +C only, and the solver will call routine MSOLVE. +C JPRE < 0 => There is preconditioning on the left +C only, and the solver will call routine MSOLVE. +C IGWK(5) = NRMAX. Maximum number of restarts of the +C Krylov iteration. The default value of NRMAX = 10. +C if IWORK(5) = -1, then no restarts are performed (in +C this case, NRMAX is set to zero internally). +C The following IWORK parameters are diagnostic information +C made available to the user after this routine completes. +C IGWK(6) = MLWK. Required minimum length of RGWK array. +C IGWK(7) = NMS. The total number of calls to MSOLVE. +C LIGW :IN Integer. +C Length of the integer workspace, IGWK. LIGW >= 20. +C RWORK :WORK Double Precision RWORK(USER DEFINED). +C Double Precision array that can be used for workspace in +C MSOLVE. +C IWORK :WORK Integer IWORK(USER DEFINED). +C Integer array that can be used for workspace in MSOLVE. +C +C *Description: +C DGMRES solves a linear system A*X = B rewritten in the form: +C +C (SB*A*(M-inverse)*(SX-inverse))*(SX*M*X) = SB*B, +C +C with right preconditioning, or +C +C (SB*(M-inverse)*A*(SX-inverse))*(SX*X) = SB*(M-inverse)*B, +C +C with left preconditioning, where A is an N-by-N double precision +C matrix, X and B are N-vectors, SB and SX are diagonal scaling +C matrices, and M is a preconditioning matrix. It uses +C preconditioned Krylov subpace methods based on the +C generalized minimum residual method (GMRES). This routine +C optionally performs either the full orthogonalization +C version of the GMRES algorithm or an incomplete variant of +C it. Both versions use restarting of the linear iteration by +C default, although the user can disable this feature. +C +C The GMRES algorithm generates a sequence of approximations +C X(L) to the true solution of the above linear system. The +C convergence criteria for stopping the iteration is based on +C the size of the scaled norm of the residual R(L) = B - +C A*X(L). The actual stopping test is either: +C +C norm(SB*(B-A*X(L))) .le. TOL*norm(SB*B), +C +C for right preconditioning, or +C +C norm(SB*(M-inverse)*(B-A*X(L))) .le. +C TOL*norm(SB*(M-inverse)*B), +C +C for left preconditioning, where norm() denotes the Euclidean +C norm, and TOL is a positive scalar less than one input by +C the user. If TOL equals zero when DGMRES is called, then a +C default value of 500*(the smallest positive magnitude, +C machine epsilon) is used. If the scaling arrays SB and SX +C are used, then ideally they should be chosen so that the +C vectors SX*X(or SX*M*X) and SB*B have all their components +C approximately equal to one in magnitude. If one wants to +C use the same scaling in X and B, then SB and SX can be the +C same array in the calling program. +C +C The following is a list of the other routines and their +C functions used by DGMRES: +C DPIGMR Contains the main iteration loop for GMRES. +C DORTH Orthogonalizes a new vector against older basis vectors. +C DHEQR Computes a QR decomposition of a Hessenberg matrix. +C DHELS Solves a Hessenberg least-squares system, using QR +C factors. +C DRLCAL Computes the scaled residual RL. +C DXLCAL Computes the solution XL. +C ISDGMR User-replaceable stopping routine. +C +C This routine does not care what matrix data structure is +C used for A and M. It simply calls the MATVEC and MSOLVE +C routines, with the arguments as described above. The user +C could write any type of structure and the appropriate MATVEC +C and MSOLVE routines. It is assumed that A is stored in the +C IA, JA, A arrays in some fashion and that M (or INV(M)) is +C stored in IWORK and RWORK in some fashion. The SLAP +C routines DSDCG and DSICCG are examples of this procedure. +C +C Two examples of matrix data structures are the: 1) SLAP +C Triad format and 2) SLAP Column format. +C +C =================== S L A P Triad format =================== +C This routine requires that the matrix A be stored in the +C SLAP Triad format. In this format only the non-zeros are +C stored. They may appear in *ANY* order. The user supplies +C three arrays of length NELT, where NELT is the number of +C non-zeros in the matrix: (IA(NELT), JA(NELT), A(NELT)). For +C each non-zero the user puts the row and column index of that +C matrix element in the IA and JA arrays. The value of the +C non-zero matrix element is placed in the corresponding +C location of the A array. This is an extremely easy data +C structure to generate. On the other hand it is not too +C efficient on vector computers for the iterative solution of +C linear systems. Hence, SLAP changes this input data +C structure to the SLAP Column format for the iteration (but +C does not change it back). +C +C Here is an example of the SLAP Triad storage format for a +C 5x5 Matrix. Recall that the entries may appear in any order. +C +C 5x5 Matrix SLAP Triad format for 5x5 matrix on left. +C 1 2 3 4 5 6 7 8 9 10 11 +C |11 12 0 0 15| A: 51 12 11 33 15 53 55 22 35 44 21 +C |21 22 0 0 0| IA: 5 1 1 3 1 5 5 2 3 4 2 +C | 0 0 33 0 35| JA: 1 2 1 3 5 3 5 2 5 4 1 +C | 0 0 0 44 0| +C |51 0 53 0 55| +C +C =================== S L A P Column format ================== +C +C This routine requires that the matrix A be stored in the +C SLAP Column format. In this format the non-zeros are stored +C counting down columns (except for the diagonal entry, which +C must appear first in each "column") and are stored in the +C double precision array A. In other words, for each column +C in the matrix put the diagonal entry in A. Then put in the +C other non-zero elements going down the column (except the +C diagonal) in order. The IA array holds the row index for +C each non-zero. The JA array holds the offsets into the IA, +C A arrays for the beginning of each column. That is, +C IA(JA(ICOL)), A(JA(ICOL)) points to the beginning of the +C ICOL-th column in IA and A. IA(JA(ICOL+1)-1), +C A(JA(ICOL+1)-1) points to the end of the ICOL-th column. +C Note that we always have JA(N+1) = NELT+1, where N is the +C number of columns in the matrix and NELT is the number of +C non-zeros in the matrix. +C +C Here is an example of the SLAP Column storage format for a +C 5x5 Matrix (in the A and IA arrays '|' denotes the end of a +C column): +C +C 5x5 Matrix SLAP Column format for 5x5 matrix on left. +C 1 2 3 4 5 6 7 8 9 10 11 +C |11 12 0 0 15| A: 11 21 51 | 22 12 | 33 53 | 44 | 55 15 35 +C |21 22 0 0 0| IA: 1 2 5 | 2 1 | 3 5 | 4 | 5 1 3 +C | 0 0 33 0 35| JA: 1 4 6 8 9 12 +C | 0 0 0 44 0| +C |51 0 53 0 55| +C +C *Cautions: +C This routine will attempt to write to the Fortran logical output +C unit IUNIT, if IUNIT .ne. 0. Thus, the user must make sure that +C this logical unit is attached to a file or terminal before calling +C this routine with a non-zero value for IUNIT. This routine does +C not check for the validity of a non-zero IUNIT unit number. +C +C***REFERENCES 1. Peter N. Brown and A. C. Hindmarsh, Reduced Storage +C Matrix Methods in Stiff ODE Systems, Lawrence Liver- +C more National Laboratory Report UCRL-95088, Rev. 1, +C Livermore, California, June 1987. +C 2. Mark K. Seager, A SLAP for the Masses, in +C G. F. Carey, Ed., Parallel Supercomputing: Methods, +C Algorithms and Applications, Wiley, 1989, pp.135-155. +C***ROUTINES CALLED D1MACH, DCOPY, DNRM2, DPIGMR +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 891004 Added new reference. +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910506 Corrected errors in C***ROUTINES CALLED list. (FNF) +C 920407 COMMON BLOCK renamed DSLBLK. (WRB) +C 920511 Added complete declaration section. (WRB) +C 920929 Corrected format of references. (FNF) +C 921019 Changed 500.0 to 500 to reduce SP/DP differences. (FNF) +C 921026 Added check for valid value of ITOL. (FNF) +C***END PROLOGUE DGMRES +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + DOUBLE PRECISION ERR, TOL + INTEGER IERR, ISYM, ITER, ITMAX, ITOL, IUNIT, LIGW, LRGW, N, NELT +C .. Array Arguments .. + DOUBLE PRECISION A(NELT), B(N), RGWK(LRGW), RWORK(*), SB(N), + + SX(N), X(N) + INTEGER IA(NELT), IGWK(LIGW), IWORK(*), JA(NELT) +C .. Subroutine Arguments .. + EXTERNAL MATVEC, MSOLVE +C .. Local Scalars .. + DOUBLE PRECISION BNRM, RHOL, SUM + INTEGER I, IFLAG, JPRE, JSCAL, KMP, LDL, LGMR, LHES, LQ, LR, LV, + + LW, LXL, LZ, LZM1, MAXL, MAXLP1, NMS, NMSL, NRMAX, NRSTS +C .. External Functions .. + DOUBLE PRECISION D1MACH, DNRM2 + EXTERNAL D1MACH, DNRM2 +C .. External Subroutines .. + EXTERNAL DCOPY, DPIGMR +C .. Intrinsic Functions .. + INTRINSIC SQRT +C***FIRST EXECUTABLE STATEMENT DGMRES + IERR = 0 +C ------------------------------------------------------------------ +C Load method parameters with user values or defaults. +C ------------------------------------------------------------------ + MAXL = IGWK(1) + IF (MAXL .EQ. 0) MAXL = 10 + IF (MAXL .GT. N) MAXL = N + KMP = IGWK(2) + IF (KMP .EQ. 0) KMP = MAXL + IF (KMP .GT. MAXL) KMP = MAXL + JSCAL = IGWK(3) + JPRE = IGWK(4) +C Check for valid value of ITOL. + IF( (ITOL.LT.0) .OR. ((ITOL.GT.3).AND.(ITOL.NE.11)) ) GOTO 650 +C Check for consistent values of ITOL and JPRE. + IF( ITOL.EQ.1 .AND. JPRE.LT.0 ) GOTO 650 + IF( ITOL.EQ.2 .AND. JPRE.GE.0 ) GOTO 650 + NRMAX = IGWK(5) + IF( NRMAX.EQ.0 ) NRMAX = 10 +C If NRMAX .eq. -1, then set NRMAX = 0 to turn off restarting. + IF( NRMAX.EQ.-1 ) NRMAX = 0 +C If input value of TOL is zero, set it to its default value. + IF( TOL.EQ.0.0D0 ) TOL = 500*D1MACH(3) +C +C Initialize counters. + ITER = 0 + NMS = 0 + NRSTS = 0 +C ------------------------------------------------------------------ +C Form work array segment pointers. +C ------------------------------------------------------------------ + MAXLP1 = MAXL + 1 + LV = 1 + LR = LV + N*MAXLP1 + LHES = LR + N + 1 + LQ = LHES + MAXL*MAXLP1 + LDL = LQ + 2*MAXL + LW = LDL + N + LXL = LW + N + LZ = LXL + N +C +C Load IGWK(6) with required minimum length of the RGWK array. + IGWK(6) = LZ + N - 1 + IF( LZ+N-1.GT.LRGW ) GOTO 640 +C ------------------------------------------------------------------ +C Calculate scaled-preconditioned norm of RHS vector b. +C ------------------------------------------------------------------ + IF (JPRE .LT. 0) THEN + CALL MSOLVE(N, B, RGWK(LR), NELT, IA, JA, A, ISYM, + $ RWORK, IWORK) + NMS = NMS + 1 + ELSE + CALL DCOPY(N, B, 1, RGWK(LR), 1) + ENDIF + IF( JSCAL.EQ.2 .OR. JSCAL.EQ.3 ) THEN + SUM = 0 + DO 10 I = 1,N + SUM = SUM + (RGWK(LR-1+I)*SB(I))**2 + 10 CONTINUE + BNRM = SQRT(SUM) + ELSE + BNRM = DNRM2(N,RGWK(LR),1) + ENDIF +C ------------------------------------------------------------------ +C Calculate initial residual. +C ------------------------------------------------------------------ + CALL MATVEC(N, X, RGWK(LR), NELT, IA, JA, A, ISYM) + DO 50 I = 1,N + RGWK(LR-1+I) = B(I) - RGWK(LR-1+I) + 50 CONTINUE +C ------------------------------------------------------------------ +C If performing restarting, then load the residual into the +C correct location in the RGWK array. +C ------------------------------------------------------------------ + 100 CONTINUE + IF( NRSTS.GT.NRMAX ) GOTO 610 + IF( NRSTS.GT.0 ) THEN +C Copy the current residual to a different location in the RGWK +C array. + CALL DCOPY(N, RGWK(LDL), 1, RGWK(LR), 1) + ENDIF +C ------------------------------------------------------------------ +C Use the DPIGMR algorithm to solve the linear system A*Z = R. +C ------------------------------------------------------------------ + CALL DPIGMR(N, RGWK(LR), SB, SX, JSCAL, MAXL, MAXLP1, KMP, + $ NRSTS, JPRE, MATVEC, MSOLVE, NMSL, RGWK(LZ), RGWK(LV), + $ RGWK(LHES), RGWK(LQ), LGMR, RWORK, IWORK, RGWK(LW), + $ RGWK(LDL), RHOL, NRMAX, B, BNRM, X, RGWK(LXL), ITOL, + $ TOL, NELT, IA, JA, A, ISYM, IUNIT, IFLAG, ERR) + ITER = ITER + LGMR + NMS = NMS + NMSL +C +C Increment X by the current approximate solution Z of A*Z = R. +C + LZM1 = LZ - 1 + DO 110 I = 1,N + X(I) = X(I) + RGWK(LZM1+I) + 110 CONTINUE + IF( IFLAG.EQ.0 ) GOTO 600 + IF( IFLAG.EQ.1 ) THEN + NRSTS = NRSTS + 1 + GOTO 100 + ENDIF + IF( IFLAG.EQ.2 ) GOTO 620 +C ------------------------------------------------------------------ +C All returns are made through this section. +C ------------------------------------------------------------------ +C The iteration has converged. +C + 600 CONTINUE + IGWK(7) = NMS + RGWK(1) = RHOL + IERR = 0 + RETURN +C +C Max number((NRMAX+1)*MAXL) of linear iterations performed. + 610 CONTINUE + IGWK(7) = NMS + RGWK(1) = RHOL + IERR = 1 + RETURN +C +C GMRES failed to reduce last residual in MAXL iterations. +C The iteration has stalled. + 620 CONTINUE + IGWK(7) = NMS + RGWK(1) = RHOL + IERR = 2 + RETURN +C Error return. Insufficient length for RGWK array. + 640 CONTINUE + ERR = TOL + IERR = -1 + RETURN +C Error return. Inconsistent ITOL and JPRE values. + 650 CONTINUE + ERR = TOL + IERR = -2 + RETURN +C------------- LAST LINE OF DGMRES FOLLOWS ---------------------------- + END diff --git a/dep/slatec/dhels.f b/dep/slatec/dhels.f new file mode 100644 index 00000000..ce3c8c9a --- /dev/null +++ b/dep/slatec/dhels.f @@ -0,0 +1,98 @@ +*DECK DHELS + SUBROUTINE DHELS (A, LDA, N, Q, B) +C***BEGIN PROLOGUE DHELS +C***SUBSIDIARY +C***PURPOSE Internal routine for DGMRES. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SHELS-S, DHELS-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C This routine is extracted from the LINPACK routine SGESL with +C changes due to the fact that A is an upper Hessenberg matrix. +C +C DHELS solves the least squares problem: +C +C MIN(B-A*X,B-A*X) +C +C using the factors computed by DHEQR. +C +C *Usage: +C INTEGER LDA, N +C DOUBLE PRECISION A(LDA,N), Q(2*N), B(N+1) +C +C CALL DHELS(A, LDA, N, Q, B) +C +C *Arguments: +C A :IN Double Precision A(LDA,N) +C The output from DHEQR which contains the upper +C triangular factor R in the QR decomposition of A. +C LDA :IN Integer +C The leading dimension of the array A. +C N :IN Integer +C A is originally an (N+1) by N matrix. +C Q :IN Double Precision Q(2*N) +C The coefficients of the N Givens rotations +C used in the QR factorization of A. +C B :INOUT Double Precision B(N+1) +C On input, B is the right hand side vector. +C On output, B is the solution vector X. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED DAXPY +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910502 Added C***FIRST EXECUTABLE STATEMENT line. (FNF) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920511 Added complete declaration section. (WRB) +C***END PROLOGUE DHELS +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + INTEGER LDA, N +C .. Array Arguments .. + DOUBLE PRECISION A(LDA,*), B(*), Q(*) +C .. Local Scalars .. + DOUBLE PRECISION C, S, T, T1, T2 + INTEGER IQ, K, KB, KP1 +C .. External Subroutines .. + EXTERNAL DAXPY +C***FIRST EXECUTABLE STATEMENT DHELS +C +C Minimize(B-A*X,B-A*X). First form Q*B. +C + DO 20 K = 1, N + KP1 = K + 1 + IQ = 2*(K-1) + 1 + C = Q(IQ) + S = Q(IQ+1) + T1 = B(K) + T2 = B(KP1) + B(K) = C*T1 - S*T2 + B(KP1) = S*T1 + C*T2 + 20 CONTINUE +C +C Now solve R*X = Q*B. +C + DO 40 KB = 1, N + K = N + 1 - KB + B(K) = B(K)/A(K,K) + T = -B(K) + CALL DAXPY(K-1, T, A(1,K), 1, B(1), 1) + 40 CONTINUE + RETURN +C------------- LAST LINE OF DHELS FOLLOWS ---------------------------- + END diff --git a/dep/slatec/dheqr.f b/dep/slatec/dheqr.f new file mode 100644 index 00000000..0c485a73 --- /dev/null +++ b/dep/slatec/dheqr.f @@ -0,0 +1,178 @@ +*DECK DHEQR + SUBROUTINE DHEQR (A, LDA, N, Q, INFO, IJOB) +C***BEGIN PROLOGUE DHEQR +C***SUBSIDIARY +C***PURPOSE Internal routine for DGMRES. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SHEQR-S, DHEQR-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C This routine performs a QR decomposition of an upper +C Hessenberg matrix A using Givens rotations. There are two +C options available: 1) Performing a fresh decomposition 2) +C updating the QR factors by adding a row and a column to the +C matrix A. +C +C *Usage: +C INTEGER LDA, N, INFO, IJOB +C DOUBLE PRECISION A(LDA,N), Q(2*N) +C +C CALL DHEQR(A, LDA, N, Q, INFO, IJOB) +C +C *Arguments: +C A :INOUT Double Precision A(LDA,N) +C On input, the matrix to be decomposed. +C On output, the upper triangular matrix R. +C The factorization can be written Q*A = R, where +C Q is a product of Givens rotations and R is upper +C triangular. +C LDA :IN Integer +C The leading dimension of the array A. +C N :IN Integer +C A is an (N+1) by N Hessenberg matrix. +C Q :OUT Double Precision Q(2*N) +C The factors c and s of each Givens rotation used +C in decomposing A. +C INFO :OUT Integer +C = 0 normal value. +C = K if A(K,K) .eq. 0.0 . This is not an error +C condition for this subroutine, but it does +C indicate that DHELS will divide by zero +C if called. +C IJOB :IN Integer +C = 1 means that a fresh decomposition of the +C matrix A is desired. +C .ge. 2 means that the current decomposition of A +C will be updated by the addition of a row +C and a column. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920511 Added complete declaration section. (WRB) +C***END PROLOGUE DHEQR +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + INTEGER IJOB, INFO, LDA, N +C .. Array Arguments .. + DOUBLE PRECISION A(LDA,*), Q(*) +C .. Local Scalars .. + DOUBLE PRECISION C, S, T, T1, T2 + INTEGER I, IQ, J, K, KM1, KP1, NM1 +C .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +C***FIRST EXECUTABLE STATEMENT DHEQR + IF (IJOB .GT. 1) GO TO 70 +C ------------------------------------------------------------------- +C A new factorization is desired. +C ------------------------------------------------------------------- +C QR decomposition without pivoting. +C + INFO = 0 + DO 60 K = 1, N + KM1 = K - 1 + KP1 = K + 1 +C +C Compute K-th column of R. +C First, multiply the K-th column of A by the previous +C K-1 Givens rotations. +C + IF (KM1 .LT. 1) GO TO 20 + DO 10 J = 1, KM1 + I = 2*(J-1) + 1 + T1 = A(J,K) + T2 = A(J+1,K) + C = Q(I) + S = Q(I+1) + A(J,K) = C*T1 - S*T2 + A(J+1,K) = S*T1 + C*T2 + 10 CONTINUE +C +C Compute Givens components C and S. +C + 20 CONTINUE + IQ = 2*KM1 + 1 + T1 = A(K,K) + T2 = A(KP1,K) + IF( T2.EQ.0.0D0 ) THEN + C = 1 + S = 0 + ELSEIF( ABS(T2).GE.ABS(T1) ) THEN + T = T1/T2 + S = -1.0D0/SQRT(1.0D0+T*T) + C = -S*T + ELSE + T = T2/T1 + C = 1.0D0/SQRT(1.0D0+T*T) + S = -C*T + ENDIF + Q(IQ) = C + Q(IQ+1) = S + A(K,K) = C*T1 - S*T2 + IF( A(K,K).EQ.0.0D0 ) INFO = K + 60 CONTINUE + RETURN +C ------------------------------------------------------------------- +C The old factorization of a will be updated. A row and a +C column has been added to the matrix A. N by N-1 is now +C the old size of the matrix. +C ------------------------------------------------------------------- + 70 CONTINUE + NM1 = N - 1 +C ------------------------------------------------------------------- +C Multiply the new column by the N previous Givens rotations. +C ------------------------------------------------------------------- + DO 100 K = 1,NM1 + I = 2*(K-1) + 1 + T1 = A(K,N) + T2 = A(K+1,N) + C = Q(I) + S = Q(I+1) + A(K,N) = C*T1 - S*T2 + A(K+1,N) = S*T1 + C*T2 + 100 CONTINUE +C ------------------------------------------------------------------- +C Complete update of decomposition by forming last Givens +C rotation, and multiplying it times the column +C vector(A(N,N),A(NP1,N)). +C ------------------------------------------------------------------- + INFO = 0 + T1 = A(N,N) + T2 = A(N+1,N) + IF ( T2.EQ.0.0D0 ) THEN + C = 1 + S = 0 + ELSEIF( ABS(T2).GE.ABS(T1) ) THEN + T = T1/T2 + S = -1.0D0/SQRT(1.0D0+T*T) + C = -S*T + ELSE + T = T2/T1 + C = 1.0D0/SQRT(1.0D0+T*T) + S = -C*T + ENDIF + IQ = 2*N - 1 + Q(IQ) = C + Q(IQ+1) = S + A(N,N) = C*T1 - S*T2 + IF (A(N,N) .EQ. 0.0D0) INFO = N + RETURN +C------------- LAST LINE OF DHEQR FOLLOWS ---------------------------- + END diff --git a/dep/slatec/dorth.f b/dep/slatec/dorth.f new file mode 100644 index 00000000..5e616267 --- /dev/null +++ b/dep/slatec/dorth.f @@ -0,0 +1,125 @@ +*DECK DORTH + SUBROUTINE DORTH (VNEW, V, HES, N, LL, LDHES, KMP, SNORMW) +C***BEGIN PROLOGUE DORTH +C***SUBSIDIARY +C***PURPOSE Internal routine for DGMRES. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SORTH-S, DORTH-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C This routine orthogonalizes the vector VNEW against the +C previous KMP vectors in the V array. It uses a modified +C Gram-Schmidt orthogonalization procedure with conditional +C reorthogonalization. +C +C *Usage: +C INTEGER N, LL, LDHES, KMP +C DOUBLE PRECISION VNEW(N), V(N,LL), HES(LDHES,LL), SNORMW +C +C CALL DORTH(VNEW, V, HES, N, LL, LDHES, KMP, SNORMW) +C +C *Arguments: +C VNEW :INOUT Double Precision VNEW(N) +C On input, the vector of length N containing a scaled +C product of the Jacobian and the vector V(*,LL). +C On output, the new vector orthogonal to V(*,i0) to V(*,LL), +C where i0 = max(1, LL-KMP+1). +C V :IN Double Precision V(N,LL) +C The N x LL array containing the previous LL +C orthogonal vectors V(*,1) to V(*,LL). +C HES :INOUT Double Precision HES(LDHES,LL) +C On input, an LL x LL upper Hessenberg matrix containing, +C in HES(I,K), K.lt.LL, the scaled inner products of +C A*V(*,K) and V(*,i). +C On return, column LL of HES is filled in with +C the scaled inner products of A*V(*,LL) and V(*,i). +C N :IN Integer +C The order of the matrix A, and the length of VNEW. +C LL :IN Integer +C The current order of the matrix HES. +C LDHES :IN Integer +C The leading dimension of the HES array. +C KMP :IN Integer +C The number of previous vectors the new vector VNEW +C must be made orthogonal to (KMP .le. MAXL). +C SNORMW :OUT DOUBLE PRECISION +C Scalar containing the l-2 norm of VNEW. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED DAXPY, DDOT, DNRM2 +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920511 Added complete declaration section. (WRB) +C***END PROLOGUE DORTH +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + DOUBLE PRECISION SNORMW + INTEGER KMP, LDHES, LL, N +C .. Array Arguments .. + DOUBLE PRECISION HES(LDHES,*), V(N,*), VNEW(*) +C .. Local Scalars .. + DOUBLE PRECISION ARG, SUMDSQ, TEM, VNRM + INTEGER I, I0 +C .. External Functions .. + DOUBLE PRECISION DDOT, DNRM2 + EXTERNAL DDOT, DNRM2 +C .. External Subroutines .. + EXTERNAL DAXPY +C .. Intrinsic Functions .. + INTRINSIC MAX, SQRT +C***FIRST EXECUTABLE STATEMENT DORTH +C +C Get norm of unaltered VNEW for later use. +C + VNRM = DNRM2(N, VNEW, 1) +C ------------------------------------------------------------------- +C Perform the modified Gram-Schmidt procedure on VNEW =A*V(LL). +C Scaled inner products give new column of HES. +C Projections of earlier vectors are subtracted from VNEW. +C ------------------------------------------------------------------- + I0 = MAX(1,LL-KMP+1) + DO 10 I = I0,LL + HES(I,LL) = DDOT(N, V(1,I), 1, VNEW, 1) + TEM = -HES(I,LL) + CALL DAXPY(N, TEM, V(1,I), 1, VNEW, 1) + 10 CONTINUE +C ------------------------------------------------------------------- +C Compute SNORMW = norm of VNEW. If VNEW is small compared +C to its input value (in norm), then reorthogonalize VNEW to +C V(*,1) through V(*,LL). Correct if relative correction +C exceeds 1000*(unit roundoff). Finally, correct SNORMW using +C the dot products involved. +C ------------------------------------------------------------------- + SNORMW = DNRM2(N, VNEW, 1) + IF (VNRM + 0.001D0*SNORMW .NE. VNRM) RETURN + SUMDSQ = 0 + DO 30 I = I0,LL + TEM = -DDOT(N, V(1,I), 1, VNEW, 1) + IF (HES(I,LL) + 0.001D0*TEM .EQ. HES(I,LL)) GO TO 30 + HES(I,LL) = HES(I,LL) - TEM + CALL DAXPY(N, TEM, V(1,I), 1, VNEW, 1) + SUMDSQ = SUMDSQ + TEM**2 + 30 CONTINUE + IF (SUMDSQ .EQ. 0.0D0) RETURN + ARG = MAX(0.0D0,SNORMW**2 - SUMDSQ) + SNORMW = SQRT(ARG) +C + RETURN +C------------- LAST LINE OF DORTH FOLLOWS ---------------------------- + END diff --git a/dep/slatec/dpigmr.f b/dep/slatec/dpigmr.f new file mode 100644 index 00000000..957ab097 --- /dev/null +++ b/dep/slatec/dpigmr.f @@ -0,0 +1,439 @@ +*DECK DPIGMR + SUBROUTINE DPIGMR (N, R0, SR, SZ, JSCAL, MAXL, MAXLP1, KMP, NRSTS, + + JPRE, MATVEC, MSOLVE, NMSL, Z, V, HES, Q, LGMR, RPAR, IPAR, WK, + + DL, RHOL, NRMAX, B, BNRM, X, XL, ITOL, TOL, NELT, IA, JA, A, + + ISYM, IUNIT, IFLAG, ERR) +C***BEGIN PROLOGUE DPIGMR +C***SUBSIDIARY +C***PURPOSE Internal routine for DGMRES. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SPIGMR-S, DPIGMR-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C This routine solves the linear system A * Z = R0 using a +C scaled preconditioned version of the generalized minimum +C residual method. An initial guess of Z = 0 is assumed. +C +C *Usage: +C INTEGER N, JSCAL, MAXL, MAXLP1, KMP, NRSTS, JPRE, NMSL, LGMR +C INTEGER IPAR(USER DEFINED), NRMAX, ITOL, NELT, IA(NELT), JA(NELT) +C INTEGER ISYM, IUNIT, IFLAG +C DOUBLE PRECISION R0(N), SR(N), SZ(N), Z(N), V(N,MAXLP1), +C $ HES(MAXLP1,MAXL), Q(2*MAXL), RPAR(USER DEFINED), +C $ WK(N), DL(N), RHOL, B(N), BNRM, X(N), XL(N), +C $ TOL, A(NELT), ERR +C EXTERNAL MATVEC, MSOLVE +C +C CALL DPIGMR(N, R0, SR, SZ, JSCAL, MAXL, MAXLP1, KMP, +C $ NRSTS, JPRE, MATVEC, MSOLVE, NMSL, Z, V, HES, Q, LGMR, +C $ RPAR, IPAR, WK, DL, RHOL, NRMAX, B, BNRM, X, XL, +C $ ITOL, TOL, NELT, IA, JA, A, ISYM, IUNIT, IFLAG, ERR) +C +C *Arguments: +C N :IN Integer +C The order of the matrix A, and the lengths +C of the vectors SR, SZ, R0 and Z. +C R0 :IN Double Precision R0(N) +C R0 = the right hand side of the system A*Z = R0. +C R0 is also used as workspace when computing +C the final approximation. +C (R0 is the same as V(*,MAXL+1) in the call to DPIGMR.) +C SR :IN Double Precision SR(N) +C SR is a vector of length N containing the non-zero +C elements of the diagonal scaling matrix for R0. +C SZ :IN Double Precision SZ(N) +C SZ is a vector of length N containing the non-zero +C elements of the diagonal scaling matrix for Z. +C JSCAL :IN Integer +C A flag indicating whether arrays SR and SZ are used. +C JSCAL=0 means SR and SZ are not used and the +C algorithm will perform as if all +C SR(i) = 1 and SZ(i) = 1. +C JSCAL=1 means only SZ is used, and the algorithm +C performs as if all SR(i) = 1. +C JSCAL=2 means only SR is used, and the algorithm +C performs as if all SZ(i) = 1. +C JSCAL=3 means both SR and SZ are used. +C MAXL :IN Integer +C The maximum allowable order of the matrix H. +C MAXLP1 :IN Integer +C MAXPL1 = MAXL + 1, used for dynamic dimensioning of HES. +C KMP :IN Integer +C The number of previous vectors the new vector VNEW +C must be made orthogonal to. (KMP .le. MAXL) +C NRSTS :IN Integer +C Counter for the number of restarts on the current +C call to DGMRES. If NRSTS .gt. 0, then the residual +C R0 is already scaled, and so scaling of it is +C not necessary. +C JPRE :IN Integer +C Preconditioner type flag. +C MATVEC :EXT External. +C Name of a routine which performs the matrix vector multiply +C Y = A*X given A and X. The name of the MATVEC routine must +C be declared external in the calling program. The calling +C sequence to MATVEC is: +C CALL MATVEC(N, X, Y, NELT, IA, JA, A, ISYM) +C where N is the number of unknowns, Y is the product A*X +C upon return, X is an input vector, and NELT is the number of +C non-zeros in the SLAP IA, JA, A storage for the matrix A. +C ISYM is a flag which, if non-zero, denotes that A is +C symmetric and only the lower or upper triangle is stored. +C MSOLVE :EXT External. +C Name of the routine which solves a linear system Mz = r for +C z given r with the preconditioning matrix M (M is supplied via +C RPAR and IPAR arrays. The name of the MSOLVE routine must +C be declared external in the calling program. The calling +C sequence to MSOLVE is: +C CALL MSOLVE(N, R, Z, NELT, IA, JA, A, ISYM, RPAR, IPAR) +C Where N is the number of unknowns, R is the right-hand side +C vector and Z is the solution upon return. NELT, IA, JA, A and +C ISYM are defined as below. RPAR is a double precision array +C that can be used to pass necessary preconditioning information +C and/or workspace to MSOLVE. IPAR is an integer work array +C for the same purpose as RPAR. +C NMSL :OUT Integer +C The number of calls to MSOLVE. +C Z :OUT Double Precision Z(N) +C The final computed approximation to the solution +C of the system A*Z = R0. +C V :OUT Double Precision V(N,MAXLP1) +C The N by (LGMR+1) array containing the LGMR +C orthogonal vectors V(*,1) to V(*,LGMR). +C HES :OUT Double Precision HES(MAXLP1,MAXL) +C The upper triangular factor of the QR decomposition +C of the (LGMR+1) by LGMR upper Hessenberg matrix whose +C entries are the scaled inner-products of A*V(*,I) +C and V(*,K). +C Q :OUT Double Precision Q(2*MAXL) +C A double precision array of length 2*MAXL containing the +C components of the Givens rotations used in the QR +C decomposition of HES. It is loaded in DHEQR and used in +C DHELS. +C LGMR :OUT Integer +C The number of iterations performed and +C the current order of the upper Hessenberg +C matrix HES. +C RPAR :IN Double Precision RPAR(USER DEFINED) +C Double Precision workspace passed directly to the MSOLVE +C routine. +C IPAR :IN Integer IPAR(USER DEFINED) +C Integer workspace passed directly to the MSOLVE routine. +C WK :IN Double Precision WK(N) +C A double precision work array of length N used by routines +C MATVEC and MSOLVE. +C DL :INOUT Double Precision DL(N) +C On input, a double precision work array of length N used for +C calculation of the residual norm RHO when the method is +C incomplete (KMP.lt.MAXL), and/or when using restarting. +C On output, the scaled residual vector RL. It is only loaded +C when performing restarts of the Krylov iteration. +C RHOL :OUT Double Precision +C A double precision scalar containing the norm of the final +C residual. +C NRMAX :IN Integer +C The maximum number of restarts of the Krylov iteration. +C NRMAX .gt. 0 means restarting is active, while +C NRMAX = 0 means restarting is not being used. +C B :IN Double Precision B(N) +C The right hand side of the linear system A*X = b. +C BNRM :IN Double Precision +C The scaled norm of b. +C X :IN Double Precision X(N) +C The current approximate solution as of the last +C restart. +C XL :IN Double Precision XL(N) +C An array of length N used to hold the approximate +C solution X(L) when ITOL=11. +C ITOL :IN Integer +C A flag to indicate the type of convergence criterion +C used. See the driver for its description. +C TOL :IN Double Precision +C The tolerance on residuals R0-A*Z in scaled norm. +C NELT :IN Integer +C The length of arrays IA, JA and A. +C IA :IN Integer IA(NELT) +C An integer array of length NELT containing matrix data. +C It is passed directly to the MATVEC and MSOLVE routines. +C JA :IN Integer JA(NELT) +C An integer array of length NELT containing matrix data. +C It is passed directly to the MATVEC and MSOLVE routines. +C A :IN Double Precision A(NELT) +C A double precision array of length NELT containing matrix +C data. It is passed directly to the MATVEC and MSOLVE routines. +C ISYM :IN Integer +C A flag to indicate symmetric matrix storage. +C If ISYM=0, all non-zero entries of the matrix are +C stored. If ISYM=1, the matrix is symmetric and +C only the upper or lower triangular part is stored. +C IUNIT :IN Integer +C The i/o unit number for writing intermediate residual +C norm values. +C IFLAG :OUT Integer +C An integer error flag.. +C 0 means convergence in LGMR iterations, LGMR.le.MAXL. +C 1 means the convergence test did not pass in MAXL +C iterations, but the residual norm is .lt. norm(R0), +C and so Z is computed. +C 2 means the convergence test did not pass in MAXL +C iterations, residual .ge. norm(R0), and Z = 0. +C ERR :OUT Double Precision. +C Error estimate of error in final approximate solution, as +C defined by ITOL. +C +C *Cautions: +C This routine will attempt to write to the Fortran logical output +C unit IUNIT, if IUNIT .ne. 0. Thus, the user must make sure that +C this logical unit is attached to a file or terminal before calling +C this routine with a non-zero value for IUNIT. This routine does +C not check for the validity of a non-zero IUNIT unit number. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED DAXPY, DCOPY, DHELS, DHEQR, DNRM2, DORTH, DRLCAL, +C DSCAL, ISDGMR +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910502 Removed MATVEC and MSOLVE from ROUTINES CALLED list. (FNF) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920511 Added complete declaration section. (WRB) +C***END PROLOGUE DPIGMR +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + DOUBLE PRECISION BNRM, ERR, RHOL, TOL + INTEGER IFLAG, ISYM, ITOL, IUNIT, JPRE, JSCAL, KMP, LGMR, MAXL, + + MAXLP1, N, NELT, NMSL, NRMAX, NRSTS +C .. Array Arguments .. + DOUBLE PRECISION A(NELT), B(*), DL(*), HES(MAXLP1,*), Q(*), R0(*), + + RPAR(*), SR(*), SZ(*), V(N,*), WK(*), X(*), + + XL(*), Z(*) + INTEGER IA(NELT), IPAR(*), JA(NELT) +C .. Subroutine Arguments .. + EXTERNAL MATVEC, MSOLVE +C .. Local Scalars .. + DOUBLE PRECISION C, DLNRM, PROD, R0NRM, RHO, S, SNORMW, TEM + INTEGER I, I2, INFO, IP1, ITER, ITMAX, J, K, LL, LLP1 +C .. External Functions .. + DOUBLE PRECISION DNRM2 + INTEGER ISDGMR + EXTERNAL DNRM2, ISDGMR +C .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DHELS, DHEQR, DORTH, DRLCAL, DSCAL +C .. Intrinsic Functions .. + INTRINSIC ABS +C***FIRST EXECUTABLE STATEMENT DPIGMR +C +C Zero out the Z array. +C + DO 5 I = 1,N + Z(I) = 0 + 5 CONTINUE +C + IFLAG = 0 + LGMR = 0 + NMSL = 0 +C Load ITMAX, the maximum number of iterations. + ITMAX =(NRMAX+1)*MAXL +C ------------------------------------------------------------------- +C The initial residual is the vector R0. +C Apply left precon. if JPRE < 0 and this is not a restart. +C Apply scaling to R0 if JSCAL = 2 or 3. +C ------------------------------------------------------------------- + IF ((JPRE .LT. 0) .AND.(NRSTS .EQ. 0)) THEN + CALL DCOPY(N, R0, 1, WK, 1) + CALL MSOLVE(N, WK, R0, NELT, IA, JA, A, ISYM, RPAR, IPAR) + NMSL = NMSL + 1 + ENDIF + IF (((JSCAL.EQ.2) .OR.(JSCAL.EQ.3)) .AND.(NRSTS.EQ.0)) THEN + DO 10 I = 1,N + V(I,1) = R0(I)*SR(I) + 10 CONTINUE + ELSE + DO 20 I = 1,N + V(I,1) = R0(I) + 20 CONTINUE + ENDIF + R0NRM = DNRM2(N, V, 1) + ITER = NRSTS*MAXL +C +C Call stopping routine ISDGMR. +C + IF (ISDGMR(N, B, X, XL, NELT, IA, JA, A, ISYM, MSOLVE, + $ NMSL, ITOL, TOL, ITMAX, ITER, ERR, IUNIT, V(1,1), Z, WK, + $ RPAR, IPAR, R0NRM, BNRM, SR, SZ, JSCAL, + $ KMP, LGMR, MAXL, MAXLP1, V, Q, SNORMW, PROD, R0NRM, + $ HES, JPRE) .NE. 0) RETURN + TEM = 1.0D0/R0NRM + CALL DSCAL(N, TEM, V(1,1), 1) +C +C Zero out the HES array. +C + DO 50 J = 1,MAXL + DO 40 I = 1,MAXLP1 + HES(I,J) = 0 + 40 CONTINUE + 50 CONTINUE +C ------------------------------------------------------------------- +C Main loop to compute the vectors V(*,2) to V(*,MAXL). +C The running product PROD is needed for the convergence test. +C ------------------------------------------------------------------- + PROD = 1 + DO 90 LL = 1,MAXL + LGMR = LL +C ------------------------------------------------------------------- +C Unscale the current V(LL) and store in WK. Call routine +C MSOLVE to compute(M-inverse)*WK, where M is the +C preconditioner matrix. Save the answer in Z. Call routine +C MATVEC to compute VNEW = A*Z, where A is the the system +C matrix. save the answer in V(LL+1). Scale V(LL+1). Call +C routine DORTH to orthogonalize the new vector VNEW = +C V(*,LL+1). Call routine DHEQR to update the factors of HES. +C ------------------------------------------------------------------- + IF ((JSCAL .EQ. 1) .OR.(JSCAL .EQ. 3)) THEN + DO 60 I = 1,N + WK(I) = V(I,LL)/SZ(I) + 60 CONTINUE + ELSE + CALL DCOPY(N, V(1,LL), 1, WK, 1) + ENDIF + IF (JPRE .GT. 0) THEN + CALL MSOLVE(N, WK, Z, NELT, IA, JA, A, ISYM, RPAR, IPAR) + NMSL = NMSL + 1 + CALL MATVEC(N, Z, V(1,LL+1), NELT, IA, JA, A, ISYM) + ELSE + CALL MATVEC(N, WK, V(1,LL+1), NELT, IA, JA, A, ISYM) + ENDIF + IF (JPRE .LT. 0) THEN + CALL DCOPY(N, V(1,LL+1), 1, WK, 1) + CALL MSOLVE(N,WK,V(1,LL+1),NELT,IA,JA,A,ISYM,RPAR,IPAR) + NMSL = NMSL + 1 + ENDIF + IF ((JSCAL .EQ. 2) .OR.(JSCAL .EQ. 3)) THEN + DO 65 I = 1,N + V(I,LL+1) = V(I,LL+1)*SR(I) + 65 CONTINUE + ENDIF + CALL DORTH(V(1,LL+1), V, HES, N, LL, MAXLP1, KMP, SNORMW) + HES(LL+1,LL) = SNORMW + CALL DHEQR(HES, MAXLP1, LL, Q, INFO, LL) + IF (INFO .EQ. LL) GO TO 120 +C ------------------------------------------------------------------- +C Update RHO, the estimate of the norm of the residual R0-A*ZL. +C If KMP < MAXL, then the vectors V(*,1),...,V(*,LL+1) are not +C necessarily orthogonal for LL > KMP. The vector DL must then +C be computed, and its norm used in the calculation of RHO. +C ------------------------------------------------------------------- + PROD = PROD*Q(2*LL) + RHO = ABS(PROD*R0NRM) + IF ((LL.GT.KMP) .AND.(KMP.LT.MAXL)) THEN + IF (LL .EQ. KMP+1) THEN + CALL DCOPY(N, V(1,1), 1, DL, 1) + DO 75 I = 1,KMP + IP1 = I + 1 + I2 = I*2 + S = Q(I2) + C = Q(I2-1) + DO 70 K = 1,N + DL(K) = S*DL(K) + C*V(K,IP1) + 70 CONTINUE + 75 CONTINUE + ENDIF + S = Q(2*LL) + C = Q(2*LL-1)/SNORMW + LLP1 = LL + 1 + DO 80 K = 1,N + DL(K) = S*DL(K) + C*V(K,LLP1) + 80 CONTINUE + DLNRM = DNRM2(N, DL, 1) + RHO = RHO*DLNRM + ENDIF + RHOL = RHO +C ------------------------------------------------------------------- +C Test for convergence. If passed, compute approximation ZL. +C If failed and LL < MAXL, then continue iterating. +C ------------------------------------------------------------------- + ITER = NRSTS*MAXL + LGMR + IF (ISDGMR(N, B, X, XL, NELT, IA, JA, A, ISYM, MSOLVE, + $ NMSL, ITOL, TOL, ITMAX, ITER, ERR, IUNIT, DL, Z, WK, + $ RPAR, IPAR, RHOL, BNRM, SR, SZ, JSCAL, + $ KMP, LGMR, MAXL, MAXLP1, V, Q, SNORMW, PROD, R0NRM, + $ HES, JPRE) .NE. 0) GO TO 200 + IF (LL .EQ. MAXL) GO TO 100 +C ------------------------------------------------------------------- +C Rescale so that the norm of V(1,LL+1) is one. +C ------------------------------------------------------------------- + TEM = 1.0D0/SNORMW + CALL DSCAL(N, TEM, V(1,LL+1), 1) + 90 CONTINUE + 100 CONTINUE + IF (RHO .LT. R0NRM) GO TO 150 + 120 CONTINUE + IFLAG = 2 +C +C Load approximate solution with zero. +C + DO 130 I = 1,N + Z(I) = 0 + 130 CONTINUE + RETURN + 150 IFLAG = 1 +C +C Tolerance not met, but residual norm reduced. +C + IF (NRMAX .GT. 0) THEN +C +C If performing restarting (NRMAX > 0) calculate the residual +C vector RL and store it in the DL array. If the incomplete +C version is being used (KMP < MAXL) then DL has already been +C calculated up to a scaling factor. Use DRLCAL to calculate +C the scaled residual vector. +C + CALL DRLCAL(N, KMP, MAXL, MAXL, V, Q, DL, SNORMW, PROD, + $ R0NRM) + ENDIF +C ------------------------------------------------------------------- +C Compute the approximation ZL to the solution. Since the +C vector Z was used as workspace, and the initial guess +C of the linear iteration is zero, Z must be reset to zero. +C ------------------------------------------------------------------- + 200 CONTINUE + LL = LGMR + LLP1 = LL + 1 + DO 210 K = 1,LLP1 + R0(K) = 0 + 210 CONTINUE + R0(1) = R0NRM + CALL DHELS(HES, MAXLP1, LL, Q, R0) + DO 220 K = 1,N + Z(K) = 0 + 220 CONTINUE + DO 230 I = 1,LL + CALL DAXPY(N, R0(I), V(1,I), 1, Z, 1) + 230 CONTINUE + IF ((JSCAL .EQ. 1) .OR.(JSCAL .EQ. 3)) THEN + DO 240 I = 1,N + Z(I) = Z(I)/SZ(I) + 240 CONTINUE + ENDIF + IF (JPRE .GT. 0) THEN + CALL DCOPY(N, Z, 1, WK, 1) + CALL MSOLVE(N, WK, Z, NELT, IA, JA, A, ISYM, RPAR, IPAR) + NMSL = NMSL + 1 + ENDIF + RETURN +C------------- LAST LINE OF DPIGMR FOLLOWS ---------------------------- + END diff --git a/dep/slatec/drlcal.f b/dep/slatec/drlcal.f new file mode 100644 index 00000000..1430a24b --- /dev/null +++ b/dep/slatec/drlcal.f @@ -0,0 +1,116 @@ +*DECK DRLCAL + SUBROUTINE DRLCAL (N, KMP, LL, MAXL, V, Q, RL, SNORMW, PROD, + + R0NRM) +C***BEGIN PROLOGUE DRLCAL +C***SUBSIDIARY +C***PURPOSE Internal routine for DGMRES. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SRLCAL-S, DRLCAL-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C This routine calculates the scaled residual RL from the +C V(I)'s. +C *Usage: +C INTEGER N, KMP, LL, MAXL +C DOUBLE PRECISION V(N,LL), Q(2*MAXL), RL(N), SNORMW, PROD, R0NORM +C +C CALL DRLCAL(N, KMP, LL, MAXL, V, Q, RL, SNORMW, PROD, R0NRM) +C +C *Arguments: +C N :IN Integer +C The order of the matrix A, and the lengths +C of the vectors SR, SZ, R0 and Z. +C KMP :IN Integer +C The number of previous V vectors the new vector VNEW +C must be made orthogonal to. (KMP .le. MAXL) +C LL :IN Integer +C The current dimension of the Krylov subspace. +C MAXL :IN Integer +C The maximum dimension of the Krylov subspace. +C V :IN Double Precision V(N,LL) +C The N x LL array containing the orthogonal vectors +C V(*,1) to V(*,LL). +C Q :IN Double Precision Q(2*MAXL) +C A double precision array of length 2*MAXL containing the +C components of the Givens rotations used in the QR +C decomposition of HES. It is loaded in DHEQR and used in +C DHELS. +C RL :OUT Double Precision RL(N) +C The residual vector RL. This is either SB*(B-A*XL) if +C not preconditioning or preconditioning on the right, +C or SB*(M-inverse)*(B-A*XL) if preconditioning on the +C left. +C SNORMW :IN Double Precision +C Scale factor. +C PROD :IN Double Precision +C The product s1*s2*...*sl = the product of the sines of the +C Givens rotations used in the QR factorization of +C the Hessenberg matrix HES. +C R0NRM :IN Double Precision +C The scaled norm of initial residual R0. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED DCOPY, DSCAL +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920511 Added complete declaration section. (WRB) +C***END PROLOGUE DRLCAL +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + DOUBLE PRECISION PROD, R0NRM, SNORMW + INTEGER KMP, LL, MAXL, N +C .. Array Arguments .. + DOUBLE PRECISION Q(*), RL(N), V(N,*) +C .. Local Scalars .. + DOUBLE PRECISION C, S, TEM + INTEGER I, I2, IP1, K, LLM1, LLP1 +C .. External Subroutines .. + EXTERNAL DCOPY, DSCAL +C***FIRST EXECUTABLE STATEMENT DRLCAL + IF (KMP .EQ. MAXL) THEN +C +C calculate RL. Start by copying V(*,1) into RL. +C + CALL DCOPY(N, V(1,1), 1, RL, 1) + LLM1 = LL - 1 + DO 20 I = 1,LLM1 + IP1 = I + 1 + I2 = I*2 + S = Q(I2) + C = Q(I2-1) + DO 10 K = 1,N + RL(K) = S*RL(K) + C*V(K,IP1) + 10 CONTINUE + 20 CONTINUE + S = Q(2*LL) + C = Q(2*LL-1)/SNORMW + LLP1 = LL + 1 + DO 30 K = 1,N + RL(K) = S*RL(K) + C*V(K,LLP1) + 30 CONTINUE + ENDIF +C +C When KMP < MAXL, RL vector already partially calculated. +C Scale RL by R0NRM*PROD to obtain the residual RL. +C + TEM = R0NRM*PROD + CALL DSCAL(N, TEM, RL, 1) + RETURN +C------------- LAST LINE OF DRLCAL FOLLOWS ---------------------------- + END diff --git a/dep/slatec/dsort.f b/dep/slatec/dsort.f new file mode 100644 index 00000000..2fe023a4 --- /dev/null +++ b/dep/slatec/dsort.f @@ -0,0 +1,324 @@ +*DECK DSORT + SUBROUTINE DSORT (DX, DY, N, KFLAG) +C***BEGIN PROLOGUE DSORT +C***PURPOSE Sort an array and optionally make the same interchanges in +C an auxiliary array. The array may be sorted in increasing +C or decreasing order. A slightly modified QUICKSORT +C algorithm is used. +C***LIBRARY SLATEC +C***CATEGORY N6A2B +C***TYPE DOUBLE PRECISION (SSORT-S, DSORT-D, ISORT-I) +C***KEYWORDS SINGLETON QUICKSORT, SORT, SORTING +C***AUTHOR Jones, R. E., (SNLA) +C Wisniewski, J. A., (SNLA) +C***DESCRIPTION +C +C DSORT sorts array DX and optionally makes the same interchanges in +C array DY. The array DX may be sorted in increasing order or +C decreasing order. A slightly modified quicksort algorithm is used. +C +C Description of Parameters +C DX - array of values to be sorted (usually abscissas) +C DY - array to be (optionally) carried along +C N - number of values in array DX to be sorted +C KFLAG - control parameter +C = 2 means sort DX in increasing order and carry DY along. +C = 1 means sort DX in increasing order (ignoring DY) +C = -1 means sort DX in decreasing order (ignoring DY) +C = -2 means sort DX in decreasing order and carry DY along. +C +C***REFERENCES R. C. Singleton, Algorithm 347, An efficient algorithm +C for sorting with minimal storage, Communications of +C the ACM, 12, 3 (1969), pp. 185-187. +C***ROUTINES CALLED XERMSG +C***REVISION HISTORY (YYMMDD) +C 761101 DATE WRITTEN +C 761118 Modified to use the Singleton quicksort algorithm. (JAW) +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890831 Modified array declarations. (WRB) +C 891009 Removed unreferenced statement labels. (WRB) +C 891024 Changed category. (WRB) +C 891024 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ) +C 901012 Declared all variables; changed X,Y to DX,DY; changed +C code to parallel SSORT. (M. McClain) +C 920501 Reformatted the REFERENCES section. (DWL, WRB) +C 920519 Clarified error messages. (DWL) +C 920801 Declarations section rebuilt and code restructured to use +C IF-THEN-ELSE-ENDIF. (RWC, WRB) +C***END PROLOGUE DSORT +C .. Scalar Arguments .. + INTEGER KFLAG, N +C .. Array Arguments .. + DOUBLE PRECISION DX(*), DY(*) +C .. Local Scalars .. + DOUBLE PRECISION R, T, TT, TTY, TY + INTEGER I, IJ, J, K, KK, L, M, NN +C .. Local Arrays .. + INTEGER IL(21), IU(21) +C .. External Subroutines .. + EXTERNAL XERMSG +C .. Intrinsic Functions .. + INTRINSIC ABS, INT +C***FIRST EXECUTABLE STATEMENT DSORT + NN = N + IF (NN .LT. 1) THEN + CALL XERMSG ('SLATEC', 'DSORT', + + 'The number of values to be sorted is not positive.', 1, 1) + RETURN + ENDIF +C + KK = ABS(KFLAG) + IF (KK.NE.1 .AND. KK.NE.2) THEN + CALL XERMSG ('SLATEC', 'DSORT', + + 'The sort control parameter, K, is not 2, 1, -1, or -2.', 2, + + 1) + RETURN + ENDIF +C +C Alter array DX to get decreasing order if needed +C + IF (KFLAG .LE. -1) THEN + DO 10 I=1,NN + DX(I) = -DX(I) + 10 CONTINUE + ENDIF +C + IF (KK .EQ. 2) GO TO 100 +C +C Sort DX only +C + M = 1 + I = 1 + J = NN + R = 0.375D0 +C + 20 IF (I .EQ. J) GO TO 60 + IF (R .LE. 0.5898437D0) THEN + R = R+3.90625D-2 + ELSE + R = R-0.21875D0 + ENDIF +C + 30 K = I +C +C Select a central element of the array and save it in location T +C + IJ = I + INT((J-I)*R) + T = DX(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (DX(I) .GT. T) THEN + DX(IJ) = DX(I) + DX(I) = T + T = DX(IJ) + ENDIF + L = J +C +C If last element of array is less than than T, interchange with T +C + IF (DX(J) .LT. T) THEN + DX(IJ) = DX(J) + DX(J) = T + T = DX(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (DX(I) .GT. T) THEN + DX(IJ) = DX(I) + DX(I) = T + T = DX(IJ) + ENDIF + ENDIF +C +C Find an element in the second half of the array which is smaller +C than T +C + 40 L = L-1 + IF (DX(L) .GT. T) GO TO 40 +C +C Find an element in the first half of the array which is greater +C than T +C + 50 K = K+1 + IF (DX(K) .LT. T) GO TO 50 +C +C Interchange these elements +C + IF (K .LE. L) THEN + TT = DX(L) + DX(L) = DX(K) + DX(K) = TT + GO TO 40 + ENDIF +C +C Save upper and lower subscripts of the array yet to be sorted +C + IF (L-I .GT. J-K) THEN + IL(M) = I + IU(M) = L + I = K + M = M+1 + ELSE + IL(M) = K + IU(M) = J + J = L + M = M+1 + ENDIF + GO TO 70 +C +C Begin again on another portion of the unsorted array +C + 60 M = M-1 + IF (M .EQ. 0) GO TO 190 + I = IL(M) + J = IU(M) +C + 70 IF (J-I .GE. 1) GO TO 30 + IF (I .EQ. 1) GO TO 20 + I = I-1 +C + 80 I = I+1 + IF (I .EQ. J) GO TO 60 + T = DX(I+1) + IF (DX(I) .LE. T) GO TO 80 + K = I +C + 90 DX(K+1) = DX(K) + K = K-1 + IF (T .LT. DX(K)) GO TO 90 + DX(K+1) = T + GO TO 80 +C +C Sort DX and carry DY along +C + 100 M = 1 + I = 1 + J = NN + R = 0.375D0 +C + 110 IF (I .EQ. J) GO TO 150 + IF (R .LE. 0.5898437D0) THEN + R = R+3.90625D-2 + ELSE + R = R-0.21875D0 + ENDIF +C + 120 K = I +C +C Select a central element of the array and save it in location T +C + IJ = I + INT((J-I)*R) + T = DX(IJ) + TY = DY(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (DX(I) .GT. T) THEN + DX(IJ) = DX(I) + DX(I) = T + T = DX(IJ) + DY(IJ) = DY(I) + DY(I) = TY + TY = DY(IJ) + ENDIF + L = J +C +C If last element of array is less than T, interchange with T +C + IF (DX(J) .LT. T) THEN + DX(IJ) = DX(J) + DX(J) = T + T = DX(IJ) + DY(IJ) = DY(J) + DY(J) = TY + TY = DY(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (DX(I) .GT. T) THEN + DX(IJ) = DX(I) + DX(I) = T + T = DX(IJ) + DY(IJ) = DY(I) + DY(I) = TY + TY = DY(IJ) + ENDIF + ENDIF +C +C Find an element in the second half of the array which is smaller +C than T +C + 130 L = L-1 + IF (DX(L) .GT. T) GO TO 130 +C +C Find an element in the first half of the array which is greater +C than T +C + 140 K = K+1 + IF (DX(K) .LT. T) GO TO 140 +C +C Interchange these elements +C + IF (K .LE. L) THEN + TT = DX(L) + DX(L) = DX(K) + DX(K) = TT + TTY = DY(L) + DY(L) = DY(K) + DY(K) = TTY + GO TO 130 + ENDIF +C +C Save upper and lower subscripts of the array yet to be sorted +C + IF (L-I .GT. J-K) THEN + IL(M) = I + IU(M) = L + I = K + M = M+1 + ELSE + IL(M) = K + IU(M) = J + J = L + M = M+1 + ENDIF + GO TO 160 +C +C Begin again on another portion of the unsorted array +C + 150 M = M-1 + IF (M .EQ. 0) GO TO 190 + I = IL(M) + J = IU(M) +C + 160 IF (J-I .GE. 1) GO TO 120 + IF (I .EQ. 1) GO TO 110 + I = I-1 +C + 170 I = I+1 + IF (I .EQ. J) GO TO 150 + T = DX(I+1) + TY = DY(I+1) + IF (DX(I) .LE. T) GO TO 170 + K = I +C + 180 DX(K+1) = DX(K) + DY(K+1) = DY(K) + K = K-1 + IF (T .LT. DX(K)) GO TO 180 + DX(K+1) = T + DY(K+1) = TY + GO TO 170 +C +C Clean up +C + 190 IF (KFLAG .LE. -1) THEN + DO 200 I=1,NN + DX(I) = -DX(I) + 200 CONTINUE + ENDIF + RETURN + END diff --git a/dep/slatec/dxlcal.f b/dep/slatec/dxlcal.f new file mode 100644 index 00000000..cb18d521 --- /dev/null +++ b/dep/slatec/dxlcal.f @@ -0,0 +1,185 @@ +*DECK DXLCAL + SUBROUTINE DXLCAL (N, LGMR, X, XL, ZL, HES, MAXLP1, Q, V, R0NRM, + + WK, SZ, JSCAL, JPRE, MSOLVE, NMSL, RPAR, IPAR, NELT, IA, JA, A, + + ISYM) +C***BEGIN PROLOGUE DXLCAL +C***SUBSIDIARY +C***PURPOSE Internal routine for DGMRES. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (SXLCAL-S, DXLCAL-D) +C***KEYWORDS GENERALIZED MINIMUM RESIDUAL, ITERATIVE PRECONDITION, +C NON-SYMMETRIC LINEAR SYSTEM, SLAP, SPARSE +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C This routine computes the solution XL, the current DGMRES +C iterate, given the V(I)'s and the QR factorization of the +C Hessenberg matrix HES. This routine is only called when +C ITOL=11. +C +C *Usage: +C INTEGER N, LGMR, MAXLP1, JSCAL, JPRE, NMSL, IPAR(USER DEFINED) +C INTEGER NELT, IA(NELT), JA(NELT), ISYM +C DOUBLE PRECISION X(N), XL(N), ZL(N), HES(MAXLP1,MAXL), Q(2*MAXL), +C $ V(N,MAXLP1), R0NRM, WK(N), SZ(N), +C $ RPAR(USER DEFINED), A(NELT) +C EXTERNAL MSOLVE +C +C CALL DXLCAL(N, LGMR, X, XL, ZL, HES, MAXLP1, Q, V, R0NRM, +C $ WK, SZ, JSCAL, JPRE, MSOLVE, NMSL, RPAR, IPAR, +C $ NELT, IA, JA, A, ISYM) +C +C *Arguments: +C N :IN Integer +C The order of the matrix A, and the lengths +C of the vectors SR, SZ, R0 and Z. +C LGMR :IN Integer +C The number of iterations performed and +C the current order of the upper Hessenberg +C matrix HES. +C X :IN Double Precision X(N) +C The current approximate solution as of the last restart. +C XL :OUT Double Precision XL(N) +C An array of length N used to hold the approximate +C solution X(L). +C Warning: XL and ZL are the same array in the calling routine. +C ZL :IN Double Precision ZL(N) +C An array of length N used to hold the approximate +C solution Z(L). +C HES :IN Double Precision HES(MAXLP1,MAXL) +C The upper triangular factor of the QR decomposition +C of the (LGMR+1) by LGMR upper Hessenberg matrix whose +C entries are the scaled inner-products of A*V(*,i) and V(*,k). +C MAXLP1 :IN Integer +C MAXLP1 = MAXL + 1, used for dynamic dimensioning of HES. +C MAXL is the maximum allowable order of the matrix HES. +C Q :IN Double Precision Q(2*MAXL) +C A double precision array of length 2*MAXL containing the +C components of the Givens rotations used in the QR +C decomposition of HES. It is loaded in DHEQR. +C V :IN Double Precision V(N,MAXLP1) +C The N by(LGMR+1) array containing the LGMR +C orthogonal vectors V(*,1) to V(*,LGMR). +C R0NRM :IN Double Precision +C The scaled norm of the initial residual for the +C current call to DPIGMR. +C WK :IN Double Precision WK(N) +C A double precision work array of length N. +C SZ :IN Double Precision SZ(N) +C A vector of length N containing the non-zero +C elements of the diagonal scaling matrix for Z. +C JSCAL :IN Integer +C A flag indicating whether arrays SR and SZ are used. +C JSCAL=0 means SR and SZ are not used and the +C algorithm will perform as if all +C SR(i) = 1 and SZ(i) = 1. +C JSCAL=1 means only SZ is used, and the algorithm +C performs as if all SR(i) = 1. +C JSCAL=2 means only SR is used, and the algorithm +C performs as if all SZ(i) = 1. +C JSCAL=3 means both SR and SZ are used. +C JPRE :IN Integer +C The preconditioner type flag. +C MSOLVE :EXT External. +C Name of the routine which solves a linear system Mz = r for +C z given r with the preconditioning matrix M (M is supplied via +C RPAR and IPAR arrays. The name of the MSOLVE routine must +C be declared external in the calling program. The calling +C sequence to MSOLVE is: +C CALL MSOLVE(N, R, Z, NELT, IA, JA, A, ISYM, RPAR, IPAR) +C Where N is the number of unknowns, R is the right-hand side +C vector and Z is the solution upon return. NELT, IA, JA, A and +C ISYM are defined as below. RPAR is a double precision array +C that can be used to pass necessary preconditioning information +C and/or workspace to MSOLVE. IPAR is an integer work array +C for the same purpose as RPAR. +C NMSL :IN Integer +C The number of calls to MSOLVE. +C RPAR :IN Double Precision RPAR(USER DEFINED) +C Double Precision workspace passed directly to the MSOLVE +C routine. +C IPAR :IN Integer IPAR(USER DEFINED) +C Integer workspace passed directly to the MSOLVE routine. +C NELT :IN Integer +C The length of arrays IA, JA and A. +C IA :IN Integer IA(NELT) +C An integer array of length NELT containing matrix data. +C It is passed directly to the MATVEC and MSOLVE routines. +C JA :IN Integer JA(NELT) +C An integer array of length NELT containing matrix data. +C It is passed directly to the MATVEC and MSOLVE routines. +C A :IN Double Precision A(NELT) +C A double precision array of length NELT containing matrix +C data. +C It is passed directly to the MATVEC and MSOLVE routines. +C ISYM :IN Integer +C A flag to indicate symmetric matrix storage. +C If ISYM=0, all non-zero entries of the matrix are +C stored. If ISYM=1, the matrix is symmetric and +C only the upper or lower triangular part is stored. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED DAXPY, DCOPY, DHELS +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910502 Removed MSOLVE from ROUTINES CALLED list. (FNF) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920511 Added complete declaration section. (WRB) +C***END PROLOGUE DXLCAL +C The following is for optimized compilation on LLNL/LTSS Crays. +CLLL. OPTIMIZE +C .. Scalar Arguments .. + DOUBLE PRECISION R0NRM + INTEGER ISYM, JPRE, JSCAL, LGMR, MAXLP1, N, NELT, NMSL +C .. Array Arguments .. + DOUBLE PRECISION A(NELT), HES(MAXLP1,*), Q(*), RPAR(*), SZ(*), + + V(N,*), WK(N), X(N), XL(N), ZL(N) + INTEGER IA(NELT), IPAR(*), JA(NELT) +C .. Subroutine Arguments .. + EXTERNAL MSOLVE +C .. Local Scalars .. + INTEGER I, K, LL, LLP1 +C .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DHELS +C***FIRST EXECUTABLE STATEMENT DXLCAL + LL = LGMR + LLP1 = LL + 1 + DO 10 K = 1,LLP1 + WK(K) = 0 + 10 CONTINUE + WK(1) = R0NRM + CALL DHELS(HES, MAXLP1, LL, Q, WK) + DO 20 K = 1,N + ZL(K) = 0 + 20 CONTINUE + DO 30 I = 1,LL + CALL DAXPY(N, WK(I), V(1,I), 1, ZL, 1) + 30 CONTINUE + IF ((JSCAL .EQ. 1) .OR.(JSCAL .EQ. 3)) THEN + DO 40 K = 1,N + ZL(K) = ZL(K)/SZ(K) + 40 CONTINUE + ENDIF + IF (JPRE .GT. 0) THEN + CALL DCOPY(N, ZL, 1, WK, 1) + CALL MSOLVE(N, WK, ZL, NELT, IA, JA, A, ISYM, RPAR, IPAR) + NMSL = NMSL + 1 + ENDIF +C calculate XL from X and ZL. + DO 50 K = 1,N + XL(K) = X(K) + ZL(K) + 50 CONTINUE + RETURN +C------------- LAST LINE OF DXLCAL FOLLOWS ---------------------------- + END diff --git a/dep/slatec/fdump.f b/dep/slatec/fdump.f new file mode 100644 index 00000000..1f44a57a --- /dev/null +++ b/dep/slatec/fdump.f @@ -0,0 +1,31 @@ +*DECK FDUMP + SUBROUTINE FDUMP +C***BEGIN PROLOGUE FDUMP +C***PURPOSE Symbolic dump (should be locally written). +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3 +C***TYPE ALL (FDUMP-A) +C***KEYWORDS ERROR, XERMSG +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C ***Note*** Machine Dependent Routine +C FDUMP is intended to be replaced by a locally written +C version which produces a symbolic dump. Failing this, +C it should be replaced by a version which prints the +C subprogram nesting list. Note that this dump must be +C printed on each of up to five files, as indicated by the +C XGETUA routine. See XSETUA and XGETUA for details. +C +C Written by Ron Jones, with SLATEC Common Math Library Subcommittee +C +C***REFERENCES (NONE) +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C***END PROLOGUE FDUMP +C***FIRST EXECUTABLE STATEMENT FDUMP + RETURN + END diff --git a/dep/slatec/i1mach.f b/dep/slatec/i1mach.f new file mode 100644 index 00000000..ad04e7b0 --- /dev/null +++ b/dep/slatec/i1mach.f @@ -0,0 +1,888 @@ +*DECK I1MACH + INTEGER FUNCTION I1MACH (I) +C***BEGIN PROLOGUE I1MACH +C***PURPOSE Return integer machine dependent constants. +C***LIBRARY SLATEC +C***CATEGORY R1 +C***TYPE INTEGER (I1MACH-I) +C***KEYWORDS MACHINE CONSTANTS +C***AUTHOR Fox, P. A., (Bell Labs) +C Hall, A. D., (Bell Labs) +C Schryer, N. L., (Bell Labs) +C***DESCRIPTION +C +C I1MACH can be used to obtain machine-dependent parameters for the +C local machine environment. It is a function subprogram with one +C (input) argument and can be referenced as follows: +C +C K = I1MACH(I) +C +C where I=1,...,16. The (output) value of K above is determined by +C the (input) value of I. The results for various values of I are +C discussed below. +C +C I/O unit numbers: +C I1MACH( 1) = the standard input unit. +C I1MACH( 2) = the standard output unit. +C I1MACH( 3) = the standard punch unit. +C I1MACH( 4) = the standard error message unit. +C +C Words: +C I1MACH( 5) = the number of bits per integer storage unit. +C I1MACH( 6) = the number of characters per integer storage unit. +C +C Integers: +C assume integers are represented in the S-digit, base-A form +C +C sign ( X(S-1)*A**(S-1) + ... + X(1)*A + X(0) ) +C +C where 0 .LE. X(I) .LT. A for I=0,...,S-1. +C I1MACH( 7) = A, the base. +C I1MACH( 8) = S, the number of base-A digits. +C I1MACH( 9) = A**S - 1, the largest magnitude. +C +C Floating-Point Numbers: +C Assume floating-point numbers are represented in the T-digit, +C base-B form +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, +C 0 .LT. X(1), and EMIN .LE. E .LE. EMAX. +C I1MACH(10) = B, the base. +C +C Single-Precision: +C I1MACH(11) = T, the number of base-B digits. +C I1MACH(12) = EMIN, the smallest exponent E. +C I1MACH(13) = EMAX, the largest exponent E. +C +C Double-Precision: +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, the desired +C set of DATA statements should be activated by removing the C from +C column 1. Also, the values of I1MACH(1) - I1MACH(4) should be +C checked for consistency with the local operating system. +C +C***REFERENCES P. A. Fox, A. D. Hall and N. L. Schryer, Framework for +C a portable library, ACM Transactions on Mathematical +C Software 4, 2 (June 1978), pp. 177-188. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 750101 DATE WRITTEN +C 891012 Added VAX G-floating constants. (WRB) +C 891012 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900618 Added DEC RISC constants. (WRB) +C 900723 Added IBM RS 6000 constants. (WRB) +C 901009 Correct I1MACH(7) for IBM Mainframes. Should be 2 not 16. +C (RWC) +C 910710 Added HP 730 constants. (SMR) +C 911114 Added Convex IEEE constants. (WRB) +C 920121 Added SUN -r8 compiler option constants. (WRB) +C 920229 Added Touchstone Delta i860 constants. (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C 920625 Added Convex -p8 and -pd8 compiler option constants. +C (BKS, WRB) +C 930201 Added DEC Alpha and SGI constants. (RWC and WRB) +C 930618 Corrected I1MACH(5) for Convex -p8 and -pd8 compiler +C options. (DWL, RWC and WRB). +C***END PROLOGUE I1MACH +C + INTEGER IMACH(16),OUTPUT + SAVE IMACH + EQUIVALENCE (IMACH(4),OUTPUT) +C +C MACHINE CONSTANTS FOR THE AMIGA +C ABSOFT COMPILER +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1022 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE APOLLO +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 129 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1025 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM +C +C DATA IMACH( 1) / 7 / +C DATA IMACH( 2) / 2 / +C DATA IMACH( 3) / 2 / +C DATA IMACH( 4) / 2 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 33 / +C DATA IMACH( 9) / Z1FFFFFFFF / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -256 / +C DATA IMACH(13) / 255 / +C DATA IMACH(14) / 60 / +C DATA IMACH(15) / -256 / +C DATA IMACH(16) / 255 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 48 / +C DATA IMACH( 6) / 6 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 39 / +C DATA IMACH( 9) / O0007777777777777 / +C DATA IMACH(10) / 8 / +C DATA IMACH(11) / 13 / +C DATA IMACH(12) / -50 / +C DATA IMACH(13) / 76 / +C DATA IMACH(14) / 26 / +C DATA IMACH(15) / -50 / +C DATA IMACH(16) / 76 / +C +C MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 48 / +C DATA IMACH( 6) / 6 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 39 / +C DATA IMACH( 9) / O0007777777777777 / +C DATA IMACH(10) / 8 / +C DATA IMACH(11) / 13 / +C DATA IMACH(12) / -50 / +C DATA IMACH(13) / 76 / +C DATA IMACH(14) / 26 / +C DATA IMACH(15) / -32754 / +C DATA IMACH(16) / 32780 / +C +C MACHINE CONSTANTS FOR THE CDC 170/180 SERIES USING NOS/VE +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 8 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 9223372036854775807 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -4095 / +C DATA IMACH(13) / 4094 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -4095 / +C DATA IMACH(16) / 4094 / +C +C MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6LOUTPUT/ +C DATA IMACH( 5) / 60 / +C DATA IMACH( 6) / 10 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 48 / +C DATA IMACH( 9) / 00007777777777777777B / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -929 / +C DATA IMACH(13) / 1070 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -929 / +C DATA IMACH(16) / 1069 / +C +C MACHINE CONSTANTS FOR THE CELERITY C1260 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 0 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / Z'7FFFFFFF' / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1022 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fn COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -fi COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -p8 COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 9223372036854775807 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 53 / +C DATA IMACH(12) / -1023 / +C DATA IMACH(13) / 1023 / +C DATA IMACH(14) / 113 / +C DATA IMACH(15) / -16383 / +C DATA IMACH(16) / 16383 / +C +C MACHINE CONSTANTS FOR THE CONVEX +C USING THE -pd8 COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 9223372036854775807 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 53 / +C DATA IMACH(12) / -1023 / +C DATA IMACH(13) / 1023 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE CRAY +C USING THE 46 BIT INTEGER COMPILER OPTION +C +C DATA IMACH( 1) / 100 / +C DATA IMACH( 2) / 101 / +C DATA IMACH( 3) / 102 / +C DATA IMACH( 4) / 101 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 8 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 46 / +C DATA IMACH( 9) / 1777777777777777B / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -8189 / +C DATA IMACH(13) / 8190 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -8099 / +C DATA IMACH(16) / 8190 / +C +C MACHINE CONSTANTS FOR THE CRAY +C USING THE 64 BIT INTEGER COMPILER OPTION +C +C DATA IMACH( 1) / 100 / +C DATA IMACH( 2) / 101 / +C DATA IMACH( 3) / 102 / +C DATA IMACH( 4) / 101 / +C DATA IMACH( 5) / 64 / +C DATA IMACH( 6) / 8 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 63 / +C DATA IMACH( 9) / 777777777777777777777B / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 47 / +C DATA IMACH(12) / -8189 / +C DATA IMACH(13) / 8190 / +C DATA IMACH(14) / 94 / +C DATA IMACH(15) / -8099 / +C DATA IMACH(16) / 8190 / +C +C MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200 +C +C DATA IMACH( 1) / 11 / +C DATA IMACH( 2) / 12 / +C DATA IMACH( 3) / 8 / +C DATA IMACH( 4) / 10 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 16 / +C DATA IMACH(11) / 6 / +C DATA IMACH(12) / -64 / +C DATA IMACH(13) / 63 / +C DATA IMACH(14) / 14 / +C DATA IMACH(15) / -64 / +C DATA IMACH(16) / 63 / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING G_FLOAT +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE DEC ALPHA +C USING IEEE_FLOAT +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE DEC RISC +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE DEC VAX +C USING D_FLOATING +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE DEC VAX +C USING G_FLOATING +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1023 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE ELXSI 6400 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 32 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1022 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE HARRIS 220 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 0 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 24 / +C DATA IMACH( 6) / 3 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 23 / +C DATA IMACH( 9) / 8388607 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 23 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 38 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HONEYWELL 600/6000 SERIES +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 43 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 6 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / O377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 63 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HP 730 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C 3 WORD DOUBLE PRECISION OPTION WITH FTN4 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 4 / +C DATA IMACH( 4) / 1 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 23 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 39 / +C DATA IMACH(15) / -128 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HP 2100 +C 4 WORD DOUBLE PRECISION OPTION WITH FTN4 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 4 / +C DATA IMACH( 4) / 1 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 23 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 55 / +C DATA IMACH(15) / -128 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE HP 9000 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 7 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 32 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -126 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1015 / +C DATA IMACH(16) / 1017 / +C +C MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, +C THE XEROX SIGMA 5/7/9, THE SEL SYSTEMS 85/86, AND +C THE PERKIN ELMER (INTERDATA) 7/32. +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 7 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / Z7FFFFFFF / +C DATA IMACH(10) / 16 / +C DATA IMACH(11) / 6 / +C DATA IMACH(12) / -64 / +C DATA IMACH(13) / 63 / +C DATA IMACH(14) / 14 / +C DATA IMACH(15) / -64 / +C DATA IMACH(16) / 63 / +C +C MACHINE CONSTANTS FOR THE IBM PC +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 0 / +C DATA IMACH( 4) / 0 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE IBM RS 6000 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 0 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE INTEL i860 +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR) +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 5 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / "377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 54 / +C DATA IMACH(15) / -101 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR) +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 5 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / "377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 62 / +C DATA IMACH(15) / -128 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 32-BIT INTEGER ARITHMETIC. +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR PDP-11 FORTRAN SUPPORTING +C 16-BIT INTEGER ARITHMETIC. +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 5 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C MACHINE CONSTANTS FOR THE SILICON GRAPHICS +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE SUN +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -125 / +C DATA IMACH(13) / 128 / +C DATA IMACH(14) / 53 / +C DATA IMACH(15) / -1021 / +C DATA IMACH(16) / 1024 / +C +C MACHINE CONSTANTS FOR THE SUN +C USING THE -r8 COMPILER OPTION +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 6 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 32 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 31 / +C DATA IMACH( 9) / 2147483647 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 53 / +C DATA IMACH(12) / -1021 / +C DATA IMACH(13) / 1024 / +C DATA IMACH(14) / 113 / +C DATA IMACH(15) / -16381 / +C DATA IMACH(16) / 16384 / +C +C MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES FTN COMPILER +C +C DATA IMACH( 1) / 5 / +C DATA IMACH( 2) / 6 / +C DATA IMACH( 3) / 1 / +C DATA IMACH( 4) / 6 / +C DATA IMACH( 5) / 36 / +C DATA IMACH( 6) / 4 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 35 / +C DATA IMACH( 9) / O377777777777 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 27 / +C DATA IMACH(12) / -128 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 60 / +C DATA IMACH(15) / -1024 / +C DATA IMACH(16) / 1023 / +C +C MACHINE CONSTANTS FOR THE Z80 MICROPROCESSOR +C +C DATA IMACH( 1) / 1 / +C DATA IMACH( 2) / 1 / +C DATA IMACH( 3) / 0 / +C DATA IMACH( 4) / 1 / +C DATA IMACH( 5) / 16 / +C DATA IMACH( 6) / 2 / +C DATA IMACH( 7) / 2 / +C DATA IMACH( 8) / 15 / +C DATA IMACH( 9) / 32767 / +C DATA IMACH(10) / 2 / +C DATA IMACH(11) / 24 / +C DATA IMACH(12) / -127 / +C DATA IMACH(13) / 127 / +C DATA IMACH(14) / 56 / +C DATA IMACH(15) / -127 / +C DATA IMACH(16) / 127 / +C +C***FIRST EXECUTABLE STATEMENT I1MACH + IF (I .LT. 1 .OR. I .GT. 16) GO TO 10 +C + I1MACH = IMACH(I) + RETURN +C + 10 CONTINUE + WRITE (UNIT = OUTPUT, FMT = 9000) + 9000 FORMAT ('1ERROR 1 IN I1MACH - I OUT OF BOUNDS') +C +C CALL FDUMP +C + STOP + END diff --git a/dep/slatec/isdgmr.f b/dep/slatec/isdgmr.f new file mode 100644 index 00000000..f65bcf3a --- /dev/null +++ b/dep/slatec/isdgmr.f @@ -0,0 +1,402 @@ +*DECK ISDGMR + INTEGER FUNCTION ISDGMR (N, B, X, XL, NELT, IA, JA, A, ISYM, + + MSOLVE, NMSL, ITOL, TOL, ITMAX, ITER, ERR, IUNIT, R, Z, DZ, + + RWORK, IWORK, RNRM, BNRM, SB, SX, JSCAL, KMP, LGMR, MAXL, + + MAXLP1, V, Q, SNORMW, PROD, R0NRM, HES, JPRE) +C***BEGIN PROLOGUE ISDGMR +C***SUBSIDIARY +C***PURPOSE Generalized Minimum Residual Stop Test. +C This routine calculates the stop test for the Generalized +C Minimum RESidual (GMRES) iteration scheme. It returns a +C non-zero if the error estimate (the type of which is +C determined by ITOL) is less than the user specified +C tolerance TOL. +C***LIBRARY SLATEC (SLAP) +C***CATEGORY D2A4, D2B4 +C***TYPE DOUBLE PRECISION (ISSGMR-S, ISDGMR-D) +C***KEYWORDS GMRES, LINEAR SYSTEM, SLAP, SPARSE, STOP TEST +C***AUTHOR Brown, Peter, (LLNL), pnbrown@llnl.gov +C Hindmarsh, Alan, (LLNL), alanh@llnl.gov +C Seager, Mark K., (LLNL), seager@llnl.gov +C Lawrence Livermore National Laboratory +C PO Box 808, L-60 +C Livermore, CA 94550 (510) 423-3141 +C***DESCRIPTION +C +C *Usage: +C INTEGER N, NELT, IA(NELT), JA(NELT), ISYM, NMSL, ITOL +C INTEGER ITMAX, ITER, IUNIT, IWORK(USER DEFINED), JSCAL +C INTEGER KMP, LGMR, MAXL, MAXLP1, JPRE +C DOUBLE PRECISION B(N), X(N), XL(MAXL), A(NELT), TOL, ERR, +C $ R(N), Z(N), DZ(N), RWORK(USER DEFINED), +C $ RNRM, BNRM, SB(N), SX(N), V(N,MAXLP1), +C $ Q(2*MAXL), SNORMW, PROD, R0NRM, +C $ HES(MAXLP1,MAXL) +C EXTERNAL MSOLVE +C +C IF (ISDGMR(N, B, X, XL, NELT, IA, JA, A, ISYM, MSOLVE, +C $ NMSL, ITOL, TOL, ITMAX, ITER, ERR, IUNIT, R, Z, DZ, +C $ RWORK, IWORK, RNRM, BNRM, SB, SX, JSCAL, +C $ KMP, LGMR, MAXL, MAXLP1, V, Q, SNORMW, PROD, R0NRM, +C $ HES, JPRE) .NE. 0) THEN ITERATION DONE +C +C *Arguments: +C N :IN Integer. +C Order of the Matrix. +C B :IN Double Precision B(N). +C Right-hand-side vector. +C X :IN Double Precision X(N). +C Approximate solution vector as of the last restart. +C XL :OUT Double Precision XL(N) +C An array of length N used to hold the approximate +C solution as of the current iteration. Only computed by +C this routine when ITOL=11. +C NELT :IN Integer. +C Number of Non-Zeros stored in A. +C IA :IN Integer IA(NELT). +C JA :IN Integer JA(NELT). +C A :IN Double Precision A(NELT). +C These arrays contain the matrix data structure for A. +C It could take any form. See "Description", in the DGMRES, +C DSLUGM and DSDGMR routines for more details. +C ISYM :IN Integer. +C Flag to indicate symmetric storage format. +C If ISYM=0, all non-zero entries of the matrix are stored. +C If ISYM=1, the matrix is symmetric, and only the upper +C or lower triangle of the matrix is stored. +C MSOLVE :EXT External. +C Name of a routine which solves a linear system Mz = r for z +C given r with the preconditioning matrix M (M is supplied via +C RWORK and IWORK arrays. The name of the MSOLVE routine must +C be declared external in the calling program. The calling +C sequence to MSOLVE is: +C CALL MSOLVE(N, R, Z, NELT, IA, JA, A, ISYM, RWORK, IWORK) +C Where N is the number of unknowns, R is the right-hand side +C vector and Z is the solution upon return. NELT, IA, JA, A and +C ISYM are defined as above. RWORK is a double precision array +C that can be used to pass necessary preconditioning information +C and/or workspace to MSOLVE. IWORK is an integer work array +C for the same purpose as RWORK. +C NMSL :INOUT Integer. +C A counter for the number of calls to MSOLVE. +C ITOL :IN Integer. +C Flag to indicate the type of convergence criterion used. +C ITOL=0 Means the iteration stops when the test described +C below on the residual RL is satisfied. This is +C the "Natural Stopping Criteria" for this routine. +C Other values of ITOL cause extra, otherwise +C unnecessary, computation per iteration and are +C therefore much less efficient. +C ITOL=1 Means the iteration stops when the first test +C described below on the residual RL is satisfied, +C and there is either right or no preconditioning +C being used. +C ITOL=2 Implies that the user is using left +C preconditioning, and the second stopping criterion +C below is used. +C ITOL=3 Means the iteration stops when the third test +C described below on Minv*Residual is satisfied, and +C there is either left or no preconditioning begin +C used. +C ITOL=11 is often useful for checking and comparing +C different routines. For this case, the user must +C supply the "exact" solution or a very accurate +C approximation (one with an error much less than +C TOL) through a common block, +C COMMON /DSLBLK/ SOLN( ) +C If ITOL=11, iteration stops when the 2-norm of the +C difference between the iterative approximation and +C the user-supplied solution divided by the 2-norm +C of the user-supplied solution is less than TOL. +C Note that this requires the user to set up the +C "COMMON /DSLBLK/ SOLN(LENGTH)" in the calling +C routine. The routine with this declaration should +C be loaded before the stop test so that the correct +C length is used by the loader. This procedure is +C not standard Fortran and may not work correctly on +C your system (although it has worked on every +C system the authors have tried). If ITOL is not 11 +C then this common block is indeed standard Fortran. +C TOL :IN Double Precision. +C Convergence criterion, as described above. +C ITMAX :IN Integer. +C Maximum number of iterations. +C ITER :IN Integer. +C The iteration for which to check for convergence. +C ERR :OUT Double Precision. +C Error estimate of error in final approximate solution, as +C defined by ITOL. Letting norm() denote the Euclidean +C norm, ERR is defined as follows.. +C +C If ITOL=0, then ERR = norm(SB*(B-A*X(L)))/norm(SB*B), +C for right or no preconditioning, and +C ERR = norm(SB*(M-inverse)*(B-A*X(L)))/ +C norm(SB*(M-inverse)*B), +C for left preconditioning. +C If ITOL=1, then ERR = norm(SB*(B-A*X(L)))/norm(SB*B), +C since right or no preconditioning +C being used. +C If ITOL=2, then ERR = norm(SB*(M-inverse)*(B-A*X(L)))/ +C norm(SB*(M-inverse)*B), +C since left preconditioning is being +C used. +C If ITOL=3, then ERR = Max |(Minv*(B-A*X(L)))(i)/x(i)| +C i=1,n +C If ITOL=11, then ERR = norm(SB*(X(L)-SOLN))/norm(SB*SOLN). +C IUNIT :IN Integer. +C Unit number on which to write the error at each iteration, +C if this is desired for monitoring convergence. If unit +C number is 0, no writing will occur. +C R :INOUT Double Precision R(N). +C Work array used in calling routine. It contains +C information necessary to compute the residual RL = B-A*XL. +C Z :WORK Double Precision Z(N). +C Workspace used to hold the pseudo-residual M z = r. +C DZ :WORK Double Precision DZ(N). +C Workspace used to hold temporary vector(s). +C RWORK :WORK Double Precision RWORK(USER DEFINED). +C Double Precision array that can be used by MSOLVE. +C IWORK :WORK Integer IWORK(USER DEFINED). +C Integer array that can be used by MSOLVE. +C RNRM :IN Double Precision. +C Norm of the current residual. Type of norm depends on ITOL. +C BNRM :IN Double Precision. +C Norm of the right hand side. Type of norm depends on ITOL. +C SB :IN Double Precision SB(N). +C Scaling vector for B. +C SX :IN Double Precision SX(N). +C Scaling vector for X. +C JSCAL :IN Integer. +C Flag indicating if scaling arrays SB and SX are being +C used in the calling routine DPIGMR. +C JSCAL=0 means SB and SX are not used and the +C algorithm will perform as if all +C SB(i) = 1 and SX(i) = 1. +C JSCAL=1 means only SX is used, and the algorithm +C performs as if all SB(i) = 1. +C JSCAL=2 means only SB is used, and the algorithm +C performs as if all SX(i) = 1. +C JSCAL=3 means both SB and SX are used. +C KMP :IN Integer +C The number of previous vectors the new vector VNEW +C must be made orthogonal to. (KMP .le. MAXL) +C LGMR :IN Integer +C The number of GMRES iterations performed on the current call +C to DPIGMR (i.e., # iterations since the last restart) and +C the current order of the upper Hessenberg +C matrix HES. +C MAXL :IN Integer +C The maximum allowable order of the matrix H. +C MAXLP1 :IN Integer +C MAXPL1 = MAXL + 1, used for dynamic dimensioning of HES. +C V :IN Double Precision V(N,MAXLP1) +C The N by (LGMR+1) array containing the LGMR +C orthogonal vectors V(*,1) to V(*,LGMR). +C Q :IN Double Precision Q(2*MAXL) +C A double precision array of length 2*MAXL containing the +C components of the Givens rotations used in the QR +C decomposition of HES. +C SNORMW :IN Double Precision +C A scalar containing the scaled norm of VNEW before it +C is renormalized in DPIGMR. +C PROD :IN Double Precision +C The product s1*s2*...*sl = the product of the sines of the +C Givens rotations used in the QR factorization of the +C Hessenberg matrix HES. +C R0NRM :IN Double Precision +C The scaled norm of initial residual R0. +C HES :IN Double Precision HES(MAXLP1,MAXL) +C The upper triangular factor of the QR decomposition +C of the (LGMR+1) by LGMR upper Hessenberg matrix whose +C entries are the scaled inner-products of A*V(*,I) +C and V(*,K). +C JPRE :IN Integer +C Preconditioner type flag. +C (See description of IGWK(4) in DGMRES.) +C +C *Description +C When using the GMRES solver, the preferred value for ITOL +C is 0. This is due to the fact that when ITOL=0 the norm of +C the residual required in the stopping test is obtained for +C free, since this value is already calculated in the GMRES +C algorithm. The variable RNRM contains the appropriate +C norm, which is equal to norm(SB*(RL - A*XL)) when right or +C no preconditioning is being performed, and equal to +C norm(SB*Minv*(RL - A*XL)) when using left preconditioning. +C Here, norm() is the Euclidean norm. Nonzero values of ITOL +C require additional work to calculate the actual scaled +C residual or its scaled/preconditioned form, and/or the +C approximate solution XL. Hence, these values of ITOL will +C not be as efficient as ITOL=0. +C +C *Cautions: +C This routine will attempt to write to the Fortran logical output +C unit IUNIT, if IUNIT .ne. 0. Thus, the user must make sure that +C this logical unit is attached to a file or terminal before calling +C this routine with a non-zero value for IUNIT. This routine does +C not check for the validity of a non-zero IUNIT unit number. +C +C This routine does not verify that ITOL has a valid value. +C The calling routine should make such a test before calling +C ISDGMR, as is done in DGMRES. +C +C***SEE ALSO DGMRES +C***ROUTINES CALLED D1MACH, DCOPY, DNRM2, DRLCAL, DSCAL, DXLCAL +C***COMMON BLOCKS DSLBLK +C***REVISION HISTORY (YYMMDD) +C 890404 DATE WRITTEN +C 890404 Previous REVISION DATE +C 890915 Made changes requested at July 1989 CML Meeting. (MKS) +C 890922 Numerous changes to prologue to make closer to SLATEC +C standard. (FNF) +C 890929 Numerous changes to reduce SP/DP differences. (FNF) +C 910411 Prologue converted to Version 4.0 format. (BAB) +C 910502 Corrected conversion errors, etc. (FNF) +C 910502 Removed MSOLVE from ROUTINES CALLED list. (FNF) +C 910506 Made subsidiary to DGMRES. (FNF) +C 920407 COMMON BLOCK renamed DSLBLK. (WRB) +C 920511 Added complete declaration section. (WRB) +C 921026 Corrected D to E in output format. (FNF) +C 921113 Corrected C***CATEGORY line. (FNF) +C***END PROLOGUE ISDGMR +C .. Scalar Arguments .. + DOUBLE PRECISION BNRM, ERR, PROD, R0NRM, RNRM, SNORMW, TOL + INTEGER ISYM, ITER, ITMAX, ITOL, IUNIT, JPRE, JSCAL, KMP, LGMR, + + MAXL, MAXLP1, N, NELT, NMSL +C .. Array Arguments .. + DOUBLE PRECISION A(*), B(*), DZ(*), HES(MAXLP1, MAXL), Q(*), R(*), + + RWORK(*), SB(*), SX(*), V(N,*), X(*), XL(*), Z(*) + INTEGER IA(*), IWORK(*), JA(*) +C .. Subroutine Arguments .. + EXTERNAL MSOLVE +C .. Arrays in Common .. + DOUBLE PRECISION SOLN(1) +C .. Local Scalars .. + DOUBLE PRECISION DXNRM, FUZZ, RAT, RATMAX, SOLNRM, TEM + INTEGER I, IELMAX +C .. External Functions .. + DOUBLE PRECISION D1MACH, DNRM2 + EXTERNAL D1MACH, DNRM2 +C .. External Subroutines .. + EXTERNAL DCOPY, DRLCAL, DSCAL, DXLCAL +C .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +C .. Common blocks .. + COMMON /DSLBLK/ SOLN +C .. Save statement .. + SAVE SOLNRM +C***FIRST EXECUTABLE STATEMENT ISDGMR + ISDGMR = 0 + IF ( ITOL.EQ.0 ) THEN +C +C Use input from DPIGMR to determine if stop conditions are met. +C + ERR = RNRM/BNRM + ENDIF + IF ( (ITOL.GT.0) .AND. (ITOL.LE.3) ) THEN +C +C Use DRLCAL to calculate the scaled residual vector. +C Store answer in R. +C + IF ( LGMR.NE.0 ) CALL DRLCAL(N, KMP, LGMR, MAXL, V, Q, R, + $ SNORMW, PROD, R0NRM) + IF ( ITOL.LE.2 ) THEN +C err = ||Residual||/||RightHandSide||(2-Norms). + ERR = DNRM2(N, R, 1)/BNRM +C +C Unscale R by R0NRM*PROD when KMP < MAXL. +C + IF ( (KMP.LT.MAXL) .AND. (LGMR.NE.0) ) THEN + TEM = 1.0D0/(R0NRM*PROD) + CALL DSCAL(N, TEM, R, 1) + ENDIF + ELSEIF ( ITOL.EQ.3 ) THEN +C err = Max |(Minv*Residual)(i)/x(i)| +C When JPRE .lt. 0, R already contains Minv*Residual. + IF ( JPRE.GT.0 ) THEN + CALL MSOLVE(N, R, DZ, NELT, IA, JA, A, ISYM, RWORK, + $ IWORK) + NMSL = NMSL + 1 + ENDIF +C +C Unscale R by R0NRM*PROD when KMP < MAXL. +C + IF ( (KMP.LT.MAXL) .AND. (LGMR.NE.0) ) THEN + TEM = 1.0D0/(R0NRM*PROD) + CALL DSCAL(N, TEM, R, 1) + ENDIF +C + FUZZ = D1MACH(1) + IELMAX = 1 + RATMAX = ABS(DZ(1))/MAX(ABS(X(1)),FUZZ) + DO 25 I = 2, N + RAT = ABS(DZ(I))/MAX(ABS(X(I)),FUZZ) + IF( RAT.GT.RATMAX ) THEN + IELMAX = I + RATMAX = RAT + ENDIF + 25 CONTINUE + ERR = RATMAX + IF( RATMAX.LE.TOL ) ISDGMR = 1 + IF( IUNIT.GT.0 ) WRITE(IUNIT,1020) ITER, IELMAX, RATMAX + RETURN + ENDIF + ENDIF + IF ( ITOL.EQ.11 ) THEN +C +C Use DXLCAL to calculate the approximate solution XL. +C + IF ( (LGMR.NE.0) .AND. (ITER.GT.0) ) THEN + CALL DXLCAL(N, LGMR, X, XL, XL, HES, MAXLP1, Q, V, R0NRM, + $ DZ, SX, JSCAL, JPRE, MSOLVE, NMSL, RWORK, IWORK, + $ NELT, IA, JA, A, ISYM) + ELSEIF ( ITER.EQ.0 ) THEN +C Copy X to XL to check if initial guess is good enough. + CALL DCOPY(N, X, 1, XL, 1) + ELSE +C Return since this is the first call to DPIGMR on a restart. + RETURN + ENDIF +C + IF ((JSCAL .EQ. 0) .OR.(JSCAL .EQ. 2)) THEN +C err = ||x-TrueSolution||/||TrueSolution||(2-Norms). + IF ( ITER.EQ.0 ) SOLNRM = DNRM2(N, SOLN, 1) + DO 30 I = 1, N + DZ(I) = XL(I) - SOLN(I) + 30 CONTINUE + ERR = DNRM2(N, DZ, 1)/SOLNRM + ELSE + IF (ITER .EQ. 0) THEN + SOLNRM = 0 + DO 40 I = 1,N + SOLNRM = SOLNRM + (SX(I)*SOLN(I))**2 + 40 CONTINUE + SOLNRM = SQRT(SOLNRM) + ENDIF + DXNRM = 0 + DO 50 I = 1,N + DXNRM = DXNRM + (SX(I)*(XL(I)-SOLN(I)))**2 + 50 CONTINUE + DXNRM = SQRT(DXNRM) +C err = ||SX*(x-TrueSolution)||/||SX*TrueSolution|| (2-Norms). + ERR = DXNRM/SOLNRM + ENDIF + ENDIF +C + IF( IUNIT.NE.0 ) THEN + IF( ITER.EQ.0 ) THEN + WRITE(IUNIT,1000) N, ITOL, MAXL, KMP + ENDIF + WRITE(IUNIT,1010) ITER, RNRM/BNRM, ERR + ENDIF + IF ( ERR.LE.TOL ) ISDGMR = 1 +C + RETURN + 1000 FORMAT(' Generalized Minimum Residual(',I3,I3,') for ', + $ 'N, ITOL = ',I5, I5, + $ /' ITER',' Natural Err Est',' Error Estimate') + 1010 FORMAT(1X,I4,1X,D16.7,1X,D16.7) + 1020 FORMAT(1X,' ITER = ',I5, ' IELMAX = ',I5, + $ ' |R(IELMAX)/X(IELMAX)| = ',D12.5) +C------------- LAST LINE OF ISDGMR FOLLOWS ---------------------------- + END diff --git a/dep/slatec/isort.f b/dep/slatec/isort.f new file mode 100644 index 00000000..10e9f90a --- /dev/null +++ b/dep/slatec/isort.f @@ -0,0 +1,323 @@ +*DECK ISORT + SUBROUTINE ISORT (IX, IY, N, KFLAG) +C***BEGIN PROLOGUE ISORT +C***PURPOSE Sort an array and optionally make the same interchanges in +C an auxiliary array. The array may be sorted in increasing +C or decreasing order. A slightly modified QUICKSORT +C algorithm is used. +C***LIBRARY SLATEC +C***CATEGORY N6A2A +C***TYPE INTEGER (SSORT-S, DSORT-D, ISORT-I) +C***KEYWORDS SINGLETON QUICKSORT, SORT, SORTING +C***AUTHOR Jones, R. E., (SNLA) +C Kahaner, D. K., (NBS) +C Wisniewski, J. A., (SNLA) +C***DESCRIPTION +C +C ISORT sorts array IX and optionally makes the same interchanges in +C array IY. The array IX may be sorted in increasing order or +C decreasing order. A slightly modified quicksort algorithm is used. +C +C Description of Parameters +C IX - integer array of values to be sorted +C IY - integer array to be (optionally) carried along +C N - number of values in integer array IX to be sorted +C KFLAG - control parameter +C = 2 means sort IX in increasing order and carry IY along. +C = 1 means sort IX in increasing order (ignoring IY) +C = -1 means sort IX in decreasing order (ignoring IY) +C = -2 means sort IX in decreasing order and carry IY along. +C +C***REFERENCES R. C. Singleton, Algorithm 347, An efficient algorithm +C for sorting with minimal storage, Communications of +C the ACM, 12, 3 (1969), pp. 185-187. +C***ROUTINES CALLED XERMSG +C***REVISION HISTORY (YYMMDD) +C 761118 DATE WRITTEN +C 810801 Modified by David K. Kahaner. +C 890531 Changed all specific intrinsics to generic. (WRB) +C 890831 Modified array declarations. (WRB) +C 891009 Removed unreferenced statement labels. (WRB) +C 891009 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ) +C 901012 Declared all variables; changed X,Y to IX,IY. (M. McClain) +C 920501 Reformatted the REFERENCES section. (DWL, WRB) +C 920519 Clarified error messages. (DWL) +C 920801 Declarations section rebuilt and code restructured to use +C IF-THEN-ELSE-ENDIF. (RWC, WRB) +C***END PROLOGUE ISORT +C .. Scalar Arguments .. + INTEGER KFLAG, N +C .. Array Arguments .. + INTEGER IX(*), IY(*) +C .. Local Scalars .. + REAL R + INTEGER I, IJ, J, K, KK, L, M, NN, T, TT, TTY, TY +C .. Local Arrays .. + INTEGER IL(21), IU(21) +C .. External Subroutines .. + EXTERNAL XERMSG +C .. Intrinsic Functions .. + INTRINSIC ABS, INT +C***FIRST EXECUTABLE STATEMENT ISORT + NN = N + IF (NN .LT. 1) THEN + CALL XERMSG ('SLATEC', 'ISORT', + + 'The number of values to be sorted is not positive.', 1, 1) + RETURN + ENDIF +C + KK = ABS(KFLAG) + IF (KK.NE.1 .AND. KK.NE.2) THEN + CALL XERMSG ('SLATEC', 'ISORT', + + 'The sort control parameter, K, is not 2, 1, -1, or -2.', 2, + + 1) + RETURN + ENDIF +C +C Alter array IX to get decreasing order if needed +C + IF (KFLAG .LE. -1) THEN + DO 10 I=1,NN + IX(I) = -IX(I) + 10 CONTINUE + ENDIF +C + IF (KK .EQ. 2) GO TO 100 +C +C Sort IX only +C + M = 1 + I = 1 + J = NN + R = 0.375E0 +C + 20 IF (I .EQ. J) GO TO 60 + IF (R .LE. 0.5898437E0) THEN + R = R+3.90625E-2 + ELSE + R = R-0.21875E0 + ENDIF +C + 30 K = I +C +C Select a central element of the array and save it in location T +C + IJ = I + INT((J-I)*R) + T = IX(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (IX(I) .GT. T) THEN + IX(IJ) = IX(I) + IX(I) = T + T = IX(IJ) + ENDIF + L = J +C +C If last element of array is less than than T, interchange with T +C + IF (IX(J) .LT. T) THEN + IX(IJ) = IX(J) + IX(J) = T + T = IX(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (IX(I) .GT. T) THEN + IX(IJ) = IX(I) + IX(I) = T + T = IX(IJ) + ENDIF + ENDIF +C +C Find an element in the second half of the array which is smaller +C than T +C + 40 L = L-1 + IF (IX(L) .GT. T) GO TO 40 +C +C Find an element in the first half of the array which is greater +C than T +C + 50 K = K+1 + IF (IX(K) .LT. T) GO TO 50 +C +C Interchange these elements +C + IF (K .LE. L) THEN + TT = IX(L) + IX(L) = IX(K) + IX(K) = TT + GO TO 40 + ENDIF +C +C Save upper and lower subscripts of the array yet to be sorted +C + IF (L-I .GT. J-K) THEN + IL(M) = I + IU(M) = L + I = K + M = M+1 + ELSE + IL(M) = K + IU(M) = J + J = L + M = M+1 + ENDIF + GO TO 70 +C +C Begin again on another portion of the unsorted array +C + 60 M = M-1 + IF (M .EQ. 0) GO TO 190 + I = IL(M) + J = IU(M) +C + 70 IF (J-I .GE. 1) GO TO 30 + IF (I .EQ. 1) GO TO 20 + I = I-1 +C + 80 I = I+1 + IF (I .EQ. J) GO TO 60 + T = IX(I+1) + IF (IX(I) .LE. T) GO TO 80 + K = I +C + 90 IX(K+1) = IX(K) + K = K-1 + IF (T .LT. IX(K)) GO TO 90 + IX(K+1) = T + GO TO 80 +C +C Sort IX and carry IY along +C + 100 M = 1 + I = 1 + J = NN + R = 0.375E0 +C + 110 IF (I .EQ. J) GO TO 150 + IF (R .LE. 0.5898437E0) THEN + R = R+3.90625E-2 + ELSE + R = R-0.21875E0 + ENDIF +C + 120 K = I +C +C Select a central element of the array and save it in location T +C + IJ = I + INT((J-I)*R) + T = IX(IJ) + TY = IY(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (IX(I) .GT. T) THEN + IX(IJ) = IX(I) + IX(I) = T + T = IX(IJ) + IY(IJ) = IY(I) + IY(I) = TY + TY = IY(IJ) + ENDIF + L = J +C +C If last element of array is less than T, interchange with T +C + IF (IX(J) .LT. T) THEN + IX(IJ) = IX(J) + IX(J) = T + T = IX(IJ) + IY(IJ) = IY(J) + IY(J) = TY + TY = IY(IJ) +C +C If first element of array is greater than T, interchange with T +C + IF (IX(I) .GT. T) THEN + IX(IJ) = IX(I) + IX(I) = T + T = IX(IJ) + IY(IJ) = IY(I) + IY(I) = TY + TY = IY(IJ) + ENDIF + ENDIF +C +C Find an element in the second half of the array which is smaller +C than T +C + 130 L = L-1 + IF (IX(L) .GT. T) GO TO 130 +C +C Find an element in the first half of the array which is greater +C than T +C + 140 K = K+1 + IF (IX(K) .LT. T) GO TO 140 +C +C Interchange these elements +C + IF (K .LE. L) THEN + TT = IX(L) + IX(L) = IX(K) + IX(K) = TT + TTY = IY(L) + IY(L) = IY(K) + IY(K) = TTY + GO TO 130 + ENDIF +C +C Save upper and lower subscripts of the array yet to be sorted +C + IF (L-I .GT. J-K) THEN + IL(M) = I + IU(M) = L + I = K + M = M+1 + ELSE + IL(M) = K + IU(M) = J + J = L + M = M+1 + ENDIF + GO TO 160 +C +C Begin again on another portion of the unsorted array +C + 150 M = M-1 + IF (M .EQ. 0) GO TO 190 + I = IL(M) + J = IU(M) +C + 160 IF (J-I .GE. 1) GO TO 120 + IF (I .EQ. 1) GO TO 110 + I = I-1 +C + 170 I = I+1 + IF (I .EQ. J) GO TO 150 + T = IX(I+1) + TY = IY(I+1) + IF (IX(I) .LE. T) GO TO 170 + K = I +C + 180 IX(K+1) = IX(K) + IY(K+1) = IY(K) + K = K-1 + IF (T .LT. IX(K)) GO TO 180 + IX(K+1) = T + IY(K+1) = TY + GO TO 170 +C +C Clean up +C + 190 IF (KFLAG .LE. -1) THEN + DO 200 I=1,NN + IX(I) = -IX(I) + 200 CONTINUE + ENDIF + RETURN + END diff --git a/dep/slatec/j4save.f b/dep/slatec/j4save.f new file mode 100644 index 00000000..6ec799ba --- /dev/null +++ b/dep/slatec/j4save.f @@ -0,0 +1,65 @@ +*DECK J4SAVE + FUNCTION J4SAVE (IWHICH, IVALUE, ISET) +C***BEGIN PROLOGUE J4SAVE +C***SUBSIDIARY +C***PURPOSE Save or recall global variables needed by error +C handling routines. +C***LIBRARY SLATEC (XERROR) +C***TYPE INTEGER (J4SAVE-I) +C***KEYWORDS ERROR MESSAGES, ERROR NUMBER, RECALL, SAVE, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C J4SAVE saves and recalls several global variables needed +C by the library error handling routines. +C +C Description of Parameters +C --Input-- +C IWHICH - Index of item desired. +C = 1 Refers to current error number. +C = 2 Refers to current error control flag. +C = 3 Refers to current unit number to which error +C messages are to be sent. (0 means use standard.) +C = 4 Refers to the maximum number of times any +C message is to be printed (as set by XERMAX). +C = 5 Refers to the total number of units to which +C each error message is to be written. +C = 6 Refers to the 2nd unit for error messages +C = 7 Refers to the 3rd unit for error messages +C = 8 Refers to the 4th unit for error messages +C = 9 Refers to the 5th unit for error messages +C IVALUE - The value to be set for the IWHICH-th parameter, +C if ISET is .TRUE. . +C ISET - If ISET=.TRUE., the IWHICH-th parameter will BE +C given the value, IVALUE. If ISET=.FALSE., the +C IWHICH-th parameter will be unchanged, and IVALUE +C is a dummy parameter. +C --Output-- +C The (old) value of the IWHICH-th parameter will be returned +C in the function value, J4SAVE. +C +C***SEE ALSO XERMSG +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900205 Minor modifications to prologue. (WRB) +C 900402 Added TYPE section. (WRB) +C 910411 Added KEYWORDS section. (WRB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE J4SAVE + LOGICAL ISET + INTEGER IPARAM(9) + SAVE IPARAM + DATA IPARAM(1),IPARAM(2),IPARAM(3),IPARAM(4)/0,2,0,10/ + DATA IPARAM(5)/1/ + DATA IPARAM(6),IPARAM(7),IPARAM(8),IPARAM(9)/0,0,0,0/ +C***FIRST EXECUTABLE STATEMENT J4SAVE + J4SAVE = IPARAM(IWHICH) + IF (ISET) IPARAM(IWHICH) = IVALUE + RETURN + END diff --git a/dep/slatec/xercnt.f b/dep/slatec/xercnt.f new file mode 100644 index 00000000..06c82ab1 --- /dev/null +++ b/dep/slatec/xercnt.f @@ -0,0 +1,60 @@ +*DECK XERCNT + SUBROUTINE XERCNT (LIBRAR, SUBROU, MESSG, NERR, LEVEL, KONTRL) +C***BEGIN PROLOGUE XERCNT +C***SUBSIDIARY +C***PURPOSE Allow user control over handling of errors. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERCNT-A) +C***KEYWORDS ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C Allows user control over handling of individual errors. +C Just after each message is recorded, but before it is +C processed any further (i.e., before it is printed or +C a decision to abort is made), a call is made to XERCNT. +C If the user has provided his own version of XERCNT, he +C can then override the value of KONTROL used in processing +C this message by redefining its value. +C KONTRL may be set to any value from -2 to 2. +C The meanings for KONTRL are the same as in XSETF, except +C that the value of KONTRL changes only for this message. +C If KONTRL is set to a value outside the range from -2 to 2, +C it will be moved back into that range. +C +C Description of Parameters +C +C --Input-- +C LIBRAR - the library that the routine is in. +C SUBROU - the subroutine that XERMSG is being called from +C MESSG - the first 20 characters of the error message. +C NERR - same as in the call to XERMSG. +C LEVEL - same as in the call to XERMSG. +C KONTRL - the current value of the control flag as set +C by a call to XSETF. +C +C --Output-- +C KONTRL - the new value of KONTRL. If KONTRL is not +C defined, it will remain at its original value. +C This changed value of control affects only +C the current occurrence of the current message. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900206 Routine changed from user-callable to subsidiary. (WRB) +C 900510 Changed calling sequence to include LIBRARY and SUBROUTINE +C names, changed routine name from XERCTL to XERCNT. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERCNT + CHARACTER*(*) LIBRAR, SUBROU, MESSG +C***FIRST EXECUTABLE STATEMENT XERCNT + RETURN + END diff --git a/dep/slatec/xerhlt.f b/dep/slatec/xerhlt.f new file mode 100644 index 00000000..89b2a770 --- /dev/null +++ b/dep/slatec/xerhlt.f @@ -0,0 +1,39 @@ +*DECK XERHLT + SUBROUTINE XERHLT (MESSG) +C***BEGIN PROLOGUE XERHLT +C***SUBSIDIARY +C***PURPOSE Abort program execution and print error message. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERHLT-A) +C***KEYWORDS ABORT PROGRAM EXECUTION, ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C ***Note*** machine dependent routine +C XERHLT aborts the execution of the program. +C The error message causing the abort is given in the calling +C sequence, in case one needs it for printing on a dayfile, +C for example. +C +C Description of Parameters +C MESSG is as in XERMSG. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED (NONE) +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900206 Routine changed from user-callable to subsidiary. (WRB) +C 900510 Changed calling sequence to delete length of character +C and changed routine name from XERABT to XERHLT. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERHLT + CHARACTER*(*) MESSG +C***FIRST EXECUTABLE STATEMENT XERHLT + STOP + END diff --git a/dep/slatec/xermsg.f b/dep/slatec/xermsg.f new file mode 100644 index 00000000..46c83ec0 --- /dev/null +++ b/dep/slatec/xermsg.f @@ -0,0 +1,364 @@ +*DECK XERMSG + SUBROUTINE XERMSG (LIBRAR, SUBROU, MESSG, NERR, LEVEL) +C***BEGIN PROLOGUE XERMSG +C***PURPOSE Process error messages for SLATEC and other libraries. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERMSG-A) +C***KEYWORDS ERROR MESSAGE, XERROR +C***AUTHOR Fong, Kirby, (NMFECC at LLNL) +C***DESCRIPTION +C +C XERMSG processes a diagnostic message in a manner determined by the +C value of LEVEL and the current value of the library error control +C flag, KONTRL. See subroutine XSETF for details. +C +C LIBRAR A character constant (or character variable) with the name +C of the library. This will be 'SLATEC' for the SLATEC +C Common Math Library. The error handling package is +C general enough to be used by many libraries +C simultaneously, so it is desirable for the routine that +C detects and reports an error to identify the library name +C as well as the routine name. +C +C SUBROU A character constant (or character variable) with the name +C of the routine that detected the error. Usually it is the +C name of the routine that is calling XERMSG. There are +C some instances where a user callable library routine calls +C lower level subsidiary routines where the error is +C detected. In such cases it may be more informative to +C supply the name of the routine the user called rather than +C the name of the subsidiary routine that detected the +C error. +C +C MESSG A character constant (or character variable) with the text +C of the error or warning message. In the example below, +C the message is a character constant that contains a +C generic message. +C +C CALL XERMSG ('SLATEC', 'MMPY', +C *'THE ORDER OF THE MATRIX EXCEEDS THE ROW DIMENSION', +C *3, 1) +C +C It is possible (and is sometimes desirable) to generate a +C specific message--e.g., one that contains actual numeric +C values. Specific numeric values can be converted into +C character strings using formatted WRITE statements into +C character variables. This is called standard Fortran +C internal file I/O and is exemplified in the first three +C lines of the following example. You can also catenate +C substrings of characters to construct the error message. +C Here is an example showing the use of both writing to +C an internal file and catenating character strings. +C +C CHARACTER*5 CHARN, CHARL +C WRITE (CHARN,10) N +C WRITE (CHARL,10) LDA +C 10 FORMAT(I5) +C CALL XERMSG ('SLATEC', 'MMPY', 'THE ORDER'//CHARN// +C * ' OF THE MATRIX EXCEEDS ITS ROW DIMENSION OF'// +C * CHARL, 3, 1) +C +C There are two subtleties worth mentioning. One is that +C the // for character catenation is used to construct the +C error message so that no single character constant is +C continued to the next line. This avoids confusion as to +C whether there are trailing blanks at the end of the line. +C The second is that by catenating the parts of the message +C as an actual argument rather than encoding the entire +C message into one large character variable, we avoid +C having to know how long the message will be in order to +C declare an adequate length for that large character +C variable. XERMSG calls XERPRN to print the message using +C multiple lines if necessary. If the message is very long, +C XERPRN will break it into pieces of 72 characters (as +C requested by XERMSG) for printing on multiple lines. +C Also, XERMSG asks XERPRN to prefix each line with ' * ' +C so that the total line length could be 76 characters. +C Note also that XERPRN scans the error message backwards +C to ignore trailing blanks. Another feature is that +C the substring '$$' is treated as a new line sentinel +C by XERPRN. If you want to construct a multiline +C message without having to count out multiples of 72 +C characters, just use '$$' as a separator. '$$' +C obviously must occur within 72 characters of the +C start of each line to have its intended effect since +C XERPRN is asked to wrap around at 72 characters in +C addition to looking for '$$'. +C +C NERR An integer value that is chosen by the library routine's +C author. It must be in the range -99 to 999 (three +C printable digits). Each distinct error should have its +C own error number. These error numbers should be described +C in the machine readable documentation for the routine. +C The error numbers need be unique only within each routine, +C so it is reasonable for each routine to start enumerating +C errors from 1 and proceeding to the next integer. +C +C LEVEL An integer value in the range 0 to 2 that indicates the +C level (severity) of the error. Their meanings are +C +C -1 A warning message. This is used if it is not clear +C that there really is an error, but the user's attention +C may be needed. An attempt is made to only print this +C message once. +C +C 0 A warning message. This is used if it is not clear +C that there really is an error, but the user's attention +C may be needed. +C +C 1 A recoverable error. This is used even if the error is +C so serious that the routine cannot return any useful +C answer. If the user has told the error package to +C return after recoverable errors, then XERMSG will +C return to the Library routine which can then return to +C the user's routine. The user may also permit the error +C package to terminate the program upon encountering a +C recoverable error. +C +C 2 A fatal error. XERMSG will not return to its caller +C after it receives a fatal error. This level should +C hardly ever be used; it is much better to allow the +C user a chance to recover. An example of one of the few +C cases in which it is permissible to declare a level 2 +C error is a reverse communication Library routine that +C is likely to be called repeatedly until it integrates +C across some interval. If there is a serious error in +C the input such that another step cannot be taken and +C the Library routine is called again without the input +C error having been corrected by the caller, the Library +C routine will probably be called forever with improper +C input. In this case, it is reasonable to declare the +C error to be fatal. +C +C Each of the arguments to XERMSG is input; none will be modified by +C XERMSG. A routine may make multiple calls to XERMSG with warning +C level messages; however, after a call to XERMSG with a recoverable +C error, the routine should return to the user. Do not try to call +C XERMSG with a second recoverable error after the first recoverable +C error because the error package saves the error number. The user +C can retrieve this error number by calling another entry point in +C the error handling package and then clear the error number when +C recovering from the error. Calling XERMSG in succession causes the +C old error number to be overwritten by the latest error number. +C This is considered harmless for error numbers associated with +C warning messages but must not be done for error numbers of serious +C errors. After a call to XERMSG with a recoverable error, the user +C must be given a chance to call NUMXER or XERCLR to retrieve or +C clear the error number. +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED FDUMP, J4SAVE, XERCNT, XERHLT, XERPRN, XERSVE +C***REVISION HISTORY (YYMMDD) +C 880101 DATE WRITTEN +C 880621 REVISED AS DIRECTED AT SLATEC CML MEETING OF FEBRUARY 1988. +C THERE ARE TWO BASIC CHANGES. +C 1. A NEW ROUTINE, XERPRN, IS USED INSTEAD OF XERPRT TO +C PRINT MESSAGES. THIS ROUTINE WILL BREAK LONG MESSAGES +C INTO PIECES FOR PRINTING ON MULTIPLE LINES. '$$' IS +C ACCEPTED AS A NEW LINE SENTINEL. A PREFIX CAN BE +C ADDED TO EACH LINE TO BE PRINTED. XERMSG USES EITHER +C ' ***' OR ' * ' AND LONG MESSAGES ARE BROKEN EVERY +C 72 CHARACTERS (AT MOST) SO THAT THE MAXIMUM LINE +C LENGTH OUTPUT CAN NOW BE AS GREAT AS 76. +C 2. THE TEXT OF ALL MESSAGES IS NOW IN UPPER CASE SINCE THE +C FORTRAN STANDARD DOCUMENT DOES NOT ADMIT THE EXISTENCE +C OF LOWER CASE. +C 880708 REVISED AFTER THE SLATEC CML MEETING OF JUNE 29 AND 30. +C THE PRINCIPAL CHANGES ARE +C 1. CLARIFY COMMENTS IN THE PROLOGUES +C 2. RENAME XRPRNT TO XERPRN +C 3. REWORK HANDLING OF '$$' IN XERPRN TO HANDLE BLANK LINES +C SIMILAR TO THE WAY FORMAT STATEMENTS HANDLE THE / +C CHARACTER FOR NEW RECORDS. +C 890706 REVISED WITH THE HELP OF FRED FRITSCH AND REG CLEMENS TO +C CLEAN UP THE CODING. +C 890721 REVISED TO USE NEW FEATURE IN XERPRN TO COUNT CHARACTERS IN +C PREFIX. +C 891013 REVISED TO CORRECT COMMENTS. +C 891214 Prologue converted to Version 4.0 format. (WRB) +C 900510 Changed test on NERR to be -9999999 < NERR < 99999999, but +C NERR .ne. 0, and on LEVEL to be -2 < LEVEL < 3. Added +C LEVEL=-1 logic, changed calls to XERSAV to XERSVE, and +C XERCTL to XERCNT. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERMSG + CHARACTER*(*) LIBRAR, SUBROU, MESSG + CHARACTER*8 XLIBR, XSUBR + CHARACTER*72 TEMP + CHARACTER*20 LFIRST +C***FIRST EXECUTABLE STATEMENT XERMSG + LKNTRL = J4SAVE (2, 0, .FALSE.) + MAXMES = J4SAVE (4, 0, .FALSE.) +C +C LKNTRL IS A LOCAL COPY OF THE CONTROL FLAG KONTRL. +C MAXMES IS THE MAXIMUM NUMBER OF TIMES ANY PARTICULAR MESSAGE +C SHOULD BE PRINTED. +C +C WE PRINT A FATAL ERROR MESSAGE AND TERMINATE FOR AN ERROR IN +C CALLING XERMSG. THE ERROR NUMBER SHOULD BE POSITIVE, +C AND THE LEVEL SHOULD BE BETWEEN 0 AND 2. +C + IF (NERR.LT.-9999999 .OR. NERR.GT.99999999 .OR. NERR.EQ.0 .OR. + * LEVEL.LT.-1 .OR. LEVEL.GT.2) THEN + CALL XERPRN (' ***', -1, 'FATAL ERROR IN...$$ ' // + * 'XERMSG -- INVALID ERROR NUMBER OR LEVEL$$ '// + * 'JOB ABORT DUE TO FATAL ERROR.', 72) + CALL XERSVE (' ', ' ', ' ', 0, 0, 0, KDUMMY) + CALL XERHLT (' ***XERMSG -- INVALID INPUT') + RETURN + ENDIF +C +C RECORD THE MESSAGE. +C + I = J4SAVE (1, NERR, .TRUE.) + CALL XERSVE (LIBRAR, SUBROU, MESSG, 1, NERR, LEVEL, KOUNT) +C +C HANDLE PRINT-ONCE WARNING MESSAGES. +C + IF (LEVEL.EQ.-1 .AND. KOUNT.GT.1) RETURN +C +C ALLOW TEMPORARY USER OVERRIDE OF THE CONTROL FLAG. +C + XLIBR = LIBRAR + XSUBR = SUBROU + LFIRST = MESSG + LERR = NERR + LLEVEL = LEVEL + CALL XERCNT (XLIBR, XSUBR, LFIRST, LERR, LLEVEL, LKNTRL) +C + LKNTRL = MAX(-2, MIN(2,LKNTRL)) + MKNTRL = ABS(LKNTRL) +C +C SKIP PRINTING IF THE CONTROL FLAG VALUE AS RESET IN XERCNT IS +C ZERO AND THE ERROR IS NOT FATAL. +C + IF (LEVEL.LT.2 .AND. LKNTRL.EQ.0) GO TO 30 + IF (LEVEL.EQ.0 .AND. KOUNT.GT.MAXMES) GO TO 30 + IF (LEVEL.EQ.1 .AND. KOUNT.GT.MAXMES .AND. MKNTRL.EQ.1) GO TO 30 + IF (LEVEL.EQ.2 .AND. KOUNT.GT.MAX(1,MAXMES)) GO TO 30 +C +C ANNOUNCE THE NAMES OF THE LIBRARY AND SUBROUTINE BY BUILDING A +C MESSAGE IN CHARACTER VARIABLE TEMP (NOT EXCEEDING 66 CHARACTERS) +C AND SENDING IT OUT VIA XERPRN. PRINT ONLY IF CONTROL FLAG +C IS NOT ZERO. +C + IF (LKNTRL .NE. 0) THEN + TEMP(1:21) = 'MESSAGE FROM ROUTINE ' + I = MIN(LEN(SUBROU), 16) + TEMP(22:21+I) = SUBROU(1:I) + TEMP(22+I:33+I) = ' IN LIBRARY ' + LTEMP = 33 + I + I = MIN(LEN(LIBRAR), 16) + TEMP(LTEMP+1:LTEMP+I) = LIBRAR (1:I) + TEMP(LTEMP+I+1:LTEMP+I+1) = '.' + LTEMP = LTEMP + I + 1 + CALL XERPRN (' ***', -1, TEMP(1:LTEMP), 72) + ENDIF +C +C IF LKNTRL IS POSITIVE, PRINT AN INTRODUCTORY LINE BEFORE +C PRINTING THE MESSAGE. THE INTRODUCTORY LINE TELLS THE CHOICE +C FROM EACH OF THE FOLLOWING THREE OPTIONS. +C 1. LEVEL OF THE MESSAGE +C 'INFORMATIVE MESSAGE' +C 'POTENTIALLY RECOVERABLE ERROR' +C 'FATAL ERROR' +C 2. WHETHER CONTROL FLAG WILL ALLOW PROGRAM TO CONTINUE +C 'PROG CONTINUES' +C 'PROG ABORTED' +C 3. WHETHER OR NOT A TRACEBACK WAS REQUESTED. (THE TRACEBACK +C MAY NOT BE IMPLEMENTED AT SOME SITES, SO THIS ONLY TELLS +C WHAT WAS REQUESTED, NOT WHAT WAS DELIVERED.) +C 'TRACEBACK REQUESTED' +C 'TRACEBACK NOT REQUESTED' +C NOTICE THAT THE LINE INCLUDING FOUR PREFIX CHARACTERS WILL NOT +C EXCEED 74 CHARACTERS. +C WE SKIP THE NEXT BLOCK IF THE INTRODUCTORY LINE IS NOT NEEDED. +C + IF (LKNTRL .GT. 0) THEN +C +C THE FIRST PART OF THE MESSAGE TELLS ABOUT THE LEVEL. +C + IF (LEVEL .LE. 0) THEN + TEMP(1:20) = 'INFORMATIVE MESSAGE,' + LTEMP = 20 + ELSEIF (LEVEL .EQ. 1) THEN + TEMP(1:30) = 'POTENTIALLY RECOVERABLE ERROR,' + LTEMP = 30 + ELSE + TEMP(1:12) = 'FATAL ERROR,' + LTEMP = 12 + ENDIF +C +C THEN WHETHER THE PROGRAM WILL CONTINUE. +C + IF ((MKNTRL.EQ.2 .AND. LEVEL.GE.1) .OR. + * (MKNTRL.EQ.1 .AND. LEVEL.EQ.2)) THEN + TEMP(LTEMP+1:LTEMP+14) = ' PROG ABORTED,' + LTEMP = LTEMP + 14 + ELSE + TEMP(LTEMP+1:LTEMP+16) = ' PROG CONTINUES,' + LTEMP = LTEMP + 16 + ENDIF +C +C FINALLY TELL WHETHER THERE SHOULD BE A TRACEBACK. +C + IF (LKNTRL .GT. 0) THEN + TEMP(LTEMP+1:LTEMP+20) = ' TRACEBACK REQUESTED' + LTEMP = LTEMP + 20 + ELSE + TEMP(LTEMP+1:LTEMP+24) = ' TRACEBACK NOT REQUESTED' + LTEMP = LTEMP + 24 + ENDIF + CALL XERPRN (' ***', -1, TEMP(1:LTEMP), 72) + ENDIF +C +C NOW SEND OUT THE MESSAGE. +C + CALL XERPRN (' * ', -1, MESSG, 72) +C +C IF LKNTRL IS POSITIVE, WRITE THE ERROR NUMBER AND REQUEST A +C TRACEBACK. +C + IF (LKNTRL .GT. 0) THEN + WRITE (TEMP, '(''ERROR NUMBER = '', I8)') NERR + DO 10 I=16,22 + IF (TEMP(I:I) .NE. ' ') GO TO 20 + 10 CONTINUE +C + 20 CALL XERPRN (' * ', -1, TEMP(1:15) // TEMP(I:23), 72) + CALL FDUMP + ENDIF +C +C IF LKNTRL IS NOT ZERO, PRINT A BLANK LINE AND AN END OF MESSAGE. +C + IF (LKNTRL .NE. 0) THEN + CALL XERPRN (' * ', -1, ' ', 72) + CALL XERPRN (' ***', -1, 'END OF MESSAGE', 72) + CALL XERPRN (' ', 0, ' ', 72) + ENDIF +C +C IF THE ERROR IS NOT FATAL OR THE ERROR IS RECOVERABLE AND THE +C CONTROL FLAG IS SET FOR RECOVERY, THEN RETURN. +C + 30 IF (LEVEL.LE.0 .OR. (LEVEL.EQ.1 .AND. MKNTRL.LE.1)) RETURN +C +C THE PROGRAM WILL BE STOPPED DUE TO AN UNRECOVERED ERROR OR A +C FATAL ERROR. PRINT THE REASON FOR THE ABORT AND THE ERROR +C SUMMARY IF THE CONTROL FLAG AND THE MAXIMUM ERROR COUNT PERMIT. +C + IF (LKNTRL.GT.0 .AND. KOUNT.LT.MAX(1,MAXMES)) THEN + IF (LEVEL .EQ. 1) THEN + CALL XERPRN + * (' ***', -1, 'JOB ABORT DUE TO UNRECOVERED ERROR.', 72) + ELSE + CALL XERPRN(' ***', -1, 'JOB ABORT DUE TO FATAL ERROR.', 72) + ENDIF + CALL XERSVE (' ', ' ', ' ', -1, 0, 0, KDUMMY) + CALL XERHLT (' ') + ELSE + CALL XERHLT (MESSG) + ENDIF + RETURN + END diff --git a/dep/slatec/xerprn.f b/dep/slatec/xerprn.f new file mode 100644 index 00000000..97eedf48 --- /dev/null +++ b/dep/slatec/xerprn.f @@ -0,0 +1,228 @@ +*DECK XERPRN + SUBROUTINE XERPRN (PREFIX, NPREF, MESSG, NWRAP) +C***BEGIN PROLOGUE XERPRN +C***SUBSIDIARY +C***PURPOSE Print error messages processed by XERMSG. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XERPRN-A) +C***KEYWORDS ERROR MESSAGES, PRINTING, XERROR +C***AUTHOR Fong, Kirby, (NMFECC at LLNL) +C***DESCRIPTION +C +C This routine sends one or more lines to each of the (up to five) +C logical units to which error messages are to be sent. This routine +C is called several times by XERMSG, sometimes with a single line to +C print and sometimes with a (potentially very long) message that may +C wrap around into multiple lines. +C +C PREFIX Input argument of type CHARACTER. This argument contains +C characters to be put at the beginning of each line before +C the body of the message. No more than 16 characters of +C PREFIX will be used. +C +C NPREF Input argument of type INTEGER. This argument is the number +C of characters to use from PREFIX. If it is negative, the +C intrinsic function LEN is used to determine its length. If +C it is zero, PREFIX is not used. If it exceeds 16 or if +C LEN(PREFIX) exceeds 16, only the first 16 characters will be +C used. If NPREF is positive and the length of PREFIX is less +C than NPREF, a copy of PREFIX extended with blanks to length +C NPREF will be used. +C +C MESSG Input argument of type CHARACTER. This is the text of a +C message to be printed. If it is a long message, it will be +C broken into pieces for printing on multiple lines. Each line +C will start with the appropriate prefix and be followed by a +C piece of the message. NWRAP is the number of characters per +C piece; that is, after each NWRAP characters, we break and +C start a new line. In addition the characters '$$' embedded +C in MESSG are a sentinel for a new line. The counting of +C characters up to NWRAP starts over for each new line. The +C value of NWRAP typically used by XERMSG is 72 since many +C older error messages in the SLATEC Library are laid out to +C rely on wrap-around every 72 characters. +C +C NWRAP Input argument of type INTEGER. This gives the maximum size +C piece into which to break MESSG for printing on multiple +C lines. An embedded '$$' ends a line, and the count restarts +C at the following character. If a line break does not occur +C on a blank (it would split a word) that word is moved to the +C next line. Values of NWRAP less than 16 will be treated as +C 16. Values of NWRAP greater than 132 will be treated as 132. +C The actual line length will be NPREF + NWRAP after NPREF has +C been adjusted to fall between 0 and 16 and NWRAP has been +C adjusted to fall between 16 and 132. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED I1MACH, XGETUA +C***REVISION HISTORY (YYMMDD) +C 880621 DATE WRITTEN +C 880708 REVISED AFTER THE SLATEC CML SUBCOMMITTEE MEETING OF +C JUNE 29 AND 30 TO CHANGE THE NAME TO XERPRN AND TO REWORK +C THE HANDLING OF THE NEW LINE SENTINEL TO BEHAVE LIKE THE +C SLASH CHARACTER IN FORMAT STATEMENTS. +C 890706 REVISED WITH THE HELP OF FRED FRITSCH AND REG CLEMENS TO +C STREAMLINE THE CODING AND FIX A BUG THAT CAUSED EXTRA BLANK +C LINES TO BE PRINTED. +C 890721 REVISED TO ADD A NEW FEATURE. A NEGATIVE VALUE OF NPREF +C CAUSES LEN(PREFIX) TO BE USED AS THE LENGTH. +C 891013 REVISED TO CORRECT ERROR IN CALCULATING PREFIX LENGTH. +C 891214 Prologue converted to Version 4.0 format. (WRB) +C 900510 Added code to break messages between words. (RWC) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERPRN + CHARACTER*(*) PREFIX, MESSG + INTEGER NPREF, NWRAP + CHARACTER*148 CBUFF + INTEGER IU(5), NUNIT + CHARACTER*2 NEWLIN + PARAMETER (NEWLIN = '$$') +C***FIRST EXECUTABLE STATEMENT XERPRN + CALL XGETUA(IU,NUNIT) +C +C A ZERO VALUE FOR A LOGICAL UNIT NUMBER MEANS TO USE THE STANDARD +C ERROR MESSAGE UNIT INSTEAD. I1MACH(4) RETRIEVES THE STANDARD +C ERROR MESSAGE UNIT. +C + N = I1MACH(4) + DO 10 I=1,NUNIT + IF (IU(I) .EQ. 0) IU(I) = N + 10 CONTINUE +C +C LPREF IS THE LENGTH OF THE PREFIX. THE PREFIX IS PLACED AT THE +C BEGINNING OF CBUFF, THE CHARACTER BUFFER, AND KEPT THERE DURING +C THE REST OF THIS ROUTINE. +C + IF ( NPREF .LT. 0 ) THEN + LPREF = LEN(PREFIX) + ELSE + LPREF = NPREF + ENDIF + LPREF = MIN(16, LPREF) + IF (LPREF .NE. 0) CBUFF(1:LPREF) = PREFIX +C +C LWRAP IS THE MAXIMUM NUMBER OF CHARACTERS WE WANT TO TAKE AT ONE +C TIME FROM MESSG TO PRINT ON ONE LINE. +C + LWRAP = MAX(16, MIN(132, NWRAP)) +C +C SET LENMSG TO THE LENGTH OF MESSG, IGNORE ANY TRAILING BLANKS. +C + LENMSG = LEN(MESSG) + N = LENMSG + DO 20 I=1,N + IF (MESSG(LENMSG:LENMSG) .NE. ' ') GO TO 30 + LENMSG = LENMSG - 1 + 20 CONTINUE + 30 CONTINUE +C +C IF THE MESSAGE IS ALL BLANKS, THEN PRINT ONE BLANK LINE. +C + IF (LENMSG .EQ. 0) THEN + CBUFF(LPREF+1:LPREF+1) = ' ' + DO 40 I=1,NUNIT + WRITE(IU(I), '(A)') CBUFF(1:LPREF+1) + 40 CONTINUE + RETURN + ENDIF +C +C SET NEXTC TO THE POSITION IN MESSG WHERE THE NEXT SUBSTRING +C STARTS. FROM THIS POSITION WE SCAN FOR THE NEW LINE SENTINEL. +C WHEN NEXTC EXCEEDS LENMSG, THERE IS NO MORE TO PRINT. +C WE LOOP BACK TO LABEL 50 UNTIL ALL PIECES HAVE BEEN PRINTED. +C +C WE LOOK FOR THE NEXT OCCURRENCE OF THE NEW LINE SENTINEL. THE +C INDEX INTRINSIC FUNCTION RETURNS ZERO IF THERE IS NO OCCURRENCE +C OR IF THE LENGTH OF THE FIRST ARGUMENT IS LESS THAN THE LENGTH +C OF THE SECOND ARGUMENT. +C +C THERE ARE SEVERAL CASES WHICH SHOULD BE CHECKED FOR IN THE +C FOLLOWING ORDER. WE ARE ATTEMPTING TO SET LPIECE TO THE NUMBER +C OF CHARACTERS THAT SHOULD BE TAKEN FROM MESSG STARTING AT +C POSITION NEXTC. +C +C LPIECE .EQ. 0 THE NEW LINE SENTINEL DOES NOT OCCUR IN THE +C REMAINDER OF THE CHARACTER STRING. LPIECE +C SHOULD BE SET TO LWRAP OR LENMSG+1-NEXTC, +C WHICHEVER IS LESS. +C +C LPIECE .EQ. 1 THE NEW LINE SENTINEL STARTS AT MESSG(NEXTC: +C NEXTC). LPIECE IS EFFECTIVELY ZERO, AND WE +C PRINT NOTHING TO AVOID PRODUCING UNNECESSARY +C BLANK LINES. THIS TAKES CARE OF THE SITUATION +C WHERE THE LIBRARY ROUTINE HAS A MESSAGE OF +C EXACTLY 72 CHARACTERS FOLLOWED BY A NEW LINE +C SENTINEL FOLLOWED BY MORE CHARACTERS. NEXTC +C SHOULD BE INCREMENTED BY 2. +C +C LPIECE .GT. LWRAP+1 REDUCE LPIECE TO LWRAP. +C +C ELSE THIS LAST CASE MEANS 2 .LE. LPIECE .LE. LWRAP+1 +C RESET LPIECE = LPIECE-1. NOTE THAT THIS +C PROPERLY HANDLES THE END CASE WHERE LPIECE .EQ. +C LWRAP+1. THAT IS, THE SENTINEL FALLS EXACTLY +C AT THE END OF A LINE. +C + NEXTC = 1 + 50 LPIECE = INDEX(MESSG(NEXTC:LENMSG), NEWLIN) + IF (LPIECE .EQ. 0) THEN +C +C THERE WAS NO NEW LINE SENTINEL FOUND. +C + IDELTA = 0 + LPIECE = MIN(LWRAP, LENMSG+1-NEXTC) + IF (LPIECE .LT. LENMSG+1-NEXTC) THEN + DO 52 I=LPIECE+1,2,-1 + IF (MESSG(NEXTC+I-1:NEXTC+I-1) .EQ. ' ') THEN + LPIECE = I-1 + IDELTA = 1 + GOTO 54 + ENDIF + 52 CONTINUE + ENDIF + 54 CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1) + NEXTC = NEXTC + LPIECE + IDELTA + ELSEIF (LPIECE .EQ. 1) THEN +C +C WE HAVE A NEW LINE SENTINEL AT MESSG(NEXTC:NEXTC+1). +C DON'T PRINT A BLANK LINE. +C + NEXTC = NEXTC + 2 + GO TO 50 + ELSEIF (LPIECE .GT. LWRAP+1) THEN +C +C LPIECE SHOULD BE SET DOWN TO LWRAP. +C + IDELTA = 0 + LPIECE = LWRAP + DO 56 I=LPIECE+1,2,-1 + IF (MESSG(NEXTC+I-1:NEXTC+I-1) .EQ. ' ') THEN + LPIECE = I-1 + IDELTA = 1 + GOTO 58 + ENDIF + 56 CONTINUE + 58 CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1) + NEXTC = NEXTC + LPIECE + IDELTA + ELSE +C +C IF WE ARRIVE HERE, IT MEANS 2 .LE. LPIECE .LE. LWRAP+1. +C WE SHOULD DECREMENT LPIECE BY ONE. +C + LPIECE = LPIECE - 1 + CBUFF(LPREF+1:LPREF+LPIECE) = MESSG(NEXTC:NEXTC+LPIECE-1) + NEXTC = NEXTC + LPIECE + 2 + ENDIF +C +C PRINT +C + DO 60 I=1,NUNIT + WRITE(IU(I), '(A)') CBUFF(1:LPREF+LPIECE) + 60 CONTINUE +C + IF (NEXTC .LE. LENMSG) GO TO 50 + RETURN + END diff --git a/dep/slatec/xersve.f b/dep/slatec/xersve.f new file mode 100644 index 00000000..6bd2a4f7 --- /dev/null +++ b/dep/slatec/xersve.f @@ -0,0 +1,155 @@ +*DECK XERSVE + SUBROUTINE XERSVE (LIBRAR, SUBROU, MESSG, KFLAG, NERR, LEVEL, + + ICOUNT) +C***BEGIN PROLOGUE XERSVE +C***SUBSIDIARY +C***PURPOSE Record that an error has occurred. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3 +C***TYPE ALL (XERSVE-A) +C***KEYWORDS ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C *Usage: +C +C INTEGER KFLAG, NERR, LEVEL, ICOUNT +C CHARACTER * (len) LIBRAR, SUBROU, MESSG +C +C CALL XERSVE (LIBRAR, SUBROU, MESSG, KFLAG, NERR, LEVEL, ICOUNT) +C +C *Arguments: +C +C LIBRAR :IN is the library that the message is from. +C SUBROU :IN is the subroutine that the message is from. +C MESSG :IN is the message to be saved. +C KFLAG :IN indicates the action to be performed. +C when KFLAG > 0, the message in MESSG is saved. +C when KFLAG=0 the tables will be dumped and +C cleared. +C when KFLAG < 0, the tables will be dumped and +C not cleared. +C NERR :IN is the error number. +C LEVEL :IN is the error severity. +C ICOUNT :OUT the number of times this message has been seen, +C or zero if the table has overflowed and does not +C contain this message specifically. When KFLAG=0, +C ICOUNT will not be altered. +C +C *Description: +C +C Record that this error occurred and possibly dump and clear the +C tables. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED I1MACH, XGETUA +C***REVISION HISTORY (YYMMDD) +C 800319 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 900413 Routine modified to remove reference to KFLAG. (WRB) +C 900510 Changed to add LIBRARY NAME and SUBROUTINE to calling +C sequence, use IF-THEN-ELSE, make number of saved entries +C easily changeable, changed routine name from XERSAV to +C XERSVE. (RWC) +C 910626 Added LIBTAB and SUBTAB to SAVE statement. (BKS) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XERSVE + PARAMETER (LENTAB=10) + INTEGER LUN(5) + CHARACTER*(*) LIBRAR, SUBROU, MESSG + CHARACTER*8 LIBTAB(LENTAB), SUBTAB(LENTAB), LIB, SUB + CHARACTER*20 MESTAB(LENTAB), MES + DIMENSION NERTAB(LENTAB), LEVTAB(LENTAB), KOUNT(LENTAB) + SAVE LIBTAB, SUBTAB, MESTAB, NERTAB, LEVTAB, KOUNT, KOUNTX, NMSG + DATA KOUNTX/0/, NMSG/0/ +C***FIRST EXECUTABLE STATEMENT XERSVE +C + IF (KFLAG.LE.0) THEN +C +C Dump the table. +C + IF (NMSG.EQ.0) RETURN +C +C Print to each unit. +C + CALL XGETUA (LUN, NUNIT) + DO 20 KUNIT = 1,NUNIT + IUNIT = LUN(KUNIT) + IF (IUNIT.EQ.0) IUNIT = I1MACH(4) +C +C Print the table header. +C + WRITE (IUNIT,9000) +C +C Print body of table. +C + DO 10 I = 1,NMSG + WRITE (IUNIT,9010) LIBTAB(I), SUBTAB(I), MESTAB(I), + * NERTAB(I),LEVTAB(I),KOUNT(I) + 10 CONTINUE +C +C Print number of other errors. +C + IF (KOUNTX.NE.0) WRITE (IUNIT,9020) KOUNTX + WRITE (IUNIT,9030) + 20 CONTINUE +C +C Clear the error tables. +C + IF (KFLAG.EQ.0) THEN + NMSG = 0 + KOUNTX = 0 + ENDIF + ELSE +C +C PROCESS A MESSAGE... +C SEARCH FOR THIS MESSG, OR ELSE AN EMPTY SLOT FOR THIS MESSG, +C OR ELSE DETERMINE THAT THE ERROR TABLE IS FULL. +C + LIB = LIBRAR + SUB = SUBROU + MES = MESSG + DO 30 I = 1,NMSG + IF (LIB.EQ.LIBTAB(I) .AND. SUB.EQ.SUBTAB(I) .AND. + * MES.EQ.MESTAB(I) .AND. NERR.EQ.NERTAB(I) .AND. + * LEVEL.EQ.LEVTAB(I)) THEN + KOUNT(I) = KOUNT(I) + 1 + ICOUNT = KOUNT(I) + RETURN + ENDIF + 30 CONTINUE +C + IF (NMSG.LT.LENTAB) THEN +C +C Empty slot found for new message. +C + NMSG = NMSG + 1 + LIBTAB(I) = LIB + SUBTAB(I) = SUB + MESTAB(I) = MES + NERTAB(I) = NERR + LEVTAB(I) = LEVEL + KOUNT (I) = 1 + ICOUNT = 1 + ELSE +C +C Table is full. +C + KOUNTX = KOUNTX+1 + ICOUNT = 0 + ENDIF + ENDIF + RETURN +C +C Formats. +C + 9000 FORMAT ('0 ERROR MESSAGE SUMMARY' / + + ' LIBRARY SUBROUTINE MESSAGE START NERR', + + ' LEVEL COUNT') + 9010 FORMAT (1X,A,3X,A,3X,A,3I10) + 9020 FORMAT ('0OTHER ERRORS NOT INDIVIDUALLY TABULATED = ', I10) + 9030 FORMAT (1X) + END diff --git a/dep/slatec/xgetua.f b/dep/slatec/xgetua.f new file mode 100644 index 00000000..2e7db021 --- /dev/null +++ b/dep/slatec/xgetua.f @@ -0,0 +1,51 @@ +*DECK XGETUA + SUBROUTINE XGETUA (IUNITA, N) +C***BEGIN PROLOGUE XGETUA +C***PURPOSE Return unit number(s) to which error messages are being +C sent. +C***LIBRARY SLATEC (XERROR) +C***CATEGORY R3C +C***TYPE ALL (XGETUA-A) +C***KEYWORDS ERROR, XERROR +C***AUTHOR Jones, R. E., (SNLA) +C***DESCRIPTION +C +C Abstract +C XGETUA may be called to determine the unit number or numbers +C to which error messages are being sent. +C These unit numbers may have been set by a call to XSETUN, +C or a call to XSETUA, or may be a default value. +C +C Description of Parameters +C --Output-- +C IUNIT - an array of one to five unit numbers, depending +C on the value of N. A value of zero refers to the +C default unit, as defined by the I1MACH machine +C constant routine. Only IUNIT(1),...,IUNIT(N) are +C defined by XGETUA. The values of IUNIT(N+1),..., +C IUNIT(5) are not defined (for N .LT. 5) or altered +C in any way by XGETUA. +C N - the number of units to which copies of the +C error messages are being sent. N will be in the +C range from 1 to 5. +C +C***REFERENCES R. E. Jones and D. K. Kahaner, XERROR, the SLATEC +C Error-handling Package, SAND82-0800, Sandia +C Laboratories, 1982. +C***ROUTINES CALLED J4SAVE +C***REVISION HISTORY (YYMMDD) +C 790801 DATE WRITTEN +C 861211 REVISION DATE from Version 3.2 +C 891214 Prologue converted to Version 4.0 format. (BAB) +C 920501 Reformatted the REFERENCES section. (WRB) +C***END PROLOGUE XGETUA + DIMENSION IUNITA(5) +C***FIRST EXECUTABLE STATEMENT XGETUA + N = J4SAVE(5,0,.FALSE.) + DO 30 I=1,N + INDEX = I+4 + IF (I.EQ.1) INDEX = 3 + IUNITA(I) = J4SAVE(INDEX,0,.FALSE.) + 30 CONTINUE + RETURN + END diff --git a/doc/UQTk_v3.0.4_manual.pdf b/doc/UQTk_v3.0.4_manual.pdf new file mode 100644 index 00000000..043c7ac8 Binary files /dev/null and b/doc/UQTk_v3.0.4_manual.pdf differ diff --git a/doc/doxygen/html/Array1D_8h.html b/doc/doxygen/html/Array1D_8h.html new file mode 100644 index 00000000..68f90a22 --- /dev/null +++ b/doc/doxygen/html/Array1D_8h.html @@ -0,0 +1,86 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array1D.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
Array1D.h File Reference
+
+
+ +

1D Array class for any type T +More...

+
#include <string>
+#include <string.h>
+#include <iostream>
+#include <vector>
+#include <fstream>
+#include <iterator>
+#include <algorithm>
+#include <typeinfo>
+#include "error_handlers.h"
+
+

Go to the source code of this file.

+ + + + + + + + + +

+Classes

class  Array1D< T >
 Stores data of any type T in a 1D array. More...
 
class  Array1D< int >
 
class  Array1D< double >
 
+

Detailed Description

+

1D Array class for any type T

+
+ + + + diff --git a/doc/doxygen/html/Array1D_8h_source.html b/doc/doxygen/html/Array1D_8h_source.html new file mode 100644 index 00000000..3c9693e9 --- /dev/null +++ b/doc/doxygen/html/Array1D_8h_source.html @@ -0,0 +1,162 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array1D.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
Array1D.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
29 
30 #ifndef ARRAY1D_H_SEEN
31 #define ARRAY1D_H_SEEN
32 
33 #include <string>
34 #include <string.h>
35 #include <iostream>
36 #include <vector>
37 #include <fstream>
38 #include <iterator>
39 #include <algorithm>
40 #include <typeinfo>
41 
42 #include "error_handlers.h"
43 
44 using namespace std;
45 
46 // template<typename T> T max_test(T a, T b) { return a > b ? a : b; }
47 
58 //column major for fortran blas
59 template<typename T>
60 class Array1D{
61 private:
62 
63 public:
64  // These two quantities used to be private but making them public
65  // allows for easy access to python interface as a "list"
66  int xsize_; // public (used to be private) size of vector
67  vector<T> data_; // public (used to be private) copy of data vector
68 
70  Array1D(): xsize_(0) {};
71 
73  Array1D(const int& nx): xsize_(nx) {
74  data_.resize(xsize_);
75  }
76 
78  Array1D(const int& nx, const T& t): xsize_(nx) {
79  data_.resize(xsize_, t);
80  }
81 
83  Array1D& operator=(const Array1D &obj) {
84  xsize_ = obj.xsize_;
85  data_ = obj.data_;
86  return *this;
87  }
88 
90  Array1D(const Array1D &obj): xsize_(obj.xsize_), data_(obj.data_) {};
91 
93  ~Array1D() {data_.clear();}
94 
96  void Clear() {
97  xsize_ = 0;
98  data_.clear();
99  }
100 
102  int XSize() const {return xsize_;}
103 
105  int Length() const {return xsize_;}
106 
108  void Resize(const int& nx) {
109  xsize_ = nx;
110  data_.resize(xsize_);
111  }
112 
115  void Resize(const int& nx, const T& t) {
116  data_.clear();
117  xsize_ = nx;
118  data_.resize(xsize_, t);
119  }
120 
122  void SetValue(const T& t){
123  for(int i=0; i < data_.size(); i++){
124  data_[i] = t;
125  }
126  }
127 
129  void PushBack(const T& t){
130  xsize_ += 1;
131  data_.push_back(t);
132  }
133 
138  return &(data_[0]);
139  }
140 
144  const T* GetConstArrayPointer() const {
145  return &(data_[0]);
146  }
147 
148  // allows access element by element, e.g. this(i) gives data_[i]
149  T& operator()(int ix) {return data_[ix];}
150  const T& operator()(int ix) const {return data_[ix];}
151 
154  void insert(Array1D<T>& insarr,int ix){
155  if (ix<0 || ix>xsize_){
156  throw Tantrum("Array1D:insert():: insert index out of bounds.");
157  }
158  int addsize = insarr.Length();
159  xsize_+=addsize;
160  T* ptr=insarr.GetArrayPointer();
161  data_.insert(data_.begin()+ix,ptr,ptr+addsize);
162  }
163 
166  void insert(const T& insval,int ix){
167  if (ix<0 || ix>xsize_)
168  throw Tantrum("Array1D:insert():: insert index out of bounds.");
169  xsize_+=1;
170  data_.insert(data_.begin()+ix,insval);
171  }
172 
174  void erase(int ix){
175  if (ix<0 || ix>=xsize_)
176  throw Tantrum("Array1D:erase():: erase index out of bounds.");
177  xsize_-=1;
178  data_.erase(data_.begin()+ix);
179  }
180 
182  void DumpBinary(FILE* f_out) const {
183  fwrite(&xsize_,sizeof(xsize_),1,f_out);
184  fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_,f_out);
185  }
186 
188  void ReadBinary(FILE* f_in){
189  fread(&xsize_,sizeof(xsize_),1,f_in);
190  data_.resize(xsize_);
191  fread(this->GetArrayPointer(),sizeof(T),xsize_,f_in);
192  }
193 
194  /**********************************************************
195  // Methods for interfacing with python
196  **********************************************************/
197 
198  // For calling [] in Python
199  T& operator[](int i) {return data_[i];}
200 
202  // cannot be read with numpy's fromfile after creation
203  void DumpBinary(char *filename){
204  FILE *f_out;
205  f_out = fopen(filename,"wb");
206  fwrite(&xsize_,sizeof(xsize_),1,f_out);
207  fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_,f_out);
208  fclose(f_out);
209  }
210 
211  // read binary file created with DumpBinary
212  // Cannot use numpy's from files
213  // only for use in c++
214  void ReadBinary(char *filename){
215  FILE *f_in;
216  f_in = fopen(filename,"rb");
217  fread(&xsize_,sizeof(xsize_),1,f_in);
218  data_.resize(xsize_);
219  fread(this->GetArrayPointer(),sizeof(T),xsize_,f_in);
220  fclose(f_in);
221  }
222 
223  // Following two methods are not compatable with certain clang comilers
224  // creates binary file that can be read with numpy's fromfile
225  void DumpBinary4py(char *filename){
226  ofstream f_out;
227  f_out.open(filename, ios::out | ios::binary);
228  f_out.write((char*)this->GetArrayPointer(),sizeof(T[xsize_])); // convert array pointer to char string
229  f_out.close();
230  }
231 
232  // can read in DumpBinary4py output, but needs size of vector
233  // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements
234  void ReadBinary4py(char *filename, int n){
235  xsize_ = n;
236  ifstream f_in;
237  f_in.open(filename, ios::in | ios::binary);
238  f_in.read((char*)this->GetArrayPointer(),sizeof(T[xsize_])); // convert array pointer to char string
239  f_in.close();
240  }
241 
242  // Set user-defined list to data_ vector
243  // This will work even for string type
244  void setArray(vector<T> inarray){
245  data_ = inarray;
246  xsize_ = inarray.size();
247  }
248 
249  // Returns data_ vector as a list in python
250  // Also acts as a print to see individual elements
251  vector<T> flatten(){
252  return data_;
253  }
254 
255  string type(){
256  return "string";
257  }
258 };
259 
260 template<>
261 class Array1D <int>{
262 private:
263  int xsize_; // private size of vector
264 public:
265  vector<int> data_; // private copy of data vector
266 
268  Array1D(): xsize_(0) {};
269 
271  Array1D(const int& nx): xsize_(nx) {
272  data_.resize(xsize_);
273  }
274 
276  Array1D(const int& nx, const int& t): xsize_(nx) {
277  data_.resize(xsize_, t);
278  }
279 
281  Array1D& operator=(const Array1D &obj) {
282  xsize_ = obj.xsize_;
283  data_ = obj.data_;
284  return *this;
285  }
286 
288  Array1D(const Array1D &obj): xsize_(obj.xsize_), data_(obj.data_) {};
289 
291  ~Array1D() {data_.clear();}
292 
294  void Clear() {
295  xsize_ = 0;
296  data_.clear();
297  }
298 
300  int XSize() const {return xsize_;}
301 
303  int Length() const {return xsize_;}
304 
306  void Resize(const int& nx) {
307  xsize_ = nx;
308  data_.resize(xsize_);
309  }
310 
313  void Resize(const int& nx, const int& t) {
314  data_.clear();
315  xsize_ = nx;
316  data_.resize(xsize_, t);
317  }
318 
320  void SetValue(const int& t){
321  for(int i=0; i < (int)data_.size(); i++){
322  data_[i] = t;
323  }
324  }
325 
327  void PushBack(const int& t){
328  xsize_ += 1;
329  data_.push_back(t);
330  }
331 
336  return &(data_[0]);
337  }
338 
342  const int* GetConstArrayPointer() const {
343  return &(data_[0]);
344  }
345 
346  // allows access element by element, e.g. this(i) gives data_[i]
347  int& operator()(int ix) {return data_[ix];}
348  const int& operator()(int ix) const {return data_[ix];}
349 
352  void insert(Array1D<int>& insarr,int ix){
353  if (ix<0 || ix>xsize_){
354  throw Tantrum("Array1D:insert():: insert index out of bounds.");
355  }
356  int addsize = insarr.Length();
357  xsize_+=addsize;
358  int* ptr=insarr.GetArrayPointer();
359  data_.insert(data_.begin()+ix,ptr,ptr+addsize);
360  }
361 
364  void insert(const int& insval,int ix){
365  if (ix<0 || ix>xsize_)
366  throw Tantrum("Array1D:insert():: insert index out of bounds.");
367  xsize_+=1;
368  data_.insert(data_.begin()+ix,insval);
369  }
370 
372  void erase(int ix){
373  if (ix<0 || ix>=xsize_)
374  throw Tantrum("Array1D:erase():: erase index out of bounds.");
375  xsize_-=1;
376  data_.erase(data_.begin()+ix);
377  }
378 
380  void DumpBinary(FILE* f_out) const {
381  fwrite(&xsize_,sizeof(xsize_),1,f_out);
382  fwrite(this->GetConstArrayPointer(),sizeof(int),xsize_,f_out);
383  }
384 
386  void ReadBinary(FILE* f_in){
387  fread(&xsize_,sizeof(xsize_),1,f_in);
388  data_.resize(xsize_);
389  fread(this->GetArrayPointer(),sizeof(int),xsize_,f_in);
390  }
391 
392  /**********************************************************
393  // Methods for interfacing with python
394  **********************************************************/
395 
396  // For calling [] in Python
397  int& operator[](int i) {return data_[i];}
398 
400  // cannot be read with numpy's fromfile after creation
401  void DumpBinary(char *filename){
402  FILE *f_out;
403  f_out = fopen(filename,"wb");
404  fwrite(&xsize_,sizeof(xsize_),1,f_out);
405  fwrite(this->GetConstArrayPointer(),sizeof(int),xsize_,f_out);
406  fclose(f_out);
407  }
408 
409  // read binary file created with DumpBinary
410  // Cannot use numpy's from files
411  // only for use in c++
412  void ReadBinary(char *filename){
413  FILE *f_in;
414  f_in = fopen(filename,"rb");
415  fread(&xsize_,sizeof(xsize_),1,f_in);
416  data_.resize(xsize_);
417  fread(this->GetArrayPointer(),sizeof(int),xsize_,f_in);
418  fclose(f_in);
419  }
420 
421  // creates binary file that can be read with numpy's fromfile
422  void DumpBinary4py(char *filename){
423  ofstream f_out;
424  f_out.open(filename, ios::out | ios::binary);
425  f_out.write((char*)this->GetArrayPointer(),xsize_*sizeof(int)); // convert array pointer to char string
426  f_out.close();
427  }
428 
429  // can read in DumpBinary4py output, but needs size of vector
430  // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements
431  void ReadBinary4py(char *filename, int n){
432  xsize_ = n;
433  ifstream f_in;
434  f_in.open(filename, ios::in | ios::binary);
435  f_in.read((char*)this->GetArrayPointer(),xsize_*sizeof(int)); // convert array pointer to char string
436  f_in.close();
437  }
438 
439  // Set user-defined list to data_ vector
440  // This will work even for string type
441  void setArray(vector<int> inarray){
442  data_ = inarray;
443  xsize_ = inarray.size();
444  }
445 
446  // // Sets user-defined 1d numpy array to data_ vector
447  void setnpintArray(long* inarray, int n){
448  xsize_ = n;
449  data_.assign(inarray,inarray+n);
450  }
451  // This is not to be used for a string type
452  void getnpintArray(long* outarray, int n){
453  // xsize_ = n;
454  // data_.assign(inarray,inarray+n);
455  copy(data_.begin(), data_.end(), outarray);
456  }
457 
458  // Returns data_ vector as a list in python
459  // Also acts as a print to see individual elements
460  vector<int> flatten(){
461  return data_;
462  }
463 
464  string type(){
465  return "int";
466  }
467 
468 };
469 
470 template<>
471 class Array1D <double> {
472 private:
473  int xsize_; // private size of vector
474 public:
475  vector<double> data_; // private copy of data vector
476 
477 
479  Array1D(): xsize_(0) {};
480 
482  Array1D(const int& nx): xsize_(nx) {
483  data_.resize(xsize_);
484  }
485 
487  Array1D(const int& nx, const double& t): xsize_(nx) {
488  data_.resize(xsize_, t);
489  }
490 
492  Array1D& operator=(const Array1D &obj) {
493  xsize_ = obj.xsize_;
494  data_ = obj.data_;
495  return *this;
496  }
497 
499  Array1D(const Array1D &obj): xsize_(obj.xsize_), data_(obj.data_) {};
500 
502  ~Array1D() {data_.clear();}
503 
505  void Clear() {
506  xsize_ = 0;
507  data_.clear();
508  }
509 
511  int XSize() const {return xsize_;}
512 
514  int Length() const {return xsize_;}
515 
517  void Resize(const int& nx) {
518  xsize_ = nx;
519  data_.resize(xsize_);
520  }
521 
524  void Resize(const int& nx, const double& t) {
525  data_.clear();
526  xsize_ = nx;
527  data_.resize(xsize_, t);
528  }
529 
531  void SetValue(const double& t){
532  for(int i=0; i < (int)data_.size(); i++){
533  data_[i] = t;
534  }
535  }
536 
538  void PushBack(const double& t){
539  xsize_ += 1;
540  data_.push_back(t);
541  }
542 
546  double* GetArrayPointer() {
547  return &(data_[0]);
548  }
549 
553  const double* GetConstArrayPointer() const {
554  return &(data_[0]);
555  }
556 
557  // allows access element by element, e.g. this(i) gives data_[i]
558  double& operator()(int ix) {return data_[ix];}
559  const double& operator()(int ix) const {return data_[ix];}
560 
563  void insert(Array1D<double>& insarr,int ix){
564  if (ix<0 || ix>xsize_){
565  throw Tantrum("Array1D:insert():: insert index out of bounds.");
566  }
567  int addsize = insarr.Length();
568  xsize_+=addsize;
569  double* ptr=insarr.GetArrayPointer();
570  data_.insert(data_.begin()+ix,ptr,ptr+addsize);
571  }
572 
575  void insert(const double& insval,int ix){
576  if (ix<0 || ix>xsize_)
577  throw Tantrum("Array1D:insert():: insert index out of bounds.");
578  xsize_+=1;
579  data_.insert(data_.begin()+ix,insval);
580  }
581 
583  void erase(int ix){
584  if (ix<0 || ix>=xsize_)
585  throw Tantrum("Array1D:erase():: erase index out of bounds.");
586  xsize_-=1;
587  data_.erase(data_.begin()+ix);
588  }
589 
591  void DumpBinary(FILE* f_out) const {
592  fwrite(&xsize_,sizeof(xsize_),1,f_out);
593  fwrite(this->GetConstArrayPointer(),sizeof(double),xsize_,f_out);
594  }
595 
597  void ReadBinary(FILE* f_in){
598  fread(&xsize_,sizeof(xsize_),1,f_in);
599  data_.resize(xsize_);
600  fread(this->GetArrayPointer(),sizeof(double),xsize_,f_in);
601  }
602 
603  /**********************************************************
604  // Methods for interfacing with python
605  **********************************************************/
606 
607  // For calling [] in Python
608  double& operator[](int i) {return data_[i];}
609 
611  // cannot be read with numpy's fromfile after creation
612  void DumpBinary(char *filename){
613  FILE *f_out;
614  f_out = fopen(filename,"wb");
615  fwrite(&xsize_,sizeof(xsize_),1,f_out);
616  fwrite(this->GetConstArrayPointer(),sizeof(double),xsize_,f_out);
617  fclose(f_out);
618  }
619 
620  // read binary file created with DumpBinary
621  // Cannot use numpy's from files
622  // only for use in c++
623  void ReadBinary(char *filename){
624  FILE *f_in;
625  f_in = fopen(filename,"rb");
626  fread(&xsize_,sizeof(xsize_),1,f_in);
627  data_.resize(xsize_);
628  fread(this->GetArrayPointer(),sizeof(double),xsize_,f_in);
629  fclose(f_in);
630  }
631 
632  // creates binary file that can be read with numpy's fromfile
633  void DumpBinary4py(char *filename){
634  ofstream f_out;
635  f_out.open(filename, ios::out | ios::binary);
636  f_out.write((char*)this->GetArrayPointer(),xsize_*sizeof(double)); // convert array pointer to char string
637  f_out.close();
638  }
639 
640  // can read in DumpBinary4py output, but needs size of vector
641  // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements
642  void ReadBinary4py(char *filename, int n){
643  xsize_ = n;
644  ifstream f_in;
645  f_in.open(filename, ios::in | ios::binary);
646  f_in.read((char*)this->GetArrayPointer(),xsize_*sizeof(double)); // convert array pointer to char string
647  f_in.close();
648  }
649 
650  // Set user-defined list to data_ vector
651  // This will work even for string type
652  void setArray(vector<double> inarray){
653  data_ = inarray;
654  xsize_ = inarray.size();
655  }
656 
657  // Sets user-defined 1d numpy array to data_ vector
658  // This is not to be used for a string type
659  void setnpdblArray(double* inarray, int n){
660  xsize_ = n;
661  data_.assign(inarray,inarray+n);
662  }
663  // Sets user-defined 1d numpy array to data_ vector
664  // This is not to be used for a string type
665  void getnpdblArray(double* outarray, int n){
666  // xsize_ = n;
667  // data_.assign(inarray,inarray+n);
668  copy(data_.begin(), data_.end(), outarray);
669  }
670 
671  // Returns data_ vector as a list in python
672  // Also acts as a print to see individual elements
673  vector<double> flatten(){
674  return data_;
675  }
676 
677  string type(){
678  return "double";
679  }
680 };
681 
682 #endif /* ARRAY1D_H_SEEN */
Stores data of any type T in a 1D array.
Definition: Array1D.h:60
+
void getnpintArray(long *outarray, int n)
Definition: Array1D.h:452
+
T * GetArrayPointer()
Return a pointer to the first element of the data in the vector so we can use it access the data in a...
Definition: Array1D.h:137
+
vector< T > data_
Definition: Array1D.h:67
+
Array1D(const int &nx, const double &t)
Constructor that allocates and initializes the data to a value t.
Definition: Array1D.h:487
+
int XSize() const
Returns size in the x-direction.
Definition: Array1D.h:300
+
void setnpintArray(long *inarray, int n)
Definition: Array1D.h:447
+
void insert(Array1D< double > &insarr, int ix)
Insert a given array to the position ix.
Definition: Array1D.h:563
+
void insert(const int &insval, int ix)
Insert a given value to the position ix.
Definition: Array1D.h:364
+
void SetValue(const T &t)
Set all values in the array to the given value.
Definition: Array1D.h:122
+
void ReadBinary4py(char *filename, int n)
Definition: Array1D.h:642
+
Array1D()
Default constructor, which does not allocate any memory.
Definition: Array1D.h:70
+
Array1D(const int &nx)
Constructor that allocates the memory.
Definition: Array1D.h:482
+
void erase(int ix)
Erase the value from the position ix.
Definition: Array1D.h:583
+
T & operator[](int i)
Definition: Array1D.h:199
+
int XSize() const
Returns size in the x-direction.
Definition: Array1D.h:511
+
void Clear()
Function to clear the memory.
Definition: Array1D.h:505
+
void ReadBinary(char *filename)
Definition: Array1D.h:623
+
void setArray(vector< double > inarray)
Definition: Array1D.h:652
+
int Length() const
Returns length (i.e. size in the x-direction)
Definition: Array1D.h:303
+
void ReadBinary(char *filename)
Definition: Array1D.h:214
+
int Length() const
Returns length (i.e. size in the x-direction)
Definition: Array1D.h:514
+
Array1D()
Default constructor, which does not allocate any memory.
Definition: Array1D.h:268
+
int & operator[](int i)
Definition: Array1D.h:397
+
void Resize(const int &nx, const T &t)
Resizes the array and sets ALL entries to the specified value.
Definition: Array1D.h:115
+
Array1D(const Array1D &obj)
Copy constructor.
Definition: Array1D.h:288
+ +
void Resize(const int &nx)
Resizes the array.
Definition: Array1D.h:517
+
string type()
Definition: Array1D.h:677
+
void ReadBinary(FILE *f_in)
Read contents of the array from a file in binary format.
Definition: Array1D.h:386
+
int Length() const
Returns length (i.e. size in the x-direction)
Definition: Array1D.h:105
+
void insert(const double &insval, int ix)
Insert a given value to the position ix.
Definition: Array1D.h:575
+
double & operator[](int i)
Definition: Array1D.h:608
+
void insert(Array1D< int > &insarr, int ix)
Insert a given array to the position ix.
Definition: Array1D.h:352
+
void DumpBinary(FILE *f_out) const
Dump contents of the array to a file in binary format.
Definition: Array1D.h:380
+
void ReadBinary(FILE *f_in)
Read contents of the array from a file in binary format.
Definition: Array1D.h:188
+
Array1D & operator=(const Array1D &obj)
Assignment operator copies the data structure by value.
Definition: Array1D.h:492
+
int XSize() const
Returns size in the x-direction.
Definition: Array1D.h:102
+
Definition: Array1D.h:471
+
const int * GetConstArrayPointer() const
Return a const point to the first element of the data in the vector so we can use it access the data ...
Definition: Array1D.h:342
+
Array1D()
Default constructor, which does not allocate any memory.
Definition: Array1D.h:479
+
int xsize_
Definition: Array1D.h:66
+
Array1D(const Array1D &obj)
Copy constructor.
Definition: Array1D.h:499
+
~Array1D()
Destructor that frees up the memory.
Definition: Array1D.h:93
+
void Resize(const int &nx, const double &t)
Resizes the array and sets ALL entries to the specified value.
Definition: Array1D.h:524
+
void PushBack(const T &t)
Add element to the end of the vector.
Definition: Array1D.h:129
+
vector< int > data_
Definition: Array1D.h:265
+
void setArray(vector< T > inarray)
Definition: Array1D.h:244
+
void ReadBinary4py(char *filename, int n)
Definition: Array1D.h:431
+
~Array1D()
Destructor that frees up the memory.
Definition: Array1D.h:291
+
Array1D< double > copy(Array1D< double > &in_array)
Returns a copy of 1D array.
Definition: arraytools.cpp:1583
+
void insert(const T &insval, int ix)
Insert a given value to the position ix.
Definition: Array1D.h:166
+
void SetValue(const double &t)
Set all values in the array to the given value.
Definition: Array1D.h:531
+
Array1D(const int &nx)
Constructor that allocates the memory.
Definition: Array1D.h:73
+
void PushBack(const double &t)
Add element to the end of the vector.
Definition: Array1D.h:538
+
Array1D(const int &nx, const T &t)
Constructor that allocates and initializes the data to a value t.
Definition: Array1D.h:78
+
const double * GetConstArrayPointer() const
Return a const point to the first element of the data in the vector so we can use it access the data ...
Definition: Array1D.h:553
+
Array1D & operator=(const Array1D &obj)
Assignment operator copies the data structure by value.
Definition: Array1D.h:83
+
void SetValue(const int &t)
Set all values in the array to the given value.
Definition: Array1D.h:320
+
vector< int > flatten()
Definition: Array1D.h:460
+
int * GetArrayPointer()
Return a pointer to the first element of the data in the vector so we can use it access the data in a...
Definition: Array1D.h:335
+
Array1D(const int &nx, const int &t)
Constructor that allocates and initializes the data to a value t.
Definition: Array1D.h:276
+
vector< double > flatten()
Definition: Array1D.h:673
+
Definition: Array1D.h:261
+
void setnpdblArray(double *inarray, int n)
Definition: Array1D.h:659
+
void Clear()
Function to clear the memory.
Definition: Array1D.h:294
+
Array1D(const int &nx)
Constructor that allocates the memory.
Definition: Array1D.h:271
+
void setArray(vector< int > inarray)
Definition: Array1D.h:441
+
~Array1D()
Destructor that frees up the memory.
Definition: Array1D.h:502
+
void Resize(const int &nx, const int &t)
Resizes the array and sets ALL entries to the specified value.
Definition: Array1D.h:313
+
const T * GetConstArrayPointer() const
Return a const point to the first element of the data in the vector so we can use it access the data ...
Definition: Array1D.h:144
+
Array1D(const Array1D &obj)
Copy constructor.
Definition: Array1D.h:90
+
void DumpBinary(char *filename)
Dump contents of the array to a file in binary format.
Definition: Array1D.h:203
+
void ReadBinary4py(char *filename, int n)
Definition: Array1D.h:234
+
const double & operator()(int ix) const
Definition: Array1D.h:559
+
void PushBack(const int &t)
Add element to the end of the vector.
Definition: Array1D.h:327
+
int xsize_
Definition: Array1D.h:473
+
void DumpBinary4py(char *filename)
Definition: Array1D.h:633
+
const int & operator()(int ix) const
Definition: Array1D.h:348
+
void DumpBinary(FILE *f_out) const
Dump contents of the array to a file in binary format.
Definition: Array1D.h:591
+
T & operator()(int ix)
Definition: Array1D.h:149
+
void erase(int ix)
Erase the value from the position ix.
Definition: Array1D.h:174
+
void DumpBinary(FILE *f_out) const
Dump contents of the array to a file in binary format.
Definition: Array1D.h:182
+
void DumpBinary4py(char *filename)
Definition: Array1D.h:225
+
void Resize(const int &nx)
Resizes the array.
Definition: Array1D.h:306
+
void DumpBinary(char *filename)
Dump contents of the array to a file in binary format.
Definition: Array1D.h:612
+
void insert(Array1D< T > &insarr, int ix)
Insert a given array to the position ix.
Definition: Array1D.h:154
+
double * GetArrayPointer()
Return a pointer to the first element of the data in the vector so we can use it access the data in a...
Definition: Array1D.h:546
+
void erase(int ix)
Erase the value from the position ix.
Definition: Array1D.h:372
+
string type()
Definition: Array1D.h:464
+
void ReadBinary(char *filename)
Definition: Array1D.h:412
+
Array1D & operator=(const Array1D &obj)
Assignment operator copies the data structure by value.
Definition: Array1D.h:281
+
string type()
Definition: Array1D.h:255
+
void DumpBinary4py(char *filename)
Definition: Array1D.h:422
+
const T & operator()(int ix) const
Definition: Array1D.h:150
+
int & operator()(int ix)
Definition: Array1D.h:347
+
void DumpBinary(char *filename)
Dump contents of the array to a file in binary format.
Definition: Array1D.h:401
+
int xsize_
Definition: Array1D.h:263
+
double & operator()(int ix)
Definition: Array1D.h:558
+
void Clear()
Function to clear the memory.
Definition: Array1D.h:96
+
void ReadBinary(FILE *f_in)
Read contents of the array from a file in binary format.
Definition: Array1D.h:597
+
vector< T > flatten()
Definition: Array1D.h:251
+
void getnpdblArray(double *outarray, int n)
Definition: Array1D.h:665
+
vector< double > data_
Definition: Array1D.h:475
+
void Resize(const int &nx)
Resizes the array.
Definition: Array1D.h:108
+
+ + + + diff --git a/doc/doxygen/html/Array2D_8h.html b/doc/doxygen/html/Array2D_8h.html new file mode 100644 index 00000000..87fde3a8 --- /dev/null +++ b/doc/doxygen/html/Array2D_8h.html @@ -0,0 +1,82 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array2D.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
Array2D.h File Reference
+
+
+ +

2D Array class for any type T +More...

+
#include <stddef.h>
+#include <cstdio>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <iterator>
+#include <algorithm>
+#include <typeinfo>
+#include "Array1D.h"
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  Array2D< T >
 Stores data of any type T in a 2D array. More...
 
+

Detailed Description

+

2D Array class for any type T

+
+ + + + diff --git a/doc/doxygen/html/Array2D_8h_source.html b/doc/doxygen/html/Array2D_8h_source.html new file mode 100644 index 00000000..c10d86a4 --- /dev/null +++ b/doc/doxygen/html/Array2D_8h_source.html @@ -0,0 +1,106 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array2D.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
Array2D.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
29 
30 
31 #ifndef ARRAY2D_H_SEEN
32 #define ARRAY2D_H_SEEN
33 
34 #include <stddef.h>
35 #include <cstdio>
36 #include <vector>
37 #include <iostream>
38 #include <fstream>
39 #include <iterator>
40 #include <algorithm>
41 #include <typeinfo>
42 #include "Array1D.h"
43 
44 using namespace std;
45 
56 // COLUMN MAJOR FORMAT
57 
58 template<typename T>
59 class Array2D{
60 private:
61 
62 public:
63  // These two quantities used to be private but making them public
64  // allows for easy access to python interface as a "list"
65  int xsize_;
66  int ysize_;
67  vector<T> data_;
70 
72  Array2D(): xsize_(0), ysize_(0) {};
73 
75  Array2D(const int& nx, const int& ny): xsize_(nx), ysize_(ny){
76  data_.resize(xsize_*ysize_);
77  }
78 
80  Array2D(const int& nx, const int& ny, const T& t): xsize_(nx), ysize_(ny){
81  data_.resize(xsize_*ysize_ , t);
82  }
83 
85  Array2D(const Array2D &obj): xsize_(obj.xsize_), ysize_(obj.ysize_), data_(obj.data_) {};
86 
88  ~Array2D() {data_.clear();}
89 
91  void Clear() {
92  xsize_ = 0;
93  ysize_ = 0;
94  data_.clear();
95  }
96 
98  int XSize() const {return xsize_;}
100  int YSize() const {return ysize_;}
101 
104  void Resize(const int& nx, const int& ny) {
105  xsize_ = nx;
106  ysize_ = ny;
107  data_.resize(xsize_*ysize_);
108  }
109 
112  void Resize(const int& nx, const int& ny, const T& t) {
113  data_.clear();
114  xsize_ = nx;
115  ysize_ = ny;
116  data_.resize(xsize_*ysize_, t);
117  }
118 
120  void SetValue(const T& t){
121  for(int i=0; i < data_.size(); i++){
122  data_[i] = t;
123  }
124  }
125 
130  return &(data_[0]);
131  }
132 
136  const T* GetConstArrayPointer() const {
137  return &(data_[0]);
138  }
139 
141  // values accessed in a row-major format
142  T& operator()(int ix,int iy) {return data_[ix + xsize_*iy];}
143  const T& operator()(int ix,int iy) const {return data_[ix + xsize_*iy];}
144 
146  void insertRow(Array1D<T>& insarr,int ix){
147  if (ix<0 || ix>xsize_)
148  throw Tantrum("Array2D:insertRow():: insert index out of bounds.");
149  if ( insarr.Length() != ysize_ )
150  throw Tantrum("Array2D:insertRow():: insert row size does not match.");
151 
152  vector<T> data_old;
153  data_old=data_;
154 
155  xsize_ += 1; // new number of rows
156  data_.resize(xsize_*ysize_);
157 
158  for(int iy=0;iy<ysize_;iy++){
159  for(int i=0; i < ix; i++)
160  data_[i+xsize_*iy] = data_old[i+(xsize_-1)*iy];
161  data_[ix+xsize_*iy]=insarr(iy);
162  for(int i=ix+1; i < xsize_; i++)
163  data_[i+xsize_*iy] = data_old[i-1+(xsize_-1)*iy];
164  }
165  }
166 
168  void insertRow(Array2D<T>& insarr,int ix){
169  if (ix<0 || ix>xsize_)
170  throw Tantrum("Array2D:insertRow():: insert index out of bounds.");
171  if ( insarr.YSize() != ysize_ )
172  throw Tantrum("Array2D:insertRow():: insert row size does not match.");
173 
174  vector<T> data_old;
175  data_old=data_;
176 
177  int insx=insarr.XSize();
178 
179  xsize_ += insx;
180  data_.resize(xsize_*ysize_);
181 
182  for(int iy=0;iy<ysize_;iy++){
183  for(int i=0; i < ix; i++)
184  data_[i+xsize_*iy] = data_old[i+(xsize_-insx)*iy];
185  for(int i=ix; i < ix+insx; i++)
186  data_[i+xsize_*iy]=insarr(i-ix,iy);
187  for(int i=ix+insx; i < xsize_; i++)
188  data_[i+xsize_*iy] = data_old[i-insx+(xsize_-insx)*iy];
189  }
190  }
191 
193  void eraseRow(int ix){
194  if (ix<0 || ix>=xsize_)
195  throw Tantrum("Array2D:eraseRow():: erase index out of bounds.");
196 
197  vector<T> data_old;
198  data_old=data_;
199 
200  xsize_-=1;
201  data_.resize(xsize_*ysize_);
202 
203  for(int iy=0;iy<ysize_;iy++){
204  for(int i=0; i < ix; i++)
205  data_[i+xsize_*iy] = data_old[i+(xsize_+1)*iy];
206  for(int i=ix; i < xsize_; i++)
207  data_[i+xsize_*iy] = data_old[i+1+(xsize_+1)*iy];
208  }
209 
210  //if (xsize_==0)
211  // printf("eraseRow(): WARNING: the xsize is zeroed!");
212 
213  }
214 
215  // /// \brief Insert array insarr as a column into position iy
216  void insertCol(Array1D<T>& insarr,int iy){
217  if (iy<0 || iy>ysize_)
218  throw Tantrum("Array2D:insertCol():: insert index out of bounds.");
219  if ( insarr.Length() != xsize_ )
220  throw Tantrum("Array2D:insertCol():: insert column size does not match.");
221 
222 
223  T* ptr=insarr.GetArrayPointer();
224  data_.insert(data_.begin()+xsize_*iy,ptr,ptr+xsize_);
225 
226  ysize_+=1;
227 
228  }
229 
231  void insertCol(Array2D<T>& insarr,int iy){
232  if (iy<0 || iy>ysize_)
233  throw Tantrum("Array2D:insertCol():: insert index out of bounds.");
234  if ( insarr.XSize() != xsize_ )
235  throw Tantrum("Array2D:insertRow():: insert column size does not match.");
236 
237  int insy=insarr.YSize();
238 
239  T* ptr=insarr.GetArrayPointer();
240  data_.insert(data_.begin()+xsize_*iy,ptr,ptr+xsize_*insy);
241 
242  ysize_+=insy;
243  }
244 
246  void eraseCol(int iy){
247  if (iy<0 || iy>=ysize_)
248  throw Tantrum("Array2D:eraseCol():: erase index out of bounds.");
249 
250  data_.erase(data_.begin()+xsize_*iy,data_.begin()+xsize_*(iy+1));
251 
252  ysize_-=1;
253 
254  //if (ysize_==0)
255  // printf("eraseCol(): WARNING: the ysize is zeroed!");
256 
257  }
258 
260  void DumpBinary(FILE* f_out) const {
261  fwrite(&xsize_,sizeof(xsize_),1,f_out);
262  fwrite(&ysize_,sizeof(ysize_),1,f_out);
263  fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_*ysize_,f_out);
264  }
265 
266 
268  void ReadBinary(FILE* f_in){
269  fread(&xsize_,sizeof(xsize_),1,f_in);
270  fread(&ysize_,sizeof(ysize_),1,f_in);
271  data_.resize(xsize_*ysize_);
272  fread(this->GetArrayPointer(),sizeof(T),xsize_*ysize_,f_in);
273  }
274 
275  /********************************************************
276  // Methods for interfacing with python
277  ********************************************************/
278 
279  // assignment operator []
280  // allows for calling Array2D using [i][j] notation
281  // make more efficient by setting two vectors equal
283  // get the ith row
284  int stride = xsize_;
285  rowvec.Resize(ysize_);
286  for (int iy = 0; iy < ysize_; iy++){
287  rowvec(iy) = data_[ix + stride*iy];
288  }
289  return rowvec;
290  }
291 
292  void getRow(int row){
293  arraycopy.Resize(ysize_,0);
294  int stride = xsize_;
295  for (int i = 0; i < ysize_; i++){
296  arraycopy[i] = data_[i*stride + row];
297  }
298  }
299 
300  // read binary file created with DumpBinary
301  // Cannot use numpy's from files
302  // only for use in c++
303  void DumpBinary(char *filename){
304  FILE *f_out;
305  f_out = fopen(filename,"wb");
306  fwrite(&xsize_,sizeof(xsize_),1,f_out);
307  fwrite(&ysize_,sizeof(ysize_),1,f_out);
308  fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_*ysize_,f_out);
309  fclose(f_out);
310  }
311 
312  // Only for use if DumpBinary was used
313  // can only be read in c++
314  // can be opened with ReadBinary(FILE* file) above
315  void ReadBinary(char *filename){
316  FILE *f_in;
317  f_in = fopen(filename,"rb");
318  fread(&xsize_,sizeof(xsize_),1,f_in);
319  fread(&ysize_,sizeof(ysize_),1,f_in);
320  data_.resize(xsize_*ysize_);
321  fread(this->GetArrayPointer(),sizeof(T),xsize_*ysize_,f_in);
322  fclose(f_in);
323  }
324 
325  // creates binary file that can be read with numpy's fromfile
326  void DumpBinary4py(char *filename){
327  ofstream f_out;
328  f_out.open(filename, ios::out | ios::binary);
329  f_out.write((char*)this->GetArrayPointer(),sizeof(T[xsize_*ysize_])); // convert array pointer to char string
330  f_out.close();
331  }
332 
333  // can read in DumpBinary4py output, but needs size of vector
334  // fromfile can automatically detect size file, so, if need by, one can use numpy's fromfile to determine # of elements
335  void ReadBinary4py(char *filename, int n1, int n2){
336  xsize_ = n1;
337  ysize_ = n2;
338  ifstream f_in;
339  f_in.open(filename, ios::in | ios::binary);
340  f_in.read((char*)this->GetArrayPointer(),sizeof(T[xsize_*ysize_])); // convert array pointer to char string
341  f_in.close();
342  }
343 
344  // Set user-defined list to data_ vector
345  // This will work even for string type
346  void setArray(vector<T> inarray){
347  data_ = inarray;
348  // xsize_ = inarray.size();
349  }
350 
351  // Sets user-defined 2d numpy array to data_ vector
352  // This is not to be used for a string type
353  void setnpdblArray(double* inarray, int n1, int n2){
354  xsize_ = n1;
355  ysize_ = n2;
356  data_.assign(inarray,inarray+n1*n2);
357  }
358 
359  // get numpy double array from data_ vector
360  void getnpdblArray(double* outarray, int n1, int n2){
361  copy(data_.begin(), data_.end(), outarray);
362  }
363 
364  // Sets user-defined 2d numpy array to data_ vector
365  // This is not to be used for a string type
366  void setnpintArray(long* inarray, int n1, int n2){
367  xsize_ = n1;
368  ysize_ = n2;
369  data_.assign(inarray,inarray+n1*n2);
370  }
371 
372  // get numpy double array from data_ vector
373  void getnpintArray(long* outarray, int n1, int n2){
374  copy(data_.begin(), data_.end(), outarray);
375  }
376 
377  // Returns data_ vector as a list in python in row-major (?)
378  // Also acts as a print to see individual elements
379  vector<T> flatten(){
380  return data_;
381  }
382 
383  string type(){
384  const char* s = typeid(data_[0]).name();
385  if (string(s) == string("Ss") ){
386  return "string";
387  }
388  else if (strcmp(s,"i") == 0){
389  return "int";
390  }
391  else {
392  return "double";
393  }
394  }
395 };
396 
397 #endif /* ARRAY2D_H_SEEN */
Stores data of any type T in a 1D array.
Definition: Array1D.h:60
+
T * GetArrayPointer()
Return a pointer to the first element of the data in the vector so we can use it access the data in a...
Definition: Array1D.h:137
+
string type()
Definition: Array2D.h:383
+
void insertCol(Array2D< T > &insarr, int iy)
Insert a 2d-array insarr into a column position iy.
Definition: Array2D.h:231
+
void Clear()
Function to clear the memory.
Definition: Array2D.h:91
+
void ReadBinary(FILE *f_in)
Read contents of the array from a file in binary format.
Definition: Array2D.h:268
+
void SetValue(const T &t)
Set all values in the array to the given value.
Definition: Array2D.h:120
+
void DumpBinary(char *filename)
Definition: Array2D.h:303
+
Array1D< T > & operator[](int ix)
Definition: Array2D.h:282
+
int xsize_
Definition: Array2D.h:65
+
void setnpdblArray(double *inarray, int n1, int n2)
Definition: Array2D.h:353
+ +
vector< T > data_
Definition: Array2D.h:67
+
Array1D< T > arraycopy
Definition: Array2D.h:68
+
int Length() const
Returns length (i.e. size in the x-direction)
Definition: Array1D.h:105
+
const T & operator()(int ix, int iy) const
Definition: Array2D.h:143
+
void eraseRow(int ix)
Erase the row ix.
Definition: Array2D.h:193
+
const T * GetConstArrayPointer() const
Return a cont point to the first element of the data in the vector so we can use it access the data i...
Definition: Array2D.h:136
+
~Array2D()
Destructor that frees up the memory.
Definition: Array2D.h:88
+
void eraseCol(int iy)
Erase the column iy.
Definition: Array2D.h:246
+
void setnpintArray(long *inarray, int n1, int n2)
Definition: Array2D.h:366
+
Stores data of any type T in a 2D array.
Definition: Array2D.h:59
+
Array1D< double > copy(Array1D< double > &in_array)
Returns a copy of 1D array.
Definition: arraytools.cpp:1583
+
void DumpBinary(FILE *f_out) const
Dump contents of the array to a file in binary format.
Definition: Array2D.h:260
+
void ReadBinary4py(char *filename, int n1, int n2)
Definition: Array2D.h:335
+
void Resize(const int &nx, const int &ny)
Resizes the array.
Definition: Array2D.h:104
+
int XSize() const
Returns size in the x-direction.
Definition: Array2D.h:98
+
void setArray(vector< T > inarray)
Definition: Array2D.h:346
+
T * GetArrayPointer()
Return a pointer to the first element of the data in the vector so we can use it access the data in a...
Definition: Array2D.h:129
+
Array2D(const int &nx, const int &ny)
Constructor that allocates the memory.
Definition: Array2D.h:75
+
void getnpdblArray(double *outarray, int n1, int n2)
Definition: Array2D.h:360
+
void insertRow(Array2D< T > &insarr, int ix)
Insert a 2d-array insarr into a row position ix.
Definition: Array2D.h:168
+
void DumpBinary4py(char *filename)
Definition: Array2D.h:326
+
int ysize_
Definition: Array2D.h:66
+
void Resize(const int &nx, const int &ny, const T &t)
Resizes the array and sets ALL entries to the specified value.
Definition: Array2D.h:112
+
Array2D(const Array2D &obj)
Copy constructor.
Definition: Array2D.h:85
+
Array1D< T > rowvec
Definition: Array2D.h:69
+
int YSize() const
Returns size in the y-direction.
Definition: Array2D.h:100
+
Array2D(const int &nx, const int &ny, const T &t)
Constructor that allocates and initializes the data to a constant t.
Definition: Array2D.h:80
+
vector< T > flatten()
Definition: Array2D.h:379
+
void ReadBinary(char *filename)
Definition: Array2D.h:315
+
T & operator()(int ix, int iy)
C-like () operator to access values in the 2D data array.
Definition: Array2D.h:142
+
void getnpintArray(long *outarray, int n1, int n2)
Definition: Array2D.h:373
+
void insertCol(Array1D< T > &insarr, int iy)
Definition: Array2D.h:216
+
void insertRow(Array1D< T > &insarr, int ix)
Insert array insarr as a row into position ix.
Definition: Array2D.h:146
+
void getRow(int row)
Definition: Array2D.h:292
+
1D Array class for any type T
+
Array2D()
Default constructor, which does not allocate any memory.
Definition: Array2D.h:72
+
void Resize(const int &nx)
Resizes the array.
Definition: Array1D.h:108
+
+ + + + diff --git a/doc/doxygen/html/Array3D_8h.html b/doc/doxygen/html/Array3D_8h.html new file mode 100644 index 00000000..bdbd1594 --- /dev/null +++ b/doc/doxygen/html/Array3D_8h.html @@ -0,0 +1,79 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array3D.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
Array3D.h File Reference
+
+
+ +

3D Array class for any type T +More...

+
#include <stddef.h>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <iterator>
+#include <algorithm>
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  Array3D< T >
 Stores data of any type T in a 3D array. More...
 
+

Detailed Description

+

3D Array class for any type T

+
+ + + + diff --git a/doc/doxygen/html/Array3D_8h_source.html b/doc/doxygen/html/Array3D_8h_source.html new file mode 100644 index 00000000..c5791fb4 --- /dev/null +++ b/doc/doxygen/html/Array3D_8h_source.html @@ -0,0 +1,83 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array3D.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
Array3D.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
29 
30 
31 #ifndef ARRAY3D_H_SEEN
32 #define ARRAY3D_H_SEEN
33 
34 #include <stddef.h>
35 #include <vector>
36 #include <iostream>
37 #include <fstream>
38 #include <iterator>
39 #include <algorithm>
40 
41 using namespace std;
42 
54 template <typename T>
55 class Array3D {
56  public:
58  Array3D(): xsize_(0), ysize_(0), zsize_(0) {};
59 
61  Array3D(const size_t& nx, const size_t& ny, const size_t& nz):
62  xsize_(nx), ysize_(ny), zsize_(nz) {
63  data_.resize(xsize_*ysize_*zsize_);
64  }
65 
67  Array3D(const size_t& nx, const size_t& ny, const size_t& nz, const T& t):
68  xsize_(nx), ysize_(ny), zsize_(nz) {
69  data_.resize(xsize_*ysize_*zsize_ , t);
70  }
71 
73  ~Array3D() {data_.clear();}
74 
76  void Clear() {
77  xsize_ = 0;
78  ysize_ = 0;
79  zsize_ = 0;
80  data_.clear();
81  }
82 
84  size_t XSize() const {return xsize_;}
86  size_t YSize() const {return ysize_;}
88  size_t ZSize() const {return zsize_;}
89 
97  void Resize(const size_t& nx, const size_t& ny, const size_t& nz) {
98  xsize_ = nx;
99  ysize_ = ny;
100  zsize_ = nz;
101  data_.resize(xsize_*ysize_*zsize_);
102  }
103 
109  void Resize(const size_t& nx, const size_t& ny, const size_t& nz, const T& t) {
110  data_.clear();
111  xsize_ = nx;
112  ysize_ = ny;
113  zsize_ = nz;
114  data_.resize(xsize_*ysize_*zsize_ , t);
115  }
116 
118  void SetValue(const T& t){
119  for(size_t i=0; i < data_.size(); i++){
120  data_[i] = t;
121  }
122  }
123 
128  return &(data_[0]);
129  }
130 
134  const T* GetConstArrayPointer() const {
135  return &(data_[0]);
136  }
137 
143  T& operator()(size_t ix, size_t iy, size_t iz) {return data_[ix+xsize_*(iy+ysize_*iz)];}
144 
150  const T& operator()(size_t ix, size_t iy, size_t iz) const {return data_[ix+xsize_*(iy+ysize_*iz)];}
151 
153  void DumpBinary(FILE* f_out) const {
154  fwrite(&xsize_,sizeof(xsize_),1,f_out);
155  fwrite(&ysize_,sizeof(ysize_),1,f_out);
156  fwrite(&zsize_,sizeof(zsize_),1,f_out);
157  fwrite(this->GetConstArrayPointer(),sizeof(T),xsize_*ysize_*zsize_,f_out);
158  }
159 
164  void DumpText(std::ofstream& f_out) const {
165  vector<double>::const_iterator it1;
166  vector<double>::const_iterator it2;
167  it2=data_.begin();
168 
169  for (int iz=0;iz<zsize_;iz++) {
170  for (int iy=0;iy<ysize_;iy++) {
171  it1=it2;
172  advance(it2,xsize_);
173  std::copy(it1,it2,std::ostream_iterator<T>(f_out," "));
174  f_out << endl;
175  }
176  }
177 
178  }
179 
181  void ReadText(FILE* f_in){
182  fread(&xsize_,sizeof(xsize_),1,f_in);
183  fread(&ysize_,sizeof(ysize_),1,f_in);
184  fread(&zsize_,sizeof(zsize_),1,f_in);
185  data_.resize(xsize_*ysize_*zsize_);
186  fread(this->GetArrayPointer(),sizeof(T),xsize_*ysize_*zsize_,f_in);
187  }
188 
191  void ReadBinary(std::ifstream& f_in){
192 
193  typedef std::istream_iterator<T> istream_iterator;
194  std::copy(istream_iterator(f_in),istream_iterator(),data_.begin());
195  }
196 
197 
198  private:
199 
202  Array3D(const Array3D &obj) {};
203 
205  size_t xsize_;
207  size_t ysize_;
209  size_t zsize_;
210 
216  vector<T> data_;
217 };
218 
219 #endif /* ARRAY3D_H_SEEN */
~Array3D()
Destructor that frees up the memory.
Definition: Array3D.h:73
+
Array3D(const size_t &nx, const size_t &ny, const size_t &nz)
Constructor that allocates the memory.
Definition: Array3D.h:61
+
size_t YSize() const
Returns size in the y-direction.
Definition: Array3D.h:86
+
void ReadBinary(std::ifstream &f_in)
Read contents of the array from a file in text format Added by Maher Salloum.
Definition: Array3D.h:191
+
void SetValue(const T &t)
Set all values in the array to the given value.
Definition: Array3D.h:118
+
T & operator()(size_t ix, size_t iy, size_t iz)
Fortran-like () operator to access values in the 3D data array.
Definition: Array3D.h:143
+
void DumpBinary(FILE *f_out) const
Dump contents of the array to a file in binary format.
Definition: Array3D.h:153
+
const T & operator()(size_t ix, size_t iy, size_t iz) const
Fortran-like () const operator to access values in the 3D data array.
Definition: Array3D.h:150
+
void Resize(const size_t &nx, const size_t &ny, const size_t &nz, const T &t)
Resizes the array and sets ALL entries to the specified value.
Definition: Array3D.h:109
+ +
size_t zsize_
Number of elements in the z-dimension.
Definition: Array3D.h:209
+
void DumpText(std::ofstream &f_out) const
Dump contents of the array to a file in text format Added by Maher Salloum When post-processing (in m...
Definition: Array3D.h:164
+
void Resize(const size_t &nx, const size_t &ny, const size_t &nz)
Resizes the array.
Definition: Array3D.h:97
+
Array1D< double > copy(Array1D< double > &in_array)
Returns a copy of 1D array.
Definition: arraytools.cpp:1583
+
size_t ZSize() const
Returns size in the z-direction.
Definition: Array3D.h:88
+
Array3D(const size_t &nx, const size_t &ny, const size_t &nz, const T &t)
Constructor that allocates and initializes the data.
Definition: Array3D.h:67
+
const T * GetConstArrayPointer() const
Return a const pointer to the first element of the data in the vector so we can use it access the dat...
Definition: Array3D.h:134
+
size_t XSize() const
Returns size in the x-direction.
Definition: Array3D.h:84
+
size_t xsize_
Number of elements in the x-dimension.
Definition: Array3D.h:202
+
T * GetArrayPointer()
Return a pointer to the first element of the data in the vector so we can use it access the data in a...
Definition: Array3D.h:127
+
vector< T > data_
Data in the array with size = xsize_ * ysize_ * zsize_.
Definition: Array3D.h:216
+
size_t ysize_
Number of elements in the y-dimension.
Definition: Array3D.h:207
+
Stores data of any type T in a 3D array.
Definition: Array3D.h:55
+
void Clear()
Function to clear the memory.
Definition: Array3D.h:76
+
void ReadText(FILE *f_in)
Read contents of the array from a file in binary format.
Definition: Array3D.h:181
+
Array3D()
Default constructor, which does not allocate any memory.
Definition: Array3D.h:58
+
+ + + + diff --git a/doc/doxygen/html/DoxyMain_8dox.html b/doc/doxygen/html/DoxyMain_8dox.html new file mode 100644 index 00000000..5c73e034 --- /dev/null +++ b/doc/doxygen/html/DoxyMain_8dox.html @@ -0,0 +1,53 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: DoxyMain.dox File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
DoxyMain.dox File Reference
+
+
+
+ + + + diff --git a/doc/doxygen/html/MyException_8h.html b/doc/doxygen/html/MyException_8h.html new file mode 100644 index 00000000..fd77d4a6 --- /dev/null +++ b/doc/doxygen/html/MyException_8h.html @@ -0,0 +1,70 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: MyException.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
MyException.h File Reference
+
+
+
#include <iostream>
+#include <exception>
+#include <string.h>
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  MyException
 
+
+ + + + diff --git a/doc/doxygen/html/MyException_8h_source.html b/doc/doxygen/html/MyException_8h_source.html new file mode 100644 index 00000000..fdfdaad2 --- /dev/null +++ b/doc/doxygen/html/MyException_8h_source.html @@ -0,0 +1,63 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: MyException.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
MyException.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _MyException_
30 #define _MyException_
31 
32 #include <iostream>
33 #include <exception>
34 #include <string.h>
35 
39 class MyException : public std::exception {
40 public:
42  MyException(const char* errormessage) {
43  std::cerr << "ERROR: " << errormessage << "\n";
44  error_ = std::string("MyException: ") + errormessage;
45  }
46 
48  MyException(const std::string& errormessage) {
49  std::cerr << "ERROR: " << errormessage << "\n";
50  error_ = std::string("MyException: ") + errormessage;
51  }
52 
54  virtual ~MyException() throw() {
55  }
56 
58  const char* what() const throw() {
59  try {
60  return error_.c_str();
61  } catch(...) {
62  ;
63  }
64  return error_.c_str();
65  }
66 
67 private:
68  std::string error_;
69 };
70 
71 #endif // _MyException_
std::string error_
Definition: MyException.h:68
+
const char * what() const
What&#39;s going on?
Definition: MyException.h:58
+
MyException(const std::string &errormessage)
Construct an exception using a C++-style string.
Definition: MyException.h:48
+
MyException(const char *errormessage)
Construct an exception using a C-style character string.
Definition: MyException.h:42
+
virtual ~MyException()
Destroy.
Definition: MyException.h:54
+
Definition: MyException.h:39
+
+ + + + diff --git a/doc/doxygen/html/Object_8h.html b/doc/doxygen/html/Object_8h.html new file mode 100644 index 00000000..e5eb8168 --- /dev/null +++ b/doc/doxygen/html/Object_8h.html @@ -0,0 +1,68 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Object.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
Object.h File Reference
+
+
+
#include "RefPtr.h"
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  Object
 
+
+ + + + diff --git a/doc/doxygen/html/Object_8h_source.html b/doc/doxygen/html/Object_8h_source.html new file mode 100644 index 00000000..37a8c991 --- /dev/null +++ b/doc/doxygen/html/Object_8h_source.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Object.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
Object.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _base_class_Object_
30 #define _base_class_Object_
31 
32 #include "RefPtr.h"
33 
46 class Object {
47  template <class T> friend class RefPtr;
48  template <class T> friend class ConstRefPtr;
49 public:
51  Object() : refs_(0) {
52  }
53 
55  virtual ~Object() {
56  }
57 
59  long int reference_count() const {
60  return refs_;
61  }
62 
63 protected:
66  long int reference_grab() const {
67  return ++refs_;
68  }
69 
70  long int reference_release() const {
71  return --refs_;
72  }
73 
74 private:
75  mutable long int refs_;
76 };
77 
78 #endif //_utility_ref_Object_
Definition: Object.h:46
+
long int refs_
Definition: Object.h:75
+ +
friend class ConstRefPtr
Definition: Object.h:48
+
long int reference_count() const
Returns the number of references that are held to this object.
Definition: Object.h:59
+
Object()
Construct a new reference counted object with a zero reference count.
Definition: Object.h:51
+
long int reference_grab() const
Definition: Object.h:66
+
virtual ~Object()
Destroy this object.
Definition: Object.h:55
+
long int reference_release() const
Definition: Object.h:70
+
Definition: RefPtr.h:45
+
+ + + + diff --git a/doc/doxygen/html/PCBasis_8cpp.html b/doc/doxygen/html/PCBasis_8cpp.html new file mode 100644 index 00000000..eb0991f5 --- /dev/null +++ b/doc/doxygen/html/PCBasis_8cpp.html @@ -0,0 +1,75 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCBasis.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
PCBasis.cpp File Reference
+
+
+ +

Univariate PC class. +More...

+
#include "PCBasis.h"
+#include "error_handlers.h"
+#include "uqtkconfig.h"
+#include <math.h>
+#include "quad.h"
+#include "arrayio.h"
+#include "pcmaps.h"
+#include "combin.h"
+#include <iostream>
+#include <string.h>
+#include <stdio.h>
+#include <sstream>
+

Detailed Description

+

Univariate PC class.

+
Author
B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 -
+
+ + + + diff --git a/doc/doxygen/html/PCBasis_8h.html b/doc/doxygen/html/PCBasis_8h.html new file mode 100644 index 00000000..be0b02a5 --- /dev/null +++ b/doc/doxygen/html/PCBasis_8h.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCBasis.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
PCBasis.h File Reference
+
+
+ +

Header file for the univariate PC class. +More...

+
#include <iostream>
+#include <string.h>
+#include "Array1D.h"
+#include "Array2D.h"
+#include "ftndefs.h"
+#include "dsfmt_add.h"
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  PCBasis
 Contains all basis type specific definitions and operations needed to generate a PCSet. More...
 
+

Detailed Description

+

Header file for the univariate PC class.

+
Author
B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 -
+
+ + + + diff --git a/doc/doxygen/html/PCBasis_8h_source.html b/doc/doxygen/html/PCBasis_8h_source.html new file mode 100644 index 00000000..49bdf275 --- /dev/null +++ b/doc/doxygen/html/PCBasis_8h_source.html @@ -0,0 +1,102 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCBasis.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
PCBasis.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
30 
31 #ifndef PCBASIS_H_SEEN
32 #define PCBASIS_H_SEEN
33 
34 #include <iostream>
35 #include <string.h>
36 #include "Array1D.h"
37 #include "Array2D.h"
38 // #include "Array3D.h"
39 #include "ftndefs.h"
40 #include "dsfmt_add.h"
41 
42 
46 class PCBasis {
47 public:
59  PCBasis(const string type="LU", const double alpha=0.0, const double betta=1.0, const int maxord=10);
60 
61 
63  ~PCBasis() {};
64 
73  void Init1dQuadPoints(int qdpts);
74 
78 
83  void Eval1dBasisAtCustPoints(Array2D<double>& psi,int kord, const Array1D<double>& custPoints);
84 
92  double EvalBasis(const double &xi, Array1D<double> &basisEvals) const;
97  double EvalBasis(const double &xi, const int kord, double *basisEvals) const;
98 
101  void Eval1dNormSq_Exact(int kord);
102 
103 
104  /***************************************************
105  New derivative functionality
106  ***************************************************/
108  void EvalDerivBasis(const double& xi, Array1D<double>& basisDEvals);
109  void Eval1dDerivBasisAtCustPoints(Array2D<double>& dpsi,int kord, const Array1D<double>& custPoints);
110 
111  void Eval2ndDerivBasis(const double& xi,Array1D<double>& ddP);
112  void Eval2ndDerivCustPoints(Array2D<double>& psi, int kord, Array1D<double>& custPoints);
113  /***************************************************
114  ***************************************************/
115 
118  void Get1dNormsSq(Array1D<double>& psi1dSq) const {psi1dSq=psi1dSq_; return;}
119 
122  void Get1dNormsSqExact(Array1D<double>& psi1dSqExact) const {psi1dSqExact=psi1dSqExact_; return;}
123 
128  void GetRandSample(Array1D<double>& randSamples);
129 
133  void GetRandSample(double* randSamples, const int& nSamp);
134 
136  int GetSeed() const {return rSeed_;}
137 
140  void SeedRandNumGen(const int& seed);
141 
143  void GetQuadRule(Array2D<double>& qPoints, Array1D<double>& qWeights, Array2D<int>& qIndices);
144 
147  void GetQuadPoints(Array2D<double>& quadPoints) const { quadPoints=quadPoints_; return;}
148 
150  void GetQuadWeights(Array1D<double>& quadWeights) const { quadWeights=quadWeights_; return;}
151 
153  void GetQuadIndices(Array2D<int>& quadIndices) const { quadIndices=quadIndices_; return;}
154 
156  void GetBasisAtQuadPoints(Array2D<double>& psi1d) const { psi1d=psi1d_; return;}
157 
159  string GetPCType() const {return type_;}
160 
162  double GetAlpha() const {return alpha_;}
163 
165  double GetBeta() const {return beta_;}
166 
167 private:
171  // PCBasis(): type_("NA") {};
172 
178  PCBasis(const PCBasis &obj):type_(obj.type_) {};
179 
180 
183  void Eval1dNormSq(int kord);
184 
185 
187  double NormSq_Exact(int kord);
188 
190  string type_;
191 
194 
197 
200 
201 
206 
209 
212 
214  int maxord_;
215 
217  int narg_;
218 
220  double alpha_;
221 
223  double beta_;
224 
227  dsfmt_t rnstate_ ;
228 
235  int rSeed_;
236 
237 };
238 
239 #endif /* PCBASIS_H_SEEN */
Array2D< double > quadPoints_
Array to store quadrature points.
Definition: PCBasis.h:193
+
double GetAlpha() const
Get the value of the parameter alpha.
Definition: PCBasis.h:162
+
double NormSq_Exact(int kord)
Evaluate 1d norm of order kord exactly.
Definition: PCBasis.cpp:509
+
double EvalBasis(const double &xi, Array1D< double > &basisEvals) const
Evaluate 1d basis functions for the given value of random variable xi. Return the value of the basis ...
Definition: PCBasis.cpp:146
+
Array2D< double > psi1d_
Array to store basis functions evaluated at quadrature points for each order: psi1d_(iqp,iord) contains the value of the polynomial chaos basis of order iord at the location of quadrature point iqp.
Definition: PCBasis.h:205
+
void EvalDerivBasis(const double &xi, Array1D< double > &basisDEvals)
Evaluate derivative of 1d non-normalized Legendre basis.
Definition: PCBasis.cpp:276
+
void Eval1dBasisAtQuadPoints()
Evaluate polynomial 1d basis functions at quadrature points and store in the private variable psi1d_...
Definition: PCBasis.cpp:108
+
void GetRandSample(Array1D< double > &randSamples)
Get samples of the random variables associated with the current PC basis functions and return them in...
Definition: PCBasis.cpp:397
+
~PCBasis()
Destructor.
Definition: PCBasis.h:63
+
PCBasis(const string type="LU", const double alpha=0.0, const double betta=1.0, const int maxord=10)
Constructor: initializes the univariate basis type and order.
Definition: PCBasis.cpp:47
+
void Eval2ndDerivBasis(const double &xi, Array1D< double > &ddP)
Definition: PCBasis.cpp:337
+
void GetQuadIndices(Array2D< int > &quadIndices) const
Get the quadrature points&#39; indices in the passed Array1D array.
Definition: PCBasis.h:153
+
Definition: Array1D.h:471
+
int GetSeed() const
Get the random number generator seed.
Definition: PCBasis.h:136
+
void Eval2ndDerivCustPoints(Array2D< double > &psi, int kord, Array1D< double > &custPoints)
Definition: PCBasis.cpp:373
+ +
int narg_
Number of parameters to specify the basis.
Definition: PCBasis.h:217
+
int rSeed_
The seed used for the random number generators that sample the xi&#39;s in the basis functions.
Definition: PCBasis.h:235
+
2D Array class for any type T
+
void GetQuadWeights(Array1D< double > &quadWeights) const
Get the quadrature weights in the passed Array1D array.
Definition: PCBasis.h:150
+
void GetQuadRule(Array2D< double > &qPoints, Array1D< double > &qWeights, Array2D< int > &qIndices)
Get the quadrature integration information.
Definition: PCBasis.cpp:457
+
double alpha_
Parameter alpha for PCs that require a parameter (GLG,SW,JB)
Definition: PCBasis.h:220
+
void GetQuadPoints(Array2D< double > &quadPoints) const
Get the quadrature points in the passed Array2D array.
Definition: PCBasis.h:147
+
double beta_
Parameter beta for PCs that require two parameters (SW,JB)
Definition: PCBasis.h:223
+
void Eval1dDerivBasisAtCustPoints(Array2D< double > &dpsi, int kord, const Array1D< double > &custPoints)
Definition: PCBasis.cpp:307
+
void Init1dQuadPoints(int qdpts)
Initialize the quadrature points and weights and store the information in arrays quadPoints_, quadWeights_,quadIndices_.
Definition: PCBasis.cpp:94
+
dsfmt_t rnstate_
Random sequence state for dsfmt.
Definition: PCBasis.h:227
+
Array1D< double > psi1dSqExact_
Array with the exact norms squared of the 1D basis functions for each order.
Definition: PCBasis.h:211
+
Array1D< double > psi1dSq_
Array with the norms squared of the 1D basis functions for each order.
Definition: PCBasis.h:208
+
void GetBasisAtQuadPoints(Array2D< double > &psi1d) const
Get the basis values at quadrature points in the passed Array2D array.
Definition: PCBasis.h:156
+
void Get1dNormsSqExact(Array1D< double > &psi1dSqExact) const
Get the analytic norms-squared of the basis functions. Returns the values for each basis function in ...
Definition: PCBasis.h:122
+
Contains all basis type specific definitions and operations needed to generate a PCSet.
Definition: PCBasis.h:46
+
void SeedRandNumGen(const int &seed)
Function to (re)seed the random number generator used to sample the Basis functions.
Definition: PCBasis.cpp:467
+
string GetPCType() const
Get the PC type.
Definition: PCBasis.h:159
+
void Eval1dBasisAtCustPoints(Array2D< double > &psi, int kord, const Array1D< double > &custPoints)
Evaluate polynomial 1d basis functions up to the order kord at custom points given by an array custPo...
Definition: PCBasis.cpp:120
+
void Eval1dNormSq_Exact(int kord)
Evaluate the norms (squared) of the basis functions exactly and stores in the private array psi1dSqEx...
Definition: PCBasis.cpp:496
+
string type_
String indicator of type of basis functions used.
Definition: PCBasis.h:190
+
void Get1dNormsSq(Array1D< double > &psi1dSq) const
Get the norms-squared of the basis functions. Returns the values for each basis function in the passe...
Definition: PCBasis.h:118
+
Array1D< double > quadWeights_
Array to store quadrature weights.
Definition: PCBasis.h:196
+
PCBasis(const PCBasis &obj)
Dummy default constructor, which should not be used as it is not well defined Therefore we make it pr...
Definition: PCBasis.h:178
+
void Eval1dNormSq(int kord)
Evaluate the norms (squared) of the basis functions and stores in the private array psi1dSq_...
Definition: PCBasis.cpp:479
+
1D Array class for any type T
+
Array2D< int > quadIndices_
Array to store quadrature point indexing; useful only for nested rules.
Definition: PCBasis.h:199
+
int maxord_
Maximal order of any dimension.
Definition: PCBasis.h:214
+
double GetBeta() const
Get the value of the parameter beta.
Definition: PCBasis.h:165
+
+ + + + diff --git a/doc/doxygen/html/PCSet_8cpp.html b/doc/doxygen/html/PCSet_8cpp.html new file mode 100644 index 00000000..2e0ddb67 --- /dev/null +++ b/doc/doxygen/html/PCSet_8cpp.html @@ -0,0 +1,95 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCSet.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
PCSet.cpp File Reference
+
+
+ +

Multivariate PC class. +More...

+
#include "PCSet.h"
+#include "PCBasis.h"
+#include <math.h>
+#include "uqtkconfig.h"
+#include "depslatec.h"
+#include "quad.h"
+#include "multiindex.h"
+#include "minmax.h"
+#include "arraytools.h"
+
+ + + +

+Macros

#define DIV_USE_GMRES
 
+

Detailed Description

+

Multivariate PC class.

+
Author
B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 -
+

Macro Definition Documentation

+ +

◆ DIV_USE_GMRES

+ +
+
+ + + + +
#define DIV_USE_GMRES
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/PCSet_8h.html b/doc/doxygen/html/PCSet_8h.html new file mode 100644 index 00000000..d3428a6f --- /dev/null +++ b/doc/doxygen/html/PCSet_8h.html @@ -0,0 +1,116 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCSet.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
PCSet.h File Reference
+
+
+ +

Header file for the Multivariate PC class. +More...

+
#include <iostream>
+#include <sstream>
+#include <string.h>
+#include <stdio.h>
+#include <map>
+#include "Array1D.h"
+#include "Array2D.h"
+#include "error_handlers.h"
+#include "ftndefs.h"
+#include "quad.h"
+#include <cvode/cvode.h>
+#include <nvector/nvector_serial.h>
+#include <cvode/cvode_dense.h>
+#include <sundials/sundials_dense.h>
+#include <sundials/sundials_types.h>
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  PCSet
 Defines and initializes PC basis function set and provides functions to manipulate PC expansions defined on this basis set. More...
 
+ + + +

+Enumerations

enum  LogCompMethod { TaylorSeries =0, +Integration + }
 
+

Detailed Description

+

Header file for the Multivariate PC class.

+
Author
B. Debusschere, C. Safta, K. Sargsyan, K. Chowdhary 2007 -
+

Enumeration Type Documentation

+ +

◆ LogCompMethod

+ +
+
+ + + + +
enum LogCompMethod
+
+ + + +
Enumerator
TaylorSeries 
Integration 
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/PCSet_8h_source.html b/doc/doxygen/html/PCSet_8h_source.html new file mode 100644 index 00000000..fa5d795d --- /dev/null +++ b/doc/doxygen/html/PCSet_8h_source.html @@ -0,0 +1,145 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCSet.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
PCSet.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
30 
31 #ifndef PCSET_H_SEEN
32 #define PCSET_H_SEEN
33 
34 #include <iostream>
35 #include <sstream>
36 #include <string.h>
37 #include <stdio.h>
38 #include <map>
39 #include "Array1D.h"
40 #include "Array2D.h"
41 #include "error_handlers.h"
42 #include "ftndefs.h"
43 #include "quad.h"
44 
45 /* CVODE headers */
46 #include <cvode/cvode.h> /* prototypes for CVODE fcts., consts. */
47 #include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., macros */
48 #include <cvode/cvode_dense.h> /* prototype for CVDense */
49 #include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
50 #include <sundials/sundials_types.h> /* definition of type realtype */
51 
52 #include <iostream>
53 #include <string.h>
54 #include <stdio.h>
55 #include <sstream>
56 using namespace std; // needed for python string conversion
57 
58 class PCBasis;
59 class Quad;
60 
62 
66 
67 class PCSet {
68 public:
69 
76  PCSet(const string sp_type, const int order, const int n_dim, const string pc_type,
77  const double alpha=0.0, const double betta=1.0);
78 
79 
89  PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, const string pc_seq,
90  const double alpha=0.0, const double betta=1.0);
91 
92 
99  PCSet(const string sp_type, const Array1D<int>& maxOrders, const int n_dim, const string pc_type,
100  const double alpha=0.0, const double betta=1.0);
101 
109  PCSet(const string sp_type, const Array2D<int>& customMultiIndex, const string pc_type,
110  const double alpha=0.0, const double betta=1.0);
111 
113  ~PCSet();
114 
118 
121  void dPhi_alpha(Array1D<double>& x, Array1D<int>& alpha, Array1D<double>& grad);
124  void dPhi(Array1D<double>& x, Array2D<int>& mindex, Array1D<double>& grad, Array1D<double>& ck);
127  void dPhi(Array2D<double>& x, Array2D<int>& mindex, Array2D<double>& grad, Array1D<double>& ck);
128 
131  void ddPhi_alpha(Array1D<double>& x, Array1D<int>& alpha, Array2D<double>& grad);
134  void ddPhi(Array1D<double>& x, Array2D<int>& mindex, Array2D<double>& grad, Array1D<double>& ck);
135 
139 
142  void SetQd1d(Array1D<double>& qdpts1d,Array1D<double>& wghts1d, int nqd);
143 
155  void SetQuadRule(const string grid_type,const string fs_type,int param);
156 
158  void SetQuadRule(Quad &quadRule);
159 
163 
165  void PrintMultiIndex() const;
166 
168  void PrintMultiIndexNormSquared() const;
169 
170 
174 
176  string GetPCType() const {return pcType_;}
177 
179  double GetAlpha() const {return alpha_;}
180 
182  double GetBeta() const {return beta_;}
183 
185  void GetMultiIndex(Array2D<int> &mindex) const {mindex=multiIndex_;}
186 
188  void GetMultiIndex(int *mindex) const;
189 
192  void GetNormSq(Array1D<double>& normsq) const {normsq=psiSq_;}
193 
195  int GetNumberPCTerms() const {return nPCTerms_;}
196 
198  int GetNDim() const {return nDim_;}
199 
201  int GetOrder() const {return order_;}
202 
204  int GetNQuadPoints() const {return nQuadPoints_;}
205 
207  void GetQuadPoints(Array2D<double>& quad) const {quad=quadPoints_;}
208 
210  void GetQuadPointsWeights(Array2D<double>& quad, Array1D<double>& wghts) const { quad=quadPoints_; wghts=quadWeights_;}
211 
213  void GetQuadPoints(double* quad) const {for(int i=0;i<nQuadPoints_;i++) for(int j=0;j<nDim_;j++) quad[i*nDim_+j]=quadPoints_(i,j);}
214 
216  void GetQuadWeights(Array1D<double>& wghts) const {wghts=quadWeights_;}
217 
219  void GetQuadWeights(double* wghts) const {for(int i=0;i<nQuadPoints_;i++) wghts[i]=quadWeights_(i);}
220 
223  void GetPsi(Array2D<double>& psi) const {psi=psi_;}
224 
227  void GetPsi(double* psi) const {for(int i=0;i<nQuadPoints_;i++) for(int j=0;j<nPCTerms_;j++) psi[i*nPCTerms_+j]=psi_(i,j);}
228 
230  void GetPsiSq(Array1D<double>& psisq) const {psisq=psiSq_;}
231 
233  void GetPsiSq(double* psisq) const {for(int i=0;i<nPCTerms_;i++) psisq[i]=psiSq_(i);}
234 
236  double GetTaylorTolerance() const {return rTolTaylor_;}
237 
239  void SetTaylorTolerance(const double& rTol) {rTolTaylor_ = rTol;}
240 
242  int GetTaylorTermsMax() const {return maxTermTaylor_;}
243 
245  void SetTaylorTermsMax(const int& maxTerm) {maxTermTaylor_ = maxTerm;}
246 
251  void SetLogCompMethod(const LogCompMethod& logMethod) {logMethod_ = logMethod;}
252 
254  double GetGMRESDivTolerance() const {return rTolGMRESDiv_;}
255 
257  void SetGMRESDivTolerance(const double& rTol) {rTolGMRESDiv_ = rTol;}
258 
259 
263 
270  void InitMeanStDv(const double& m, const double& s, double* p) const;
271 
278  void InitMeanStDv(const double& m, const double& s, Array1D<double>& p) const;
279 
283  void Copy(double* p1, const double* p2) const;
284 
289  void Copy(Array1D<double>& p1, const Array1D<double>& p2) const;
290 
293  void Add(const double* p1, const double* p2, double* p3) const;
294 
298  void Add(const Array1D<double>& p1, const Array1D<double>& p2, Array1D<double>& p3) const;
299 
302  void AddInPlace(double* p1, const double* p2) const;
303 
307  void AddInPlace(Array1D<double>& p1, const Array1D<double>& p2) const;
308 
311  void Multiply(const double* p1, const double& a, double* p2) const;
312 
316  void Multiply(const Array1D<double>& p1, const double& a, Array1D<double>& p2) const;
317 
320  void MultiplyInPlace(double* p1, const double& a) const;
321 
325  void MultiplyInPlace(Array1D<double>& p1, const double& a) const;
326 
329  void Subtract(const double* p1, const double* p2, double* p3) const;
330 
334  void Subtract(const Array1D<double>& p1, const Array1D<double>& p2, Array1D<double>& p3) const;
335 
338  void SubtractInPlace(double* p1, const double* p2) const;
339 
343  void SubtractInPlace(Array1D<double>& p1, const Array1D<double>& p2) const;
344 
347  void Prod(const double* p1, const double* p2, double* p3) const;
348 
352  void Prod(const Array1D<double>& p1, const Array1D<double>& p2, Array1D<double>& p3) const;
353 
356  void Prod3(const double* p1, const double* p2, const double* p3, double* p4) const;
357 
361  void Prod3(const Array1D<double>& p1, const Array1D<double>& p2, const Array1D<double>& p3,
362  Array1D<double>& p4) const;
363 
368  void Polyn(const double* polycf, int npoly, const double* p1, double* p2) const;
369 
374  void Polyn(const Array1D<double>& polycf, const Array1D<double>& p1, Array1D<double>& p2) const;
375 
386  void PolynMulti(const Array1D<double>& polycf, const Array2D<int>& mindex, const Array2D<double>& p1, Array1D<double>& p2) const;
387 
403  void Exp(const double* p1, double* p2) const;
404 
408  void Exp(const Array1D<double>& p1, Array1D<double>& p2) const;
409 
414  void Log(const double* p1, double* p2) const;
415 
419  void Log(const Array1D<double>& p1, Array1D<double>& p2) const;
420 
425  void Log10(const double* p1, double* p2) const;
426 
430  void Log10(const Array1D<double>& p1, Array1D<double>& p2) const;
431 
437  void RPow(const double* p1, double* p2, const double& a) const;
438 
442  void RPow(const Array1D<double>& p1, Array1D<double>& p2, const double& a) const;
443 
446  void IPow(const double* p1, double* p2, const int& ia) const;
447 
451  void IPow(const Array1D<double>& p1, Array1D<double>& p2, const int& ia) const;
452 
456  void Inv(const double* p1, double* p2) const;
457 
461  void Inv(const Array1D<double>& p1, Array1D<double>& p2) const;
462 
475  void Div(const double* p1, const double* p2, double* p3) const;
476 
480  void Div(const Array1D<double>& p1, const Array1D<double>& p2, Array1D<double>& p3) const;
481 
485  double StDv(const double* p) const;
486 
492  double StDv(const Array1D<double>& p) const;
493 
497  double GetModesRMS(const double* p) const;
498 
503  double GetModesRMS(const Array1D<double>& p) const;
504 
510  void Derivative(const double* p1, double* p2) const;
511 
517  void Derivative(const Array1D<double>& p1, Array1D<double>& p2) const;
518 
520  int GetNumTripleProd() const;
522  void GetTripleProd(int *nTriple, int *iProd, int *jProd, double *Cijk) const;
524  void GetTripleProd(Array1D<int>& nTriple, Array1D<int>& iProd, Array1D<int>& jProd, Array1D<double>& Cijk) const;
526  int GetNumQuadProd() const;
528  void GetQuadProd(int *nQuad, int *iProd, int *jProd, int *kProd, double *Cijkl) const;
530  void GetQuadProd(Array1D<int> &nQuad, Array1D<int> &iProd, Array1D<int> &jProd, Array1D<int> &kProd,
531  Array1D<double> &Cijkl) const;
532 
536 
539  void SeedBasisRandNumGen(const int& seed) const;
540 
546  void DrawSampleSet(const Array1D<double>& p, Array1D<double>& samples);
547 
551  void DrawSampleSet(const double* p, double* samples, const int& nSamples);
552 
555  void DrawSampleVar(Array2D<double>& samples) const;
556  void DrawSampleVar(double *samples, const int &nS, const int &nD) const;
557 
561 
569  double EvalPC(const Array1D<double>& p, Array1D<double>& randVarSamples);
570 
578  double EvalPC(const double* p, const double* randVarSamples);
579 
583  void EvalPCAtCustPoints(Array1D<double>& xch, Array2D<double>& custPoints,Array1D<double>& p);
584 
587  void EvalBasisAtCustPts(const Array2D<double>& custPoints,Array2D<double>& psi);
588 
589  void EvalBasisAtCustPts(const double* custPoints, const int npts, double* psi);
590  // void EvalBasisAtCustPts(const int npts, const int ndim, const int npc, const double *custPoints, double *psi);
591 
595 
602  void GalerkProjection(const Array1D<double>& fcn, Array1D<double>& ck);
603 
609  void GalerkProjectionMC(const Array2D<double>& x, const Array1D<double>& fcn, Array1D<double>& ck);
610 
614 
618  int ComputeOrders(Array1D<int>& orders);
619 
625  int ComputeEffDims(int *effdim);
626 
632  int ComputeEffDims(Array1D<int> &effdim);
633 
637  void EncodeMindex(Array1D< Array2D<int> >& sp_mindex);
638 
642 
645  double ComputeMean(const double *coef);
646 
648  double ComputeMean(Array1D<double>& coef);
649 
654  double ComputeVarFrac(const double *coef, double *varfrac);
655 
660  double ComputeVarFrac(Array1D<double>& coef, Array1D<double>& varfrac);
661 
664  void ComputeMainSens(Array1D<double>& coef, Array1D<double>& mainsens);
665 
668  void ComputeTotSens(Array1D<double>& coef, Array1D<double>& totsens);
669 
673  void ComputeJointSens(Array1D<double>& coef, Array2D<double>& jointsens);
674 
675 
679 
682  void SetVerbosity(int verbosity) { uqtkverbose_ = verbosity; }
683 
686  void EvalNormSq(Array1D<double>& normsq);
687  void EvalNormSq(double* normsq, const int npc);
688 
692  void EvalNormSqExact(Array1D<double>& normsq);
693 
695  bool IsInDomain(double x);
696 
697 
698 
699  private:
703  PCSet(): order_(0), nDim_(0) {};
704 
705 
711  PCSet(const PCSet &obj):order_(obj.order_), nDim_(obj.nDim_) {};
712 
714  void ComputeMaxOrdPerDim();
715 
719  void Initialize(const string ordertype);
720 
722  // void InitQuadrature();
723 
725  void InitISP();
727  void InitNISP();
728 
730  void EvalBasisProd3();
731 
733  void EvalBasisProd4();
734 
743  static void GMRESMatrixVectorProdWrapper(int* n, double* x, double* y, int* nelt,
744  int* ia, int* ja, double* a, int* obj) {
745  // Look up *obj in the map that relates integer indices to pointers to PCSet
746  OMap_t::iterator it = omap_->find(*obj);
747  if(it == omap_->end()) {
748  string err_message = (string) "GMRESMatrixVectorProdWrapper():"
749  + " the callback object is not a valid entry in the map";
750  throw Tantrum(err_message);
751  }
752  // Perform callback to the member function of the proper PCSet instance
753  it->second->GMRESMatrixVectorProd(x, a, y);
754 
755  return;
756  }
757 
766  static void GMRESPreCondWrapper(int* n, double* r, double* z, int* nelt,
767  int* ia, int* ja, double* a, int* obj,
768  double* rwork, int* iwork) { };
769 
775  void GMRESMatrixVectorProd(const double* x, const double*a, double* y) const;
776 
789  void LogTaylor(const double* p1, double* p2) const;
790 
793  void LogInt(const double* p1, double* p2) const;
794 
799  static int LogIntRhsWrapper(realtype t, N_Vector y, N_Vector ydot, void *f_data)
800  {
801  double indxobj = ((double*) f_data)[0] ;
802 
803  OMap_t::iterator it = omap_->find((int) indxobj);
804 
805  if (it == omap_->end())
806  {
807  string err_message = (string) "LogIntRhsWrapper():"
808  + " the callback object is not a valid entry in the map";
809  throw Tantrum(err_message);
810  }
811 
812  // Perform callback to the member function of the proper PCSet instance
813  it->second->LogIntRhs(t,y,ydot,f_data);
814 
815  return ( 0 ) ;
816 
817  }
818 
820  int LogIntRhs(realtype t, N_Vector y, N_Vector ydot, void *f_data) const;
821 
825 
827  string spType_;
828 
830  string pcType_;
831 
833  string pcSeq_;
834 
837 
839  int order_;
840 
843 
846 
849 
851  const int nDim_;
852 
855 
858 
860  double rTolTaylor_;
861 
864 
866  double SMALL_;
867 
870 
875 
879 
882 
885 
888 
893 
897 
901 
905 
909 
913 
917 
921 
924 
927 
930 
932  double CVinitstep_;
933 
935  double CVmaxstep_;
936 
938  double CVrelt_;
939 
941  double CVabst_ ;
942 
944  int Check_CVflag(void *flagvalue, const char *funcname, int opt) const;
945 
948 
950  int narg_;
951 
953  double alpha_;
955  double beta_;
956 
958  typedef std::map<int, PCSet*> OMap_t;
960  static int next_index_;
962  static OMap_t *omap_;
963 
964 };
965 
966 #endif /* !PCSET_H_SEEN */
Stores data of any type T in a 1D array.
Definition: Array1D.h:60
+
double rTolTaylor_
Relative tolerance for Taylor series approximations.
Definition: PCSet.h:860
+
string spType_
String indicator of ISP or NISP implementation type.
Definition: PCSet.h:827
+
Defines and initializes PC basis function set and provides functions to manipulate PC expansions defi...
Definition: PCSet.h:67
+
Array1D< double > psiSq_
Array with the norms squared of the basis functions, corresponding to each term in the PC expansion...
Definition: PCSet.h:878
+
int CVmaxord_
CVODE parameter: maximal order.
Definition: PCSet.h:926
+
int GetNDim() const
Get the PC dimensionality.
Definition: PCSet.h:198
+
std::map< int, PCSet * > OMap_t
Definition of a map to connect integer indexes with pointers to this class.
Definition: PCSet.h:958
+
Array2D< int > quadIndices_
Array to store quadrature point indexing; useful for nested rules.
Definition: PCSet.h:887
+
int GetNQuadPoints() const
Get the number of quadrature points.
Definition: PCSet.h:204
+
double GetBeta() const
Get the value of the parameter beta.
Definition: PCSet.h:182
+
int CVmaxnumsteps_
CVODE parameter: maximal number of steps.
Definition: PCSet.h:929
+
int order_
Order of the PC representation.
Definition: PCSet.h:839
+
double GetGMRESDivTolerance() const
Get relative tolerance for GMRES in Div routine.
Definition: PCSet.h:254
+ +
static OMap_t * omap_
Map to connect integer indexes with pointers to this class.
Definition: PCSet.h:962
+
double CVrelt_
CVODE parameter: relative tolerance.
Definition: PCSet.h:938
+
Array1D< Array1D< double > > psiIJKLProd3_
<\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l
Definition: PCSet.h:920
+
int maxorddim_
Maximal order within all dimensions.
Definition: PCSet.h:842
+
Array1D< Array1D< double > > psiIJKProd2_
<\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k
Definition: PCSet.h:904
+
void GetPsi(double *psi) const
Get the polynomials evaluated at the quadrature points folded into a one-dimensional array psi...
Definition: PCSet.h:227
+
Array1D< Array1D< int > > jProd2_
j-indices of <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k
Definition: PCSet.h:900
+
double alpha_
Parameter alpha for PCs that require a parameter (GLG,SW,JB)
Definition: PCSet.h:953
+
int uqtkverbose_
Verbosity level.
Definition: PCSet.h:824
+
int maxTermTaylor_
Max number of terms in Taylor series approximations.
Definition: PCSet.h:863
+
Array1D< int > maxOrders_
Array of maximum orders requested if custom(HDMR) ordering is requested.
Definition: PCSet.h:845
+
void SetGMRESDivTolerance(const double &rTol)
Set the relative tolerance for GMRES in Div routine.
Definition: PCSet.h:257
+
Definition: Array1D.h:471
+
void SetTaylorTolerance(const double &rTol)
Set relative tolerance for Taylor series approximations.
Definition: PCSet.h:239
+
static int next_index_
index of next object in map
Definition: PCSet.h:960
+
static void GMRESMatrixVectorProdWrapper(int *n, double *x, double *y, int *nelt, int *ia, int *ja, double *a, int *obj)
Wrapper for Matrix-vector multiplication routine to be called by GMRES.
Definition: PCSet.h:743
+
double GetAlpha() const
Get the value of the parameter alpha.
Definition: PCSet.h:179
+
double rTolGMRESDiv_
GMRES tolerance in Div()
Definition: PCSet.h:869
+
void GetMultiIndex(Array2D< int > &mindex) const
Get the multiindex (return Array2D)
Definition: PCSet.h:185
+
const int nDim_
Number of stochastic dimensions (degrees of freedom) in the PC representation.
Definition: PCSet.h:851
+
Array1D< double > quadWeights_
Array to store quadrature weights.
Definition: PCSet.h:884
+
void GetPsiSq(Array1D< double > &psisq) const
Get the basis polynomial norms-squared in an array class object psisq.
Definition: PCSet.h:230
+ +
void GetPsiSq(double *psisq) const
Get the basis polynomial norms-squared in a double* array psisq.
Definition: PCSet.h:233
+
void SetLogCompMethod(const LogCompMethod &logMethod)
Set method of computing the log function.
Definition: PCSet.h:251
+
2D Array class for any type T
+
void GetQuadPoints(double *quad) const
Get the quadrature points folded into a one-dimensional array quad.
Definition: PCSet.h:213
+
Generates quadrature rules.
Definition: quad.h:53
+
PCSet(const PCSet &obj)
Dummy copy constructor, which should not be used as it is currently not well defined. Therefore we make it private so it is not accessible.
Definition: PCSet.h:711
+
void GetQuadWeights(double *wghts) const
Get the quadrature weights folded into a one-dimensional array wghts.
Definition: PCSet.h:219
+
int my_index_
Index of this class.
Definition: PCSet.h:947
+
Array1D< int > maxOrdPerDim_
Array of maximum orders per dimension.
Definition: PCSet.h:848
+
PCBasis * p_basis_
Pointer to the class that defines the basis type and functions.
Definition: PCSet.h:836
+
LogCompMethod logMethod_
Flag for method to compute log: TaylorSeries or Integration.
Definition: PCSet.h:923
+
double CVabst_
CVODE parameter: absolute tolerance.
Definition: PCSet.h:941
+
static int LogIntRhsWrapper(realtype t, N_Vector y, N_Vector ydot, void *f_data)
Wrapper for LogIntRhs. The first component of f_data pointer carries an integer handle identifying th...
Definition: PCSet.h:799
+
Header file for the quadrature class.
+
Definition: Array1D.h:261
+
Array1D< Array1D< int > > iProd2_
i-indices of <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k
Definition: PCSet.h:896
+
void SetTaylorTermsMax(const int &maxTerm)
Set maximum number of terms in Taylor series approximations.
Definition: PCSet.h:245
+
double SMALL_
Tolerance to avoid floating-point errors.
Definition: PCSet.h:866
+
LogCompMethod
Definition: PCSet.h:61
+
static void GMRESPreCondWrapper(int *n, double *r, double *z, int *nelt, int *ia, int *ja, double *a, int *obj, double *rwork, int *iwork)
Wrapper for preconditioner routine to be called by GMRES.
Definition: PCSet.h:766
+
double CVinitstep_
CVODE parameter: initial step size.
Definition: PCSet.h:932
+
Contains all basis type specific definitions and operations needed to generate a PCSet.
Definition: PCBasis.h:46
+
int nQuadPoints_
Number of quadrature points used.
Definition: PCSet.h:854
+
void GetNormSq(Array1D< double > &normsq) const
Get the norm-squared.
Definition: PCSet.h:192
+
void SetVerbosity(int verbosity)
Other.
Definition: PCSet.h:682
+
Array2D< double > psi_
Array to store basis functions evaluated at quadrature points for each order: psi_(iqp,ipc) contains the value of the polynomial chaos ipc-th basis at the location of quadrature point iqp.
Definition: PCSet.h:874
+
Array1D< Array1D< int > > iProd3_
i-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l
Definition: PCSet.h:908
+
string GetPCType() const
Get and set variables/arrays inline.
Definition: PCSet.h:176
+
int nPCTerms_
Total number of terms in the PC expansions.
Definition: PCSet.h:857
+
double CVmaxstep_
CVODE parameter: maximal step size.
Definition: PCSet.h:935
+
Array1D< Array1D< int > > kProd3_
k-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l
Definition: PCSet.h:916
+
void GetQuadWeights(Array1D< double > &wghts) const
Get the quadrature weights.
Definition: PCSet.h:216
+
void GetQuadPointsWeights(Array2D< double > &quad, Array1D< double > &wghts) const
Get the quadrature points and weights.
Definition: PCSet.h:210
+
Definition: PCSet.h:61
+
PCSet()
Dummy default constructor, which should not be used as it is not well defined Therefore we make it pr...
Definition: PCSet.h:703
+
double GetTaylorTolerance() const
Get relative tolerance for Taylor series approximations.
Definition: PCSet.h:236
+
void GetPsi(Array2D< double > &psi) const
Get the values of the basis polynomials evaluated at the quadrature points.
Definition: PCSet.h:223
+
string pcSeq_
String indicator of multiindex ordering.
Definition: PCSet.h:833
+
Array2D< double > quadPoints_
Array to store quadrature points.
Definition: PCSet.h:881
+
Array2D< int > multiIndex_
Array to store multi-index: multiIndex_(ipc,idim) contains the order of the basis function associated...
Definition: PCSet.h:892
+
int GetNumberPCTerms() const
Get the number of terms in a PC expansion of this order and dimension.
Definition: PCSet.h:195
+
double beta_
Parameter beta for PCs that require two parameters (SW,JB)
Definition: PCSet.h:955
+
Array1D< Array1D< int > > jProd3_
j-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l
Definition: PCSet.h:912
+
void GetQuadPoints(Array2D< double > &quad) const
Get the quadrature points.
Definition: PCSet.h:207
+
int GetOrder() const
Get the PC order.
Definition: PCSet.h:201
+
1D Array class for any type T
+
Definition: PCSet.h:61
+
string pcType_
String indicator of PC type.
Definition: PCSet.h:830
+
int narg_
Number of free parameters to specify the basis.
Definition: PCSet.h:950
+
int GetTaylorTermsMax() const
Get maximum number of terms in Taylor series approximations.
Definition: PCSet.h:242
+
+ + + + diff --git a/doc/doxygen/html/RefPtr_8h.html b/doc/doxygen/html/RefPtr_8h.html new file mode 100644 index 00000000..c57d3373 --- /dev/null +++ b/doc/doxygen/html/RefPtr_8h.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: RefPtr.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
RefPtr.h File Reference
+
+
+
#include "MyException.h"
+#include <typeinfo>
+#include <unistd.h>
+#include <stddef.h>
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  RefPtr< T >
 
+
+ + + + diff --git a/doc/doxygen/html/RefPtr_8h_source.html b/doc/doxygen/html/RefPtr_8h_source.html new file mode 100644 index 00000000..626abfef --- /dev/null +++ b/doc/doxygen/html/RefPtr_8h_source.html @@ -0,0 +1,81 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: RefPtr.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
RefPtr.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _utility_ref_RefPtr_
30 #define _utility_ref_RefPtr_
31 
32 #include "MyException.h"
33 #include <typeinfo> // for dynamic_cast
34 #include <unistd.h>
35 #include <stddef.h>
36 
44 template <class T>
45 class RefPtr {
46 public:
48  typedef T Type;
49 
51  RefPtr() : ptr_(NULL) {}
52 
54  RefPtr(T* p) : ptr_(p) {
55  grab();
56  }
57 
59  RefPtr(const RefPtr<T>& p) : ptr_(p.ptr_) {
60  grab();
61  }
62 
65  template <class Other>
66  RefPtr(RefPtr<Other> p) : ptr_(static_cast<T*>(p.pointee())) {
67  grab();
68  }
69 
71  ~RefPtr() {
72  release();
73  }
74 
77  if(p != ptr_) {
78  release(); // release the old pointer
79  ptr_ = p; // assign our value to this one
80  grab(); // grab this pointer
81  }
82  return *this;
83  }
84 
87  if(p.ptr_ != ptr_) {
88  release();
89  ptr_ = p.ptr_;
90  grab();
91  }
92  return *this;
93  }
94 
98  template <class Other>
99  RefPtr<T>& cast(Other* p) {
100  if(p != ptr_) {
101  release();
102 
103  //std::cout << "DEBUG: Dynamic cast from type " << typeid(p).name()
104  // << " to " << typeid(T).name() << std::endl;
105 
106  ptr_ = dynamic_cast<T*>(p);
107  if(p != NULL && ptr_ == NULL) {
108  throw MyException
109  (std::string("RefPtr::cast(Other): Failed dynamic cast from ")
110  + std::string(typeid(Other).name()) + std::string(" to ") +
111  std::string(typeid(Type).name()));
112 
113  }
114  grab();
115  }
116  return *this;
117  }
118 
122  template <class Other>
124  if(p.ptr_ != ptr_) {
125  release();
126 
127  //std::cout << "DEBUG: Dynamic cast from type "
128  // << typeid(p.pointee()).name()
129  // << " to " << typeid(T).name() << std::endl;
130 
131  ptr_ = dynamic_cast<T*>(p.pointee());
132  if(p != NULL && ptr_ == NULL) {
133  throw MyException
134  (std::string("RefPtr::cast(Other): Failed dynamic cast from ")
135  + std::string(typeid(Other).name()) + std::string(" to ") +
136  std::string(typeid(Type).name()));
137  }
138  grab();
139  }
140  return *this;
141  }
142 
145  T* operator->() const {
146  if(ptr_ == NULL) {
147  std::cerr << "RefPtr<" << typeid(T).name()
148  << ">::operator->() const invoked on a null pointer\n";
149  throw MyException("RefPtr::operator->() const");
150  }
151  return ptr_;
152  }
153 
156  T& operator*() const {
157  if(ptr_ == NULL) {
158  std::cerr << "RefPtr<" << typeid(T).name()
159  << ">::operator*() const invoked on a null pointer\n";
160  throw MyException("RefPtr::operator*() const");
161  }
162  return *ptr_;
163  }
164 
166  T* pointee() {
167  return ptr_;
168  }
169 
171  const T* pointee() const {
172  return ptr_;
173  }
174 
176  bool operator==(const T* p) const {
177  return ptr_ == p;
178  }
179 
181  bool operator==(const RefPtr<T>& p) const {
182  return ptr_ == p.pointee();
183  }
184 
186  bool operator!=(const T* p) const {
187  return ptr_ != p;
188  }
189 
191  bool operator!=(const RefPtr<T>& p) const {
192  return ptr_ != p.ptr_;
193  }
194 
196  inline bool operator<(const RefPtr<T>& p) const {
197  return ptr_ < p.ptr_;
198  }
199 
201  template <class Other>
202  bool operator<(const RefPtr<Other>& p) const {
203  return ptr_ < p.pointee();
204  }
205 
206 private:
207  T* ptr_;
208 
210  inline void grab() {
211  if(ptr_ != NULL)
212  ptr_->reference_grab();
213  }
214 
218  inline void release() {
219  if(ptr_ != NULL) {
220  if(ptr_->reference_release() == 0)
221  delete ptr_;
222  }
223  }
224 };
225 
226 #endif //_utility_ref_RefPtr_
const T * pointee() const
Return the pointee of this RefPtr in a const context.
Definition: RefPtr.h:171
+
T Type
Make the typename that this pointer holds accessible to other objects.
Definition: RefPtr.h:48
+
RefPtr()
Construct a new RefPtr and initialize the pointee to NULL.
Definition: RefPtr.h:51
+
RefPtr(RefPtr< Other > p)
Definition: RefPtr.h:66
+
bool operator==(const RefPtr< T > &p) const
Compare the value of this pointee with the pointee of the given RefPtr.
Definition: RefPtr.h:181
+
T * ptr_
Definition: RefPtr.h:207
+
RefPtr< T > & operator=(T *p)
Assign the value of this RefPtr to the given pointee.
Definition: RefPtr.h:76
+
T & operator*() const
Definition: RefPtr.h:156
+
bool operator==(const T *p) const
Compare the pointee of this RefPtr with the given pointer.
Definition: RefPtr.h:176
+
RefPtr< T > & cast(RefPtr< Other > p)
Definition: RefPtr.h:123
+ +
void release()
Definition: RefPtr.h:218
+
void grab()
Grab a reference to the current pointee if it is not NULL.
Definition: RefPtr.h:210
+
RefPtr(const RefPtr< T > &p)
Construct a new RefPtr and initialize to the given RefPtr pointee.
Definition: RefPtr.h:59
+
RefPtr(T *p)
Construct a new RefPtr and initialize the pointee as given.
Definition: RefPtr.h:54
+
bool operator!=(const RefPtr< T > &p) const
Test inequality.
Definition: RefPtr.h:191
+
Definition: MyException.h:39
+
T * operator->() const
Definition: RefPtr.h:145
+
~RefPtr()
Destroy this RefPtr.
Definition: RefPtr.h:71
+
RefPtr< T > & cast(Other *p)
Definition: RefPtr.h:99
+
RefPtr< T > & operator=(const RefPtr< T > &p)
Assign the value of this RefPtr to the pointee of the given RefPtr.
Definition: RefPtr.h:86
+
bool operator!=(const T *p) const
Test inequality.
Definition: RefPtr.h:186
+
T * pointee()
Return the pointee of this RefPtr.
Definition: RefPtr.h:166
+
Definition: RefPtr.h:45
+
+ + + + diff --git a/doc/doxygen/html/XMLAttributeList_8cpp.html b/doc/doxygen/html/XMLAttributeList_8cpp.html new file mode 100644 index 00000000..93395127 --- /dev/null +++ b/doc/doxygen/html/XMLAttributeList_8cpp.html @@ -0,0 +1,181 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLAttributeList.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLAttributeList.cpp File Reference
+
+
+
#include "XMLAttributeList.h"
+#include "MyException.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+ + + + + + + + + +

+Functions

double to_double (const std::string &value)
 
int to_int (const std::string &value)
 
std::string to_string (int value)
 
std::string to_string (double value)
 
+

Function Documentation

+ +

◆ to_double()

+ +
+
+ + + + + +
+ + + + + + + + +
double to_double (const std::string & value)
+
+inline
+
+ +
+
+ +

◆ to_int()

+ +
+
+ + + + + +
+ + + + + + + + +
int to_int (const std::string & value)
+
+inline
+
+ +
+
+ +

◆ to_string() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
std::string to_string (int value)
+
+inline
+
+ +
+
+ +

◆ to_string() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
std::string to_string (double value)
+
+inline
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/XMLAttributeList_8h.html b/doc/doxygen/html/XMLAttributeList_8h.html new file mode 100644 index 00000000..96429f39 --- /dev/null +++ b/doc/doxygen/html/XMLAttributeList_8h.html @@ -0,0 +1,69 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLAttributeList.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLAttributeList.h File Reference
+
+
+
#include "Object.h"
+#include <map>
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  XMLAttributeList
 
+
+ + + + diff --git a/doc/doxygen/html/XMLAttributeList_8h_source.html b/doc/doxygen/html/XMLAttributeList_8h_source.html new file mode 100644 index 00000000..fe0bb96b --- /dev/null +++ b/doc/doxygen/html/XMLAttributeList_8h_source.html @@ -0,0 +1,82 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLAttributeList.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLAttributeList.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _util_xml_class_XMLAttributeList_
30 #define _util_xml_class_XMLAttributeList_
31 
32 #include "Object.h"
33 #include <map>
34 
56 class XMLAttributeList : public Object {
57  template <class T> friend class RefPtr;
58  template <class T> friend class ConstRefPtr;
59 public:
61  typedef std::map< std::string, std::string > Map_t;
62 
64  typedef Map_t::iterator iterator;
65  typedef Map_t::const_iterator const_iterator;
66 
69 
70 private:
73 
74 public:
76  virtual ~XMLAttributeList();
77 
78 private:
82 
83 public:
85  int size() const;
86 
88  bool has(const std::string&) const;
89 
92  const std::string& get(const std::string&) const;
93 
96  std::string get(const std::string&, const std::string&) const;
97 
101  int get_int(const std::string&) const;
102 
106  int get_int(const std::string&, int) const;
107 
111  double get_double(const std::string&) const;
112 
116  double get_double(const std::string&, double) const;
117 
123  bool get_bool(const std::string&) const;
124 
128  bool get_bool(const std::string&, bool) const;
129 
131  void set(const std::string&, const std::string&);
132 
134  void set_int(const std::string&, int);
135 
137  void set_double(const std::string&, double);
138 
141  void set_bool(const std::string&, bool);
142 
144  iterator begin();
145 
147  iterator end();
148 
150  const_iterator begin() const;
151 
153  const_iterator end() const;
154 
155 private:
157  Map_t attribute_;
158 
161  void make_lower_case(std::string&) const;
162 
164  iterator get_location(const std::string&);
165 
167  const_iterator get_location(const std::string&) const;
168 
171  bool boolean_value(const std::string&, const char* where) const;
172 };
173 
174 #endif // _util_xml_class_XMLAttributeList_
Definition: Object.h:46
+
Map_t::const_iterator const_iterator
Definition: XMLAttributeList.h:65
+
XMLAttributeList & operator=(const XMLAttributeList &)
Definition: XMLAttributeList.cpp:98
+
Map_t attribute_
The attributes.
Definition: XMLAttributeList.h:157
+
friend class ConstRefPtr
Definition: XMLAttributeList.h:58
+
iterator end()
Get an iterator past the last element.
Definition: XMLAttributeList.cpp:300
+
bool boolean_value(const std::string &, const char *where) const
Definition: XMLAttributeList.cpp:360
+
int get_int(const std::string &) const
Definition: XMLAttributeList.cpp:144
+
double get_double(const std::string &) const
Definition: XMLAttributeList.cpp:184
+
bool has(const std::string &) const
Return true if the given key is defined.
Definition: XMLAttributeList.cpp:112
+
iterator begin()
Get an iterator to the first element.
Definition: XMLAttributeList.cpp:293
+
virtual ~XMLAttributeList()
Destroy this list.
Definition: XMLAttributeList.cpp:91
+
void set_double(const std::string &, double)
Assign a numerical value to the given key.
Definition: XMLAttributeList.cpp:265
+
bool get_bool(const std::string &) const
Definition: XMLAttributeList.cpp:223
+
Map_t::iterator iterator
The iterator type returned by this implementation.
Definition: XMLAttributeList.h:64
+
XMLAttributeList()
Construct a blank attribute list.
Definition: XMLAttributeList.cpp:76
+
void set_bool(const std::string &, bool)
Definition: XMLAttributeList.cpp:281
+
void set_int(const std::string &, int)
Assign an integer value to the given key.
Definition: XMLAttributeList.cpp:256
+ +
Definition: XMLAttributeList.h:56
+
void make_lower_case(std::string &) const
Definition: XMLAttributeList.cpp:321
+
int size() const
Get the number of attributes in the list.
Definition: XMLAttributeList.cpp:105
+
std::map< std::string, std::string > Map_t
The container type used to hold the attributes.
Definition: XMLAttributeList.h:61
+
iterator get_location(const std::string &)
Get an iterator pointing to the location of the given string.
Definition: XMLAttributeList.cpp:332
+
Definition: RefPtr.h:45
+
+ + + + diff --git a/doc/doxygen/html/XMLElement_8cpp.html b/doc/doxygen/html/XMLElement_8cpp.html new file mode 100644 index 00000000..040b24ad --- /dev/null +++ b/doc/doxygen/html/XMLElement_8cpp.html @@ -0,0 +1,60 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLElement.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLElement.cpp File Reference
+
+
+
#include "XMLElement.h"
+#include "MyException.h"
+#include <algorithm>
+
+ + + + diff --git a/doc/doxygen/html/XMLElement_8h.html b/doc/doxygen/html/XMLElement_8h.html new file mode 100644 index 00000000..9d700d35 --- /dev/null +++ b/doc/doxygen/html/XMLElement_8h.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLElement.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLElement.h File Reference
+
+
+
#include "Object.h"
+#include "XMLAttributeList.h"
+#include <vector>
+#include <set>
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  XMLElement
 
+
+ + + + diff --git a/doc/doxygen/html/XMLElement_8h_source.html b/doc/doxygen/html/XMLElement_8h_source.html new file mode 100644 index 00000000..c8d20d39 --- /dev/null +++ b/doc/doxygen/html/XMLElement_8h_source.html @@ -0,0 +1,85 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLElement.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLElement.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _util_xml_class_XMLElement_
30 #define _util_xml_class_XMLElement_
31 
32 #include "Object.h"
33 #include "XMLAttributeList.h"
34 #include <vector>
35 #include <set>
36 
57 class XMLElement : public Object {
58  template <class T> friend class RefPtr;
59  template <class T> friend class ConstRefPtr;
60 public:
62  XMLElement(const std::string&);
63 
64 private:
67  XMLElement(const XMLElement&);
68 
69 public:
71  virtual ~XMLElement();
72 
73 private:
77 
78 public:
80  const std::string& label() const;
81 
83  void set_label(const std::string&);
84 
87  int count_attributes() const;
88 
91 
94 
96  int count_children() const;
97 
101 
108  RefPtr<XMLElement> get_child(const std::string&);
109 
116 
119 
121  void clear_children();
122 
125  int count_content() const;
126 
129  const std::string& get_content_line(int);
130 
132  void add_content_line(const std::string&);
133 
135  void clear_content();
136 
138  //typedef std::vector< RefPtr<XMLElement> >::iterator child_iterator;
139 
140 private:
142  std::string label_;
143 
146 
148  std::vector< RefPtr<XMLElement> > children_;
149 
151  std::vector<std::string> content_;
152 
155  void recurse(RefPtr<XMLElement>, std::set< RefPtr<XMLElement> >);
156 };
157 
158 #endif // _util_xml_class_XMLElement_
Definition: Object.h:46
+
XMLElement(const std::string &)
Construct a new xml element object and give it a label.
Definition: XMLElement.cpp:39
+
void add_content_line(const std::string &)
Add a line of content.
Definition: XMLElement.cpp:219
+
std::string label_
The iterator type returned for list of children.
Definition: XMLElement.h:142
+
int count_children() const
Utility function to check how many children this element has.
Definition: XMLElement.cpp:103
+
RefPtr< XMLElement > get_child(int)
Definition: XMLElement.cpp:110
+
void recurse(RefPtr< XMLElement >, std::set< RefPtr< XMLElement > >)
Definition: XMLElement.cpp:233
+
virtual ~XMLElement()
Destructor.
Definition: XMLElement.cpp:55
+
const std::string & get_content_line(int)
Definition: XMLElement.cpp:209
+
std::vector< std::string > content_
The list of content associated with this element.
Definition: XMLElement.h:151
+
std::vector< RefPtr< XMLElement > > children_
The list of children associated with this element.
Definition: XMLElement.h:148
+
int count_attributes() const
Definition: XMLElement.cpp:82
+ +
const std::string & label() const
Get the label of this node.
Definition: XMLElement.cpp:68
+
Definition: XMLElement.h:57
+
XMLElement & operator=(const XMLElement &)
Definition: XMLElement.cpp:61
+
void add_child_rpt(RefPtr< XMLElement >)
Same as add_child, but this allows for repeating children.
Definition: XMLElement.cpp:171
+
void clear_children()
Erase all child elements from this node.
Definition: XMLElement.cpp:195
+
void clear_content()
Clear all text content.
Definition: XMLElement.cpp:226
+
void set_attributes(RefPtr< XMLAttributeList >)
Assign an attribute list to this element.
Definition: XMLElement.cpp:96
+
void add_child(RefPtr< XMLElement >)
Definition: XMLElement.cpp:144
+ +
int count_content() const
Definition: XMLElement.cpp:202
+
RefPtr< XMLAttributeList > attributes()
Get access to the attribute list.
Definition: XMLElement.cpp:89
+
friend class ConstRefPtr
Definition: XMLElement.h:59
+
void set_label(const std::string &)
Assign a new label to this node.
Definition: XMLElement.cpp:75
+
Definition: RefPtr.h:45
+
RefPtr< XMLAttributeList > attributes_
The list of attributes associated with this element.
Definition: XMLElement.h:145
+
+ + + + diff --git a/doc/doxygen/html/XMLExpatParser_8cpp.html b/doc/doxygen/html/XMLExpatParser_8cpp.html new file mode 100644 index 00000000..56089310 --- /dev/null +++ b/doc/doxygen/html/XMLExpatParser_8cpp.html @@ -0,0 +1,96 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLExpatParser.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLExpatParser.cpp File Reference
+
+
+
#include "XMLExpatParser.h"
+#include "MyException.h"
+#include <cstdio>
+#include <iostream>
+
+ + + +

+Functions

std::string to_string (int value)
 
+

Function Documentation

+ +

◆ to_string()

+ +
+
+ + + + + +
+ + + + + + + + +
std::string to_string (int value)
+
+inline
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/XMLExpatParser_8h.html b/doc/doxygen/html/XMLExpatParser_8h.html new file mode 100644 index 00000000..92ad6ce2 --- /dev/null +++ b/doc/doxygen/html/XMLExpatParser_8h.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLExpatParser.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLExpatParser.h File Reference
+
+
+
#include "XMLParser.h"
+#include <iostream>
+#include <vector>
+#include <expat.h>
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  XMLExpatParser
 
+
+ + + + diff --git a/doc/doxygen/html/XMLExpatParser_8h_source.html b/doc/doxygen/html/XMLExpatParser_8h_source.html new file mode 100644 index 00000000..ae25d11d --- /dev/null +++ b/doc/doxygen/html/XMLExpatParser_8h_source.html @@ -0,0 +1,77 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLExpatParser.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLExpatParser.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _util_xml_class_XMLExpatParser_
30 #define _util_xml_class_XMLExpatParser_
31 
32 #include "XMLParser.h"
33 #include <iostream>
34 #include <vector>
35 #include <expat.h>
36 
47 class XMLExpatParser : public XMLParser {
48  template <class T> friend class RefPtr;
49  template <class T> friend class ConstRefPtr;
50 public:
53 
54 private:
58 
59 public:
61  virtual ~XMLExpatParser() throw();
62 
63 private:
65  XMLExpatParser& operator=(const XMLExpatParser&);
66 
67 public:
69  RefPtr<XMLElement> parse(std::istream&);
70 
71 private:
73  XML_Parser parser_;
74 
76  std::vector< RefPtr<XMLElement> > path_;
77 
80 
82  void do_start(const XML_Char*, const XML_Char**);
83 
85  void do_end(const XML_Char*);
86 
88  void do_character_data(const XML_Char*, int);
89 
91  void init();
92 
93 public:
97  static void start_(void*, const XML_Char*, const XML_Char**);
98 
102  static void end_(void*, const XML_Char*);
103 
107  static void character_data_(void*, const XML_Char*, int);
108 };
109 
110 #endif // _util_xml_class_XMLExpatParser_
RefPtr< XMLElement > leaf_
The current leaf of the parse tree.
Definition: XMLExpatParser.h:79
+
std::vector< RefPtr< XMLElement > > path_
The path that we have traversed so far in building the tree.
Definition: XMLExpatParser.h:76
+ +
void do_character_data(const XML_Char *, int)
The method used to parse character (content) data.
Definition: XMLExpatParser.cpp:165
+ +
XMLExpatParser()
Construct a new parser.
Definition: XMLExpatParser.cpp:50
+
static void end_(void *, const XML_Char *)
Definition: XMLExpatParser.cpp:220
+
static void start_(void *, const XML_Char *, const XML_Char **)
Definition: XMLExpatParser.cpp:210
+
void init()
Initialize the state of the parser.
Definition: XMLExpatParser.cpp:190
+
Definition: XMLExpatParser.h:47
+
void do_end(const XML_Char *)
The method used to parse the end tag.
Definition: XMLExpatParser.cpp:151
+
Definition: XMLElement.h:57
+
void do_start(const XML_Char *, const XML_Char **)
The method used to parse the start tag.
Definition: XMLExpatParser.cpp:128
+
Definition: XMLParser.h:41
+
virtual ~XMLExpatParser()
Destructor.
Definition: XMLExpatParser.cpp:68
+
XML_Parser parser_
The Expat parser.
Definition: XMLExpatParser.h:73
+
RefPtr< XMLElement > parse(std::istream &)
Parse the given input buffer and return a parse tree.
Definition: XMLExpatParser.cpp:85
+
friend class ConstRefPtr
Definition: XMLExpatParser.h:49
+
static void character_data_(void *, const XML_Char *, int)
Definition: XMLExpatParser.cpp:227
+
Definition: RefPtr.h:45
+
+ + + + diff --git a/doc/doxygen/html/XMLParser_8cpp.html b/doc/doxygen/html/XMLParser_8cpp.html new file mode 100644 index 00000000..0044c12d --- /dev/null +++ b/doc/doxygen/html/XMLParser_8cpp.html @@ -0,0 +1,58 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLParser.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLParser.cpp File Reference
+
+
+
#include "XMLParser.h"
+
+ + + + diff --git a/doc/doxygen/html/XMLParser_8h.html b/doc/doxygen/html/XMLParser_8h.html new file mode 100644 index 00000000..b2edae5d --- /dev/null +++ b/doc/doxygen/html/XMLParser_8h.html @@ -0,0 +1,69 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLParser.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLParser.h File Reference
+
+
+
#include "XMLElement.h"
+#include <iostream>
+
+

Go to the source code of this file.

+ + + + +

+Classes

class  XMLParser
 
+
+ + + + diff --git a/doc/doxygen/html/XMLParser_8h_source.html b/doc/doxygen/html/XMLParser_8h_source.html new file mode 100644 index 00000000..30d16912 --- /dev/null +++ b/doc/doxygen/html/XMLParser_8h_source.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLParser.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLParser.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 // -*- C++ -*-
28 
29 #ifndef _util_xml_class_XMLParser_
30 #define _util_xml_class_XMLParser_
31 
32 #include "XMLElement.h"
33 #include <iostream>
34 
41 class XMLParser : virtual public Object {
42  template <class T> friend class RefPtr;
43  template <class T> friend class ConstRefPtr;
44 public:
46  XMLParser();
47 
49  virtual ~XMLParser();
50 
52  virtual RefPtr<XMLElement> parse(std::istream&) = 0;
53 };
54 
55 #endif // _util_xml_class_XMLParser_
Definition: Object.h:46
+
XMLParser()
Default constructor. Intended for derived classes.
Definition: XMLParser.cpp:34
+ +
Definition: XMLParser.h:41
+
virtual ~XMLParser()
Destructor.
Definition: XMLParser.cpp:41
+
friend class ConstRefPtr
Definition: XMLParser.h:43
+
virtual RefPtr< XMLElement > parse(std::istream &)=0
Parse the given input buffer and return the parse tree.
+
Definition: RefPtr.h:45
+
+ + + + diff --git a/doc/doxygen/html/XMLUtils_8cpp.html b/doc/doxygen/html/XMLUtils_8cpp.html new file mode 100644 index 00000000..fcd5d9f0 --- /dev/null +++ b/doc/doxygen/html/XMLUtils_8cpp.html @@ -0,0 +1,104 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLUtils.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLUtils.cpp File Reference
+
+
+
#include "XMLUtils.h"
+
+ + + + +

+Functions

void dump_xml_tree (RefPtr< XMLElement > tree, const std::string &indentation, std::ostream &outfile)
 Recursively dump XML tree to an output file or stream. More...
 
+

Function Documentation

+ +

◆ dump_xml_tree()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void dump_xml_tree (RefPtr< XMLElementtree,
const std::string & indentation,
std::ostream & outfile 
)
+
+ +

Recursively dump XML tree to an output file or stream.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/XMLUtils_8h.html b/doc/doxygen/html/XMLUtils_8h.html new file mode 100644 index 00000000..41a433a9 --- /dev/null +++ b/doc/doxygen/html/XMLUtils_8h.html @@ -0,0 +1,107 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLUtils.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
XMLUtils.h File Reference
+
+
+
#include "XMLExpatParser.h"
+#include <iostream>
+
+

Go to the source code of this file.

+ + + + + +

+Functions

void dump_xml_tree (RefPtr< XMLElement >, const std::string &, std::ostream &)
 Recursively dump XML tree to an output file or stream. More...
 
+

Function Documentation

+ +

◆ dump_xml_tree()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void dump_xml_tree (RefPtr< XMLElement,
const std::string & ,
std::ostream &  
)
+
+ +

Recursively dump XML tree to an output file or stream.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/XMLUtils_8h_source.html b/doc/doxygen/html/XMLUtils_8h_source.html new file mode 100644 index 00000000..24d5129f --- /dev/null +++ b/doc/doxygen/html/XMLUtils_8h_source.html @@ -0,0 +1,60 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLUtils.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
XMLUtils.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 #include "XMLExpatParser.h"
28 #include <iostream>
29 
31 void dump_xml_tree(RefPtr<XMLElement> , const std::string& ,std::ostream& );
+
void dump_xml_tree(RefPtr< XMLElement >, const std::string &, std::ostream &)
Recursively dump XML tree to an output file or stream.
Definition: XMLUtils.cpp:32
+ +
+ + + + diff --git a/doc/doxygen/html/annotated.html b/doc/doxygen/html/annotated.html new file mode 100644 index 00000000..15ef333f --- /dev/null +++ b/doc/doxygen/html/annotated.html @@ -0,0 +1,99 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
[detail level 12]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 CArray1DStores data of any type T in a 1D array
 CArray1D< double >
 CArray1D< int >
 CArray2DStores data of any type T in a 2D array
 CArray3DStores data of any type T in a 3D array
 CDFI
 CDFIInner
 CDFISetup
 CDFISetupBase
 CGprocClass for Gaussian processes
 CKLDecompUniComputes the Karhunen-Loeve decomposition of a univariate stochastic process
 CLik_ABCDerived class for ABC likelihood
 CLik_ABCmDerived class for ABC-mean likelihood
 CLik_ClassicalDerived class for classical likelihood
 CLik_FullDerived class for full likelihood
 CLik_GausMargDerived class for gaussian-marginal likelihood
 CLik_GausMargDDerived class for gaussian-marginal likelihood with discrete parameter
 CLik_KohDerived class for Kennedy-O'Hagan likelihood
 CLik_MargDerived class for marginal likelihood
 CLik_MVNDerived class for mvn likelihood
 CLikelihoodBase
 CLregClass for linear parameteric regression
 CMCMCMarkov Chain Monte Carlo class. Implemented single-site and adaptive MCMC algorithms
 CchainstateStructure that holds the chain state information
 CmethodparA structure to hold method-specific parameters
 CoutputparA structure to hold parameters of output specification
 CMrvMultivariate RV parameterized by PC expansions
 CMyException
 CObject
 CPCBasisContains all basis type specific definitions and operations needed to generate a PCSet
 CPCregDerived class for PC regression
 CPCSetDefines and initializes PC basis function set and provides functions to manipulate PC expansions defined on this basis set
 CPLregDerived class for polynomial regression
 CPostPosterior evaluation with various likelihood and prior options
 CQuadGenerates quadrature rules
 CQuadRuleRule structure that stores quadrature points, weights and indices
 CRBFregDerived class for RBF regression
 CRefPtr
 CXMLAttributeList
 CXMLElement
 CXMLExpatParser
 CXMLParser
+
+
+ + + + diff --git a/doc/doxygen/html/arrayio_8cpp.html b/doc/doxygen/html/arrayio_8cpp.html new file mode 100644 index 00000000..1f340b03 --- /dev/null +++ b/doc/doxygen/html/arrayio_8cpp.html @@ -0,0 +1,1167 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: arrayio.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
arrayio.cpp File Reference
+
+
+ +

Read/write capabilities from/to matrix or vector form arrays/files. +More...

+
#include "arrayio.h"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

template<typename T >
void read_datafile (Array2D< T > &data, const char *filename)
 Read a datafile from filename in a matrix form and store it in the 2d array data of typename T. More...
 
template void read_datafile (Array2D< double > &data, const char *filename)
 
template void read_datafile (Array2D< int > &data, const char *filename)
 
template<typename T >
void read_datafileVS (Array2D< T > &data, const char *filename)
 Read a datafile from filename in a matrix form and store it in the 2d array data if typename T. More...
 
template void read_datafileVS (Array2D< double > &data, const char *filename)
 
template void read_datafileVS (Array2D< int > &data, const char *filename)
 
template<typename T >
void read_datafileVS (std::vector< T > &data, int &nrows, int &ncols, const char *filename)
 Read a datafile from filename in a matrix form and store it in a std::vector in column-major storage scheme. More...
 
template void read_datafileVS (std::vector< double > &data, int &nrows, int &ncols, const char *filename)
 
template void read_datafileVS (std::vector< int > &data, int &nrows, int &ncols, const char *filename)
 
template<typename T >
void read_datafile_1d (Array1D< T > &data, const char *filename)
 Read a data from filename in a vector form and store it in a 1d array data of typename T. More...
 
template void read_datafile_1d (Array1D< double > &data, const char *filename)
 
template void read_datafile_1d (Array1D< int > &data, const char *filename)
 
template<typename T >
void read_datafileVS (Array1D< T > &data, const char *filename)
 Read a datafile from filename in a vector form and store it in the 1d array data of typename T. More...
 
template void read_datafileVS (Array1D< double > &data, const char *filename)
 
template void read_datafileVS (Array1D< int > &data, const char *filename)
 
template<typename T >
void write_datafile_size (const Array2D< T > &data, const char *filename)
 Write to file filename the number of rows and number of columns on the first line, followed by the contents of a 2d array data of typename T in a matrix form. More...
 
template void write_datafile_size (const Array2D< double > &data, const char *filename)
 
template void write_datafile_size (const Array2D< int > &data, const char *filename)
 
template<typename T >
void write_datafile (const Array2D< T > &data, const char *filename)
 Write the contents of a 2d array data of typename T to file filename in a matrix form. More...
 
template void write_datafile (const Array2D< double > &data, const char *filename)
 
template void write_datafile (const Array2D< int > &data, const char *filename)
 
template<typename T >
void write_datafile (const Array2D< T > &data, const char *filename, const char *action)
 Write/append the contents of a 2d array data of typename T to file filename in a matrix form. More...
 
template void write_datafile (const Array2D< double > &data, const char *filename, const char *action)
 
template void write_datafile (const Array2D< int > &data, const char *filename, const char *action)
 
template<typename T >
void write_datafile (const std::vector< T > &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action)
 Write the contents of a vector of typename T to file filename in a matrix form. More...
 
template void write_datafile (const std::vector< double > &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action)
 
template void write_datafile (const std::vector< int > &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action)
 
template<typename T >
void write_datafile_1d (const Array1D< T > &data, const char *filename)
 Write the contents of a 1d array data of typename T to file filename in a vector form. More...
 
template void write_datafile_1d (const Array1D< double > &data, const char *filename)
 
template void write_datafile_1d (const Array1D< int > &data, const char *filename)
 
+

Detailed Description

+

Read/write capabilities from/to matrix or vector form arrays/files.

+

Function Documentation

+ +

◆ read_datafile() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafile (Array2D< T > & data,
const char * filename 
)
+
+ +

Read a datafile from filename in a matrix form and store it in the 2d array data of typename T.

+
Note
The array data needs to have the correct sizes
+ +
+
+ +

◆ read_datafile() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafile (Array2D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafile() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafile (Array2D< int > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafile_1d() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafile_1d (Array1D< T > & data,
const char * filename 
)
+
+ +

Read a data from filename in a vector form and store it in a 1d array data of typename T.

+
Note
The array data needs to have the correct size
+ +
+
+ +

◆ read_datafile_1d() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafile_1d (Array1D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafile_1d() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafile_1d (Array1D< int > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafileVS() [1/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafileVS (Array2D< T > & data,
const char * filename 
)
+
+ +

Read a datafile from filename in a matrix form and store it in the 2d array data if typename T.

+
Note
The array data is resized to match the file contents
+
+This function makes two passes: the first pass figures the no. or rows and columns, then the data array is appropriately resized, and the filename is read during second pass
+ +
+
+ +

◆ read_datafileVS() [2/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafileVS (Array2D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafileVS() [3/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafileVS (Array2D< int > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafileVS() [4/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void read_datafileVS (std::vector< T > & data,
int & nrows,
int & ncols,
const char * filename 
)
+
+ +

Read a datafile from filename in a matrix form and store it in a std::vector in column-major storage scheme.

+
Note
The vector is resized to match the file contents
+
+This function makes two passes: the first pass figures the no. or rows and columns, then the data vector is appropriately resized, and the filename is read during second pass
+ +
+
+ +

◆ read_datafileVS() [5/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void read_datafileVS (std::vector< double > & data,
int & nrows,
int & ncols,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafileVS() [6/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void read_datafileVS (std::vector< int > & data,
int & nrows,
int & ncols,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafileVS() [7/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafileVS (Array1D< T > & data,
const char * filename 
)
+
+ +

Read a datafile from filename in a vector form and store it in the 1d array data of typename T.

+
Note
The array data is resized to match the file contents
+
+This function makes two passes: the first pass figures the no. or rows and columns, then the data array is appropriately resized, and the filename is read during second pass
+ +
+
+ +

◆ read_datafileVS() [8/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafileVS (Array1D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ read_datafileVS() [9/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void read_datafileVS (Array1D< int > & data,
const char * filename 
)
+
+ +
+
+ +

◆ write_datafile() [1/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void write_datafile (const Array2D< T > & data,
const char * filename 
)
+
+ +

Write the contents of a 2d array data of typename T to file filename in a matrix form.

+ +
+
+ +

◆ write_datafile() [2/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void write_datafile (const Array2D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ write_datafile() [3/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void write_datafile (const Array2D< int > & data,
const char * filename 
)
+
+ +
+
+ +

◆ write_datafile() [4/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void write_datafile (const Array2D< T > & data,
const char * filename,
const char * action 
)
+
+ +

Write/append the contents of a 2d array data of typename T to file filename in a matrix form.

+ +
+
+ +

◆ write_datafile() [5/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void write_datafile (const Array2D< double > & data,
const char * filename,
const char * action 
)
+
+ +
+
+ +

◆ write_datafile() [6/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void write_datafile (const Array2D< int > & data,
const char * filename,
const char * action 
)
+
+ +
+
+ +

◆ write_datafile() [7/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void write_datafile (const std::vector< T > & data,
const int & nrows,
const int & ncols,
const char * storage,
const char * filename,
const char * action 
)
+
+ +

Write the contents of a vector of typename T to file filename in a matrix form.

+ +
+
+ +

◆ write_datafile() [8/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void write_datafile (const std::vector< double > & data,
const int & nrows,
const int & ncols,
const char * storage,
const char * filename,
const char * action 
)
+
+ +
+
+ +

◆ write_datafile() [9/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void write_datafile (const std::vector< int > & data,
const int & nrows,
const int & ncols,
const char * storage,
const char * filename,
const char * action 
)
+
+ +
+
+ +

◆ write_datafile_1d() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void write_datafile_1d (const Array1D< T > & data,
const char * filename 
)
+
+ +

Write the contents of a 1d array data of typename T to file filename in a vector form.

+ +
+
+ +

◆ write_datafile_1d() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void write_datafile_1d (const Array1D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ write_datafile_1d() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void write_datafile_1d (const Array1D< int > & data,
const char * filename 
)
+
+ +
+
+ +

◆ write_datafile_size() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void write_datafile_size (const Array2D< T > & data,
const char * filename 
)
+
+ +

Write to file filename the number of rows and number of columns on the first line, followed by the contents of a 2d array data of typename T in a matrix form.

+ +
+
+ +

◆ write_datafile_size() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void write_datafile_size (const Array2D< double > & data,
const char * filename 
)
+
+ +
+
+ +

◆ write_datafile_size() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void write_datafile_size (const Array2D< int > & data,
const char * filename 
)
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/arrayio_8h.html b/doc/doxygen/html/arrayio_8h.html new file mode 100644 index 00000000..eaab4a6b --- /dev/null +++ b/doc/doxygen/html/arrayio_8h.html @@ -0,0 +1,490 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: arrayio.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
arrayio.h File Reference
+
+
+ +

Header file for array read/write utilities. +More...

+
#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <stdlib.h>
+#include "Array1D.h"
+#include "Array2D.h"
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

template<typename T >
void read_datafile (Array2D< T > &data, const char *filename)
 Read a datafile from filename in a matrix form and store it in the 2d array data of typename T. More...
 
template<typename T >
void read_datafileVS (Array2D< T > &data, const char *filename)
 Read a datafile from filename in a matrix form and store it in the 2d array data if typename T. More...
 
template<typename T >
void read_datafileVS (std::vector< T > &data, int &nrows, int &ncols, const char *filename)
 Read a datafile from filename in a matrix form and store it in a std::vector in column-major storage scheme. More...
 
template<typename T >
void read_datafile_1d (Array1D< T > &data, const char *filename)
 Read a data from filename in a vector form and store it in a 1d array data of typename T. More...
 
template<typename T >
void read_datafileVS (Array1D< T > &data, const char *filename)
 Read a datafile from filename in a vector form and store it in the 1d array data of typename T. More...
 
template<typename T >
void write_datafile (const Array2D< T > &data, const char *filename, const char *action)
 Write/append the contents of a 2d array data of typename T to file filename in a matrix form. More...
 
template<typename T >
void write_datafile (const Array2D< T > &data, const char *filename)
 Write the contents of a 2d array data of typename T to file filename in a matrix form. More...
 
template<typename T >
void write_datafile (const std::vector< T > &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action)
 Write the contents of a vector of typename T to file filename in a matrix form. More...
 
template<typename T >
void write_datafile_size (const Array2D< T > &data, const char *filename)
 Write to file filename the number of rows and number of columns on the first line, followed by the contents of a 2d array data of typename T in a matrix form. More...
 
template<typename T >
void write_datafile_1d (const Array1D< T > &data, const char *filename)
 Write the contents of a 1d array data of typename T to file filename in a vector form. More...
 
+

Detailed Description

+

Header file for array read/write utilities.

+

Function Documentation

+ +

◆ read_datafile()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafile (Array2D< T > & data,
const char * filename 
)
+
+ +

Read a datafile from filename in a matrix form and store it in the 2d array data of typename T.

+
Note
The array data needs to have the correct sizes
+ +
+
+ +

◆ read_datafile_1d()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafile_1d (Array1D< T > & data,
const char * filename 
)
+
+ +

Read a data from filename in a vector form and store it in a 1d array data of typename T.

+
Note
The array data needs to have the correct size
+ +
+
+ +

◆ read_datafileVS() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafileVS (Array2D< T > & data,
const char * filename 
)
+
+ +

Read a datafile from filename in a matrix form and store it in the 2d array data if typename T.

+
Note
The array data is resized to match the file contents
+
+This function makes two passes: the first pass figures the no. or rows and columns, then the data array is appropriately resized, and the filename is read during second pass
+ +
+
+ +

◆ read_datafileVS() [2/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void read_datafileVS (std::vector< T > & data,
int & nrows,
int & ncols,
const char * filename 
)
+
+ +

Read a datafile from filename in a matrix form and store it in a std::vector in column-major storage scheme.

+
Note
The vector is resized to match the file contents
+
+This function makes two passes: the first pass figures the no. or rows and columns, then the data vector is appropriately resized, and the filename is read during second pass
+ +
+
+ +

◆ read_datafileVS() [3/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void read_datafileVS (Array1D< T > & data,
const char * filename 
)
+
+ +

Read a datafile from filename in a vector form and store it in the 1d array data of typename T.

+
Note
The array data is resized to match the file contents
+
+This function makes two passes: the first pass figures the no. or rows and columns, then the data array is appropriately resized, and the filename is read during second pass
+ +
+
+ +

◆ write_datafile() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void write_datafile (const Array2D< T > & data,
const char * filename,
const char * action 
)
+
+ +

Write/append the contents of a 2d array data of typename T to file filename in a matrix form.

+ +
+
+ +

◆ write_datafile() [2/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void write_datafile (const Array2D< T > & data,
const char * filename 
)
+
+ +

Write the contents of a 2d array data of typename T to file filename in a matrix form.

+ +
+
+ +

◆ write_datafile() [3/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void write_datafile (const std::vector< T > & data,
const int & nrows,
const int & ncols,
const char * storage,
const char * filename,
const char * action 
)
+
+ +

Write the contents of a vector of typename T to file filename in a matrix form.

+ +
+
+ +

◆ write_datafile_1d()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void write_datafile_1d (const Array1D< T > & data,
const char * filename 
)
+
+ +

Write the contents of a 1d array data of typename T to file filename in a vector form.

+ +
+
+ +

◆ write_datafile_size()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void write_datafile_size (const Array2D< T > & data,
const char * filename 
)
+
+ +

Write to file filename the number of rows and number of columns on the first line, followed by the contents of a 2d array data of typename T in a matrix form.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/arrayio_8h_source.html b/doc/doxygen/html/arrayio_8h_source.html new file mode 100644 index 00000000..c35a194b --- /dev/null +++ b/doc/doxygen/html/arrayio_8h_source.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: arrayio.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
arrayio.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
29 
30 #ifndef ARRAYIO_H
31 #define ARRAYIO_H
32 
33 #include <iostream>
34 #include <fstream>
35 #include <sstream>
36 #include <stdlib.h>
37 
38 #include "Array1D.h"
39 #include "Array2D.h"
40 
41 
45 template <typename T> void read_datafile(Array2D<T> &data, const char *filename);
46 
52 template <typename T> void read_datafileVS(Array2D<T> &data, const char *filename);
53 
59 template <typename T> void read_datafileVS(std::vector<T> &data, int &nrows, int &ncols, const char *filename);
60 
64 template <typename T> void read_datafile_1d(Array1D<T>& data, const char* filename);
65 
71 template <typename T> void read_datafileVS(Array1D<T> &data, const char *filename);
72 
75 template <typename T>
76 void write_datafile(const Array2D<T> &data, const char *filename, const char *action);
77 
80 template <typename T>
81 void write_datafile(const Array2D<T> &data, const char *filename);
82 
85 template <typename T>
86 void write_datafile(const std::vector<T> &data, const int &nrows, const int &ncols, const char *storage, const char *filename, const char *action);
87 
91 template <typename T>
92 void write_datafile_size(const Array2D<T> &data, const char *filename);
93 
96 template <typename T> void write_datafile_1d(const Array1D<T>& data, const char* filename);
97 
98 #endif // ARRAYIO_H
Stores data of any type T in a 1D array.
Definition: Array1D.h:60
+
void read_datafile_1d(Array1D< T > &data, const char *filename)
Read a data from filename in a vector form and store it in a 1d array data of typename T...
Definition: arrayio.cpp:270
+
Stores data of any type T in a 2D array.
Definition: Array2D.h:59
+
void write_datafile_size(const Array2D< T > &data, const char *filename)
Write to file filename the number of rows and number of columns on the first line, followed by the contents of a 2d array data of typename T in a matrix form.
Definition: arrayio.cpp:363
+
2D Array class for any type T
+
void read_datafileVS(Array2D< T > &data, const char *filename)
Read a datafile from filename in a matrix form and store it in the 2d array data if typename T...
Definition: arrayio.cpp:93
+
void write_datafile(const Array2D< T > &data, const char *filename, const char *action)
Write/append the contents of a 2d array data of typename T to file filename in a matrix form...
Definition: arrayio.cpp:440
+
void read_datafile(Array2D< T > &data, const char *filename)
Read a datafile from filename in a matrix form and store it in the 2d array data of typename T...
Definition: arrayio.cpp:37
+
1D Array class for any type T
+
void write_datafile_1d(const Array1D< T > &data, const char *filename)
Write the contents of a 1d array data of typename T to file filename in a vector form.
Definition: arrayio.cpp:568
+
+ + + + diff --git a/doc/doxygen/html/arraytools_8cpp.html b/doc/doxygen/html/arraytools_8cpp.html new file mode 100644 index 00000000..66ffed45 --- /dev/null +++ b/doc/doxygen/html/arraytools_8cpp.html @@ -0,0 +1,4984 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: arraytools.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
arraytools.cpp File Reference
+
+
+ +

Tools to manipulate Array 1D and 2D objects. Some tools mimick MATLAB functionalities. +More...

+
#include "stdlib.h"
+#include "stdio.h"
+#include "math.h"
+#include "assert.h"
+#include <sstream>
+#include <fstream>
+#include <iomanip>
+#include "arraytools.h"
+#include "ftndefs.h"
+#include "gen_defs.h"
+#include "depblas.h"
+#include "deplapack.h"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

template<typename T >
void array1Dto2D (Array1D< T > &arr_1d, Array2D< T > &arr)
 Store a given 1d array in a 2d array with a single second dimension. More...
 
template void array1Dto2D (Array1D< double > &arr_1d, Array2D< double > &arr)
 
template void array1Dto2D (Array1D< int > &arr_1d, Array2D< int > &arr)
 
template<typename T >
void array2Dto1D (Array2D< T > &arr_2d, Array1D< T > &arr)
 Store a given 2d array with a single second dimension in a 1d array. More...
 
template void array2Dto1D (Array2D< double > &arr_2d, Array1D< double > &arr)
 
template void array2Dto1D (Array2D< int > &arr_2d, Array1D< int > &arr)
 
template<typename T >
void paste (Array1D< T > &arr1, Array1D< T > &arr2, Array2D< T > &arr)
 Paste two 1d arrays of same size into a single 2d array with second dimension equal to two. More...
 
template void paste (Array1D< double > &arr1, Array1D< double > &arr2, Array2D< double > &arr)
 
template void paste (Array1D< int > &arr1, Array1D< int > &arr2, Array2D< int > &arr)
 
template<typename T >
void generate_multigrid (Array2D< T > &multigrid, Array2D< T > &grid)
 Generates multigrid as a cartesian product of each column of grid. More...
 
template void generate_multigrid (Array2D< double > &multigrid, Array2D< double > &grid)
 
template void generate_multigrid (Array2D< int > &multigrid, Array2D< int > &grid)
 
void paste (Array2D< double > &x, Array2D< double > &y, Array2D< double > &xy)
 Paste two 2D arrays next to each other (horizontal stack) More...
 
void merge (Array2D< double > &x, Array2D< double > &y, Array2D< double > &xy)
 Merge 2d double arrays (vertical stack) More...
 
void merge (Array1D< double > &x, Array1D< double > &y, Array1D< double > &xy)
 Merge 1d double arrays. More...
 
void merge (Array1D< int > &x, Array1D< int > &y, Array1D< int > &xy)
 Merge 1d int arrays. More...
 
void append (Array1D< double > &x, Array1D< double > &y)
 Append array y to array x in place (double format) More...
 
void append (Array1D< int > &x, Array1D< int > &y)
 Append array y to array x in place (int format) More...
 
template<typename T >
void transpose (Array2D< T > &x, Array2D< T > &xt)
 Transpose a 2d double or int array x and return the result in xt. More...
 
template void transpose (Array2D< double > &x, Array2D< double > &xt)
 
template void transpose (Array2D< int > &x, Array2D< int > &xt)
 
void flatten (Array2D< double > &arr_2, Array1D< double > &arr_1)
 Unfold/flatten a 2d array into a 1d array (double format) More...
 
void fold_1dto2d (Array1D< double > &x1, Array2D< double > &x2)
 Fold a 1d array into a 2d array (double format) More...
 
void swap (Array1D< double > &arr, int i, int j)
 Swap i-th and j-th elements of the array arr. More...
 
void swap (Array2D< double > &arr, int i, int j)
 Swap i-th and j-th rows of the 2d array arr. More...
 
double access (int nx, int ny, Array1D< double > &arr_1, int i, int j)
 Access element $j+i\times ny$ from 1D array 'arr_1'. More...
 
template<typename T >
void getRow (Array2D< T > &arr2d, int k, Array1D< T > &arr1d)
 Retrieves row 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'. More...
 
template void getRow (Array2D< double > &arr2d, int k, Array1D< double > &arr1d)
 
template void getRow (Array2D< int > &arr2d, int k, Array1D< int > &arr1d)
 
template<typename T >
void getCol (Array2D< T > &arr2d, int k, Array1D< T > &arr1d)
 Retrieves column 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'. More...
 
template void getCol (Array2D< double > &arr2d, int k, Array1D< double > &arr1d)
 
template void getCol (Array2D< int > &arr2d, int k, Array1D< int > &arr1d)
 
template<typename T >
void addVal (int n, T *arr1d, T val)
 Adds 'val' to the first n elements of an array pointer (double or int) More...
 
template void addVal (int n, double *arr1d, double val)
 
template void addVal (int n, int *arr1d, int val)
 
template<typename T >
void addVal (Array1D< T > &arr1d, T val)
 Adds 'val' to all elements of 1D array arr1d (double or int) More...
 
template void addVal (Array1D< double > &arr1d, double val)
 
template void addVal (Array1D< int > &arr1d, int val)
 
template<typename T >
void addVal (Array2D< T > &arr2d, T val)
 Adds 'val' to all elements of 2D array arr2d (double or int) More...
 
template void addVal (Array2D< double > &arr2d, double val)
 
template void addVal (Array2D< int > &arr2d, int val)
 
template<typename T >
void subVector (Array1D< T > &vector, Array1D< int > &ind, Array1D< T > &subvector)
 Extracts from 'vector', elements corresponding to indices 'ind' and returns them in 'subvector' (double or int) More...
 
template void subVector (Array1D< double > &vector, Array1D< int > &ind, Array1D< double > &subvector)
 
template void subVector (Array1D< int > &vector, Array1D< int > &ind, Array1D< int > &subvector)
 
template<typename T >
void subMatrix_row (Array2D< T > &matrix, Array1D< int > &ind, Array2D< T > &submatrix)
 Extracts from 'matrix' rows corresponding to indices 'ind' and returns them in 'submatrix' (double or int) More...
 
template void subMatrix_row (Array2D< double > &matrix, Array1D< int > &ind, Array2D< double > &submatrix)
 
template void subMatrix_row (Array2D< int > &matrix, Array1D< int > &ind, Array2D< int > &submatrix)
 
template<typename T >
void subMatrix_col (Array2D< T > &matrix, Array1D< int > &ind, Array2D< T > &submatrix)
 Extracts from 'matrix' columns corresponding to indices 'ind' and returns them in 'submatrix' (double or int) More...
 
template void subMatrix_col (Array2D< double > &matrix, Array1D< int > &ind, Array2D< double > &submatrix)
 
template void subMatrix_col (Array2D< int > &matrix, Array1D< int > &ind, Array2D< int > &submatrix)
 
template<typename T >
void matPvec (Array2D< T > &matrix, const Array1D< T > &rc, T alpha, char *RC)
 Adds scaled row or column to all rows / columns of a matrix (double or int) More...
 
template void matPvec (Array2D< double > &matrix, const Array1D< double > &rc, double alpha, char *RC)
 
template void matPvec (Array2D< int > &matrix, const Array1D< int > &rc, int alpha, char *RC)
 
template<typename T >
maxVal (const Array1D< T > &vector, int *indx)
 Returns maximum value in 'vector' and its location in *indx (double or int) More...
 
template double maxVal (const Array1D< double > &vector, int *indx)
 
template int maxVal (const Array1D< int > &vector, int *indx)
 
void setdiff (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
 Returns $ C=A\backslash B$ (C=Elements of A that are not in B); C is sorted in ascending order. More...
 
void setdiff_s (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
 Returns $ C=A\backslash B$ ( C=Elements of A that are not in B); C is sorted in ascending order. More...
 
void shell_sort (int *a, int n)
 Sorts integer array. More...
 
void shell_sort (Array1D< int > &array)
 Sorts integer array in ascending order. More...
 
void shell_sort (Array1D< double > &array)
 Sorts double array in ascending order. More...
 
void shell_sort_col (Array2D< double > &array, int col, Array1D< int > &newInd, Array1D< int > &oldInd)
 Sorts double array in ascending order according to a given column. More...
 
void shell_sort_all (Array2D< double > &array, Array1D< int > &newInd, Array1D< int > &oldInd)
 Sorts double array in ascending order according to first column, then second column breaks the tie, and so on. More...
 
void quicksort3 (Array1D< double > &arr, int l, int r)
 Quick-sort with 3-way partitioning of array between indices l and r. More...
 
void quicksort3 (Array2D< double > &arr, int l, int r, int col)
 Quick-sort with 3-way partitioning of 2d array between indices l and r, according to column col. More...
 
void quicksort3 (Array2D< double > &arr, int l, int r)
 Quick-sort with 3-way partitioning of 2d array between indices l and r, and sorting is done comparing rows (by first element, then by second, etc...) More...
 
void intersect (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C, Array1D< int > &iA, Array1D< int > &iB)
 Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order. It also returns the original locations of these entries in 1D arrays 'iA' and 'iB', respectively. More...
 
void intersect (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
 Find common entries in 1D arrays 'A' and 'B' and return them in 'C', sorted in ascending order. More...
 
template<typename T >
void find (Array1D< T > &theta, T lmbda, string type, Array1D< int > &indx)
 Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" ), larger or equal ( type="ge" ), smaller ( type="lt" ), smaller or equal ( type="le" ) than lmbda. More...
 
template void find (Array1D< double > &theta, double lmbda, string type, Array1D< int > &indx)
 
template void find (Array1D< int > &theta, int lmbda, string type, Array1D< int > &indx)
 
void prodAlphaMatVec (Array2D< double > &A, Array1D< double > &x, double alpha, Array1D< double > &y)
 Returns $y=\alpha Ax$, where 'A' is a $\left[n\times m\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements. More...
 
void prodAlphaMatTVec (Array2D< double > &A, Array1D< double > &x, double alpha, Array1D< double > &y)
 Returns $y=\alpha A^Tx$, where 'A' is a $\left[m\times n\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements. More...
 
void prodAlphaMatMat (Array2D< double > &A, Array2D< double > &B, double alpha, Array2D< double > &C)
 Returns $C=\alpha AB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements. More...
 
void prodAlphaMatTMat (Array2D< double > &A, Array2D< double > &B, double alpha, Array2D< double > &C)
 Returns $C=\alpha A^TB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements. More...
 
void addVecAlphaVecPow (Array1D< double > &x, double alpha, Array1D< double > &y, int ip)
 Implements $x_i=x_i+\alpha y_i^ip$, where 'x' and 'y' are 1D arrays with $n$ elements. More...
 
double prod_vecTmatvec (Array1D< double > &a, Array2D< double > &B, Array1D< double > &c)
 Returns $a^T B c$. More...
 
Array2D< double > MatTMat (Array2D< double > &A)
 Returns $A^T A$, where 'A' is a $\left[n\times k\right]$ 2D array. More...
 
template<typename T >
void delRow (Array2D< T > &A, int irow)
 Deletes row 'irow' from 2D array 'A'. More...
 
template void delRow (Array2D< double > &A, int irow)
 
template void delRow (Array2D< int > &A, int irow)
 
template<typename T >
void delCol (Array2D< T > &A, int icol)
 Deletes column 'icol' from 2D array 'A'. More...
 
template void delCol (Array2D< double > &A, int icol)
 
template void delCol (Array2D< int > &A, int icol)
 
template<typename T >
void delCol (Array1D< T > &x, int icol)
 Deletes element 'icol' from 1D array 'A'. More...
 
template void delCol (Array1D< double > &x, int icol)
 
template void delCol (Array1D< int > &x, int icol)
 
void paddMatRow (Array2D< double > &A, Array1D< double > &x)
 Padds 2D array 'A' with the row 'x'. More...
 
void paddMatCol (Array2D< double > &A, Array1D< double > &x)
 Padds 2D array 'A' with the column 'x'. More...
 
void paddMatRow (Array2D< int > &A, Array1D< int > &x)
 Padds 2D array 'A' with the row 'x'. More...
 
void paddMatCol (Array2D< int > &A, Array1D< int > &x)
 Padds 2D array 'A' with the column 'x'. More...
 
void paddMatColScal (Array2D< double > &A, Array1D< double > &x, double scal)
 Padds square 2D array 'A' $\left[n\times n\right]$ with the elements of 'x' and 'scal' as follows: $A_{n+1,i}=A_{i,n+1}=x_i$ and $A_{n+1,n+1}=scal$. More...
 
bool is_equal (Array1D< int > &a, Array1D< int > &b)
 Checks if two 1d int arrays are equal. More...
 
bool is_equal (Array1D< double > &a, Array1D< double > &b)
 Checks if two 1d double arrays are equal. More...
 
bool is_less (Array1D< int > &a, Array1D< int > &b)
 Checks if one 1d int array is less than another (by first element, then by second, etc...) More...
 
bool is_less (Array1D< double > &a, Array1D< double > &b)
 Checks if one 1d double array is less than another (by first element, then by second, etc...) More...
 
int vecIsInArray (Array1D< int > &vec, Array2D< int > &array)
 Checks if vec matches with any of the rows of array Returns the row number, or -1 if vec is not equal to any of the rows of array. More...
 
double select_kth (int k, Array1D< double > &arr)
 Select the k-th smallest element of an array arr. More...
 
double logdeterm (Array2D< double > &mat)
 Log-determinant of a real symmetric positive-definite matrix. More...
 
double trace (Array2D< double > &mat)
 Trace of a matrix. More...
 
double evalLogMVN (Array1D< double > &x, Array1D< double > &mu, Array2D< double > &Sigma)
 Evaluates the natural logarithm of a multivariate normal distribution. More...
 
Array2D< double > diag (Array1D< double > &diagonal_array)
 Returns a diagonal matrix with a given diagonal. More...
 
Array1D< double > copy (Array1D< double > &in_array)
 Returns a copy of 1D array. More...
 
Array2D< double > copy (Array2D< double > &in_array)
 Return a copy of 2D Array. More...
 
Array2D< double > mtxdel (Array2D< double > &A, int index, int dim)
 Deletes matrix columns or rows. Index specifies which column or row and dim = 1 deletes column, dim = 0 deletes the row. More...
 
Array1D< double > add (Array1D< double > &x, Array1D< double > &y)
 Add two 1D Arrays and returns sum (must be of the same shape) More...
 
Array2D< double > add (Array2D< double > &x, Array2D< double > &y)
 Add two 2D Arrays and returns sum (must be of same shape) More...
 
void addinplace (Array2D< double > &x, Array2D< double > &y)
 Add two 2D Arrays in place. Summation is returned as x. More...
 
void addinplace (Array1D< double > &x, Array1D< double > &y)
 Add two 1D Arrays in place. Summation is returned as x. More...
 
Array1D< double > subtract (Array1D< double > &x, Array1D< double > &y)
 Returns subtraction of two 1D Arrays (must be of the same shape) More...
 
Array2D< double > subtract (Array2D< double > &x, Array2D< double > &y)
 Returns subtraction of two 2D Arrays (must be of the same shape) More...
 
void subtractinplace (Array2D< double > &x, Array2D< double > &y)
 Subtract two 2D Arrays in place. Difference is returned as x. More...
 
void subtractinplace (Array1D< double > &x, Array1D< double > &y)
 Subtract two 1D Arrays in place. Difference is returned as x. More...
 
Array1D< double > scale (Array1D< double > &x, double alpha)
 Returns 1D Arrays scaled by a double. More...
 
Array2D< double > scale (Array2D< double > &x, double alpha)
 Returns 2D Array scaled by a double. More...
 
void scaleinplace (Array1D< double > &x, double alpha)
 Multiply Array1D by double in place. More...
 
void scaleinplace (Array1D< int > &x, int alpha)
 Multiply Array1D by int in place. More...
 
void scaleinplace (Array2D< double > &x, double alpha)
 Multiply Array2D by double in place. More...
 
void scaleinplace (Array2D< int > &x, int alpha)
 Multiply Array2D by int in place. More...
 
Array2D< double > dotmult (Array2D< double > &A, Array2D< double > &B)
 Returns the elementwise multiplication of two 2D Arrays. More...
 
Array1D< double > dotmult (Array1D< double > &A, Array1D< double > &B)
 Returns the elementwise multiplication of two 1D Arrays. More...
 
Array2D< double > dotdivide (Array2D< double > &A, Array2D< double > &B)
 Returns the elementwise division of two 2D Arrays. More...
 
Array1D< double > dotdivide (Array1D< double > &A, Array1D< double > &B)
 Returns the elementwise division of two 1D Arrays. More...
 
double norm (Array1D< double > &x)
 Returns norm of 1D Array (Euclidean) More...
 
double dist_sq (Array1D< double > &x, Array1D< double > &y, Array1D< double > &w)
 Weighted vector distance-squared. More...
 
Array2D< double > Trans (Array2D< double > &A)
 Returns the transpose of a 2D Array. More...
 
double dot (Array1D< double > &v1, Array1D< double > &v2)
 Returns the dot product of two 1D Arrays (must be of the same length) More...
 
Array1D< double > dot (Array2D< double > &A, Array1D< double > &x)
 Returns the matrix vector product. More...
 
Array1D< double > dot (Array1D< double > &x, Array2D< double > &A)
 
Array2D< double > dot (Array2D< double > &A, Array2D< double > &B)
 Returns the matrix matrix product. More...
 
Array2D< double > dotT (Array2D< double > &A, Array2D< double > &B)
 Returns the matrix matrix^T product. More...
 
Array2D< double > INV (Array2D< double > &A)
 Returns the inverse of a square 2D Array. More...
 
Array2D< double > AinvH (Array2D< double > &A, Array2D< double > &H)
 Solves linear system AX=H, i.e. returns A^(-1)*H, where A is real, symmetric and positive definite. More...
 
Array1D< double > Ainvb (Array2D< double > &A, Array1D< double > &b)
 Solves linear system Ax=b, i.e. return A^(-1)*b where A is real, symmetric and positive definite. More...
 
void LSTSQ (Array2D< double > &A, Array1D< double > &b, Array1D< double > &x)
 Least squares solution for overdetermined system. Note that A must be "taller than wide". Solution is returned in x. More...
 
void QR (Array2D< double > &B, Array2D< double > &Q, Array2D< double > &R)
 Computes the QR factorization of a 2D Array (need not be square) More...
 
void SVD (Array2D< double > &A, Array2D< double > &U, Array1D< double > &S, Array2D< double > &VT)
 Computes the SVD calculation of a 2D Array (need not be square) More...
 
void printarray (Array1D< double > &x)
 Prints 1D double Array to screen (alternative to for loop using cout) More...
 
void printarray (Array1D< int > &x)
 Prints 1D int Array to screen (alternative to for loop using cout) More...
 
void printarray (Array2D< double > &x)
 Prints 2D double Array to screen (alternative to for loop using cout) More...
 
void printarray (Array2D< int > &x)
 Prints 2D int Array to screen (alternative to for loop using cout) More...
 
+

Detailed Description

+

Tools to manipulate Array 1D and 2D objects. Some tools mimick MATLAB functionalities.

+

Function Documentation

+ +

◆ access()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
double access (int nx,
int ny,
Array1D< double > & arr_1,
int i,
int j 
)
+
+ +

Access element $j+i\times ny$ from 1D array 'arr_1'.

+ +
+
+ +

◆ add() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> add (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Add two 1D Arrays and returns sum (must be of the same shape)

+ +
+
+ +

◆ add() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> add (Array2D< double > & x,
Array2D< double > & y 
)
+
+ +

Add two 2D Arrays and returns sum (must be of same shape)

+ +
+
+ +

◆ addinplace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void addinplace (Array2D< double > & x,
Array2D< double > & y 
)
+
+ +

Add two 2D Arrays in place. Summation is returned as x.

+ +
+
+ +

◆ addinplace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void addinplace (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Add two 1D Arrays in place. Summation is returned as x.

+ +
+
+ +

◆ addVal() [1/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void addVal (int n,
T * arr1d,
val 
)
+
+ +

Adds 'val' to the first n elements of an array pointer (double or int)

+ +
+
+ +

◆ addVal() [2/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void addVal (int n,
double * arr1d,
double val 
)
+
+ +
+
+ +

◆ addVal() [3/9]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void addVal (int n,
int * arr1d,
int val 
)
+
+ +
+
+ +

◆ addVal() [4/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void addVal (Array1D< T > & arr1d,
val 
)
+
+ +

Adds 'val' to all elements of 1D array arr1d (double or int)

+ +
+
+ +

◆ addVal() [5/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void addVal (Array1D< double > & arr1d,
double val 
)
+
+ +
+
+ +

◆ addVal() [6/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void addVal (Array1D< int > & arr1d,
int val 
)
+
+ +
+
+ +

◆ addVal() [7/9]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void addVal (Array2D< T > & arr2d,
val 
)
+
+ +

Adds 'val' to all elements of 2D array arr2d (double or int)

+ +
+
+ +

◆ addVal() [8/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void addVal (Array2D< double > & arr2d,
double val 
)
+
+ +
+
+ +

◆ addVal() [9/9]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void addVal (Array2D< int > & arr2d,
int val 
)
+
+ +
+
+ +

◆ addVecAlphaVecPow()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void addVecAlphaVecPow (Array1D< double > & x,
double alpha,
Array1D< double > & y,
int ip 
)
+
+ +

Implements $x_i=x_i+\alpha y_i^ip$, where 'x' and 'y' are 1D arrays with $n$ elements.

+ +
+
+ +

◆ Ainvb()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> Ainvb (Array2D< double > & A,
Array1D< double > & b 
)
+
+ +

Solves linear system Ax=b, i.e. return A^(-1)*b where A is real, symmetric and positive definite.

+ +
+
+ +

◆ AinvH()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> AinvH (Array2D< double > & A,
Array2D< double > & H 
)
+
+ +

Solves linear system AX=H, i.e. returns A^(-1)*H, where A is real, symmetric and positive definite.

+ +
+
+ +

◆ append() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void append (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Append array y to array x in place (double format)

+ +
+
+ +

◆ append() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void append (Array1D< int > & x,
Array1D< int > & y 
)
+
+ +

Append array y to array x in place (int format)

+ +
+
+ +

◆ array1Dto2D() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void array1Dto2D (Array1D< T > & arr_1d,
Array2D< T > & arr 
)
+
+ +

Store a given 1d array in a 2d array with a single second dimension.

+ +
+
+ +

◆ array1Dto2D() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void array1Dto2D (Array1D< double > & arr_1d,
Array2D< double > & arr 
)
+
+ +
+
+ +

◆ array1Dto2D() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void array1Dto2D (Array1D< int > & arr_1d,
Array2D< int > & arr 
)
+
+ +
+
+ +

◆ array2Dto1D() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void array2Dto1D (Array2D< T > & arr_2d,
Array1D< T > & arr 
)
+
+ +

Store a given 2d array with a single second dimension in a 1d array.

+ +
+
+ +

◆ array2Dto1D() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void array2Dto1D (Array2D< double > & arr_2d,
Array1D< double > & arr 
)
+
+ +
+
+ +

◆ array2Dto1D() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void array2Dto1D (Array2D< int > & arr_2d,
Array1D< int > & arr 
)
+
+ +
+
+ +

◆ copy() [1/2]

+ +
+
+ + + + + + + + +
Array1D<double> copy (Array1D< double > & in_array)
+
+ +

Returns a copy of 1D array.

+ +
+
+ +

◆ copy() [2/2]

+ +
+
+ + + + + + + + +
Array2D<double> copy (Array2D< double > & in_array)
+
+ +

Return a copy of 2D Array.

+ +
+
+ +

◆ delCol() [1/6]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void delCol (Array2D< T > & A,
int icol 
)
+
+ +

Deletes column 'icol' from 2D array 'A'.

+
Todo:
This should move to Array2D class
+ +
+
+ +

◆ delCol() [2/6]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void delCol (Array2D< double > & A,
int icol 
)
+
+ +
+
+ +

◆ delCol() [3/6]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void delCol (Array2D< int > & A,
int icol 
)
+
+ +
+
+ +

◆ delCol() [4/6]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void delCol (Array1D< T > & x,
int icol 
)
+
+ +

Deletes element 'icol' from 1D array 'A'.

+
Todo:
This should move to Array1D class
+ +
+
+ +

◆ delCol() [5/6]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void delCol (Array1D< double > & x,
int icol 
)
+
+ +
+
+ +

◆ delCol() [6/6]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void delCol (Array1D< int > & x,
int icol 
)
+
+ +
+
+ +

◆ delRow() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void delRow (Array2D< T > & A,
int irow 
)
+
+ +

Deletes row 'irow' from 2D array 'A'.

+
Todo:
This should move to Array2D class
+ +
+
+ +

◆ delRow() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void delRow (Array2D< double > & A,
int irow 
)
+
+ +
+
+ +

◆ delRow() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void delRow (Array2D< int > & A,
int irow 
)
+
+ +
+
+ +

◆ diag()

+ +
+
+ + + + + + + + +
Array2D<double> diag (Array1D< double > & diagonal_array)
+
+ +

Returns a diagonal matrix with a given diagonal.

+ +
+
+ +

◆ dist_sq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double dist_sq (Array1D< double > & x,
Array1D< double > & y,
Array1D< double > & w 
)
+
+ +

Weighted vector distance-squared.

+ +
+
+ +

◆ dot() [1/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double dot (Array1D< double > & v1,
Array1D< double > & v2 
)
+
+ +

Returns the dot product of two 1D Arrays (must be of the same length)

+ +
+
+ +

◆ dot() [2/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dot (Array2D< double > & A,
Array1D< double > & x 
)
+
+ +

Returns the matrix vector product.

+ +
+
+ +

◆ dot() [3/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dot (Array1D< double > & x,
Array2D< double > & A 
)
+
+ +
+
+ +

◆ dot() [4/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dot (Array2D< double > & A,
Array2D< double > & B 
)
+
+ +

Returns the matrix matrix product.

+ +
+
+ +

◆ dotdivide() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dotdivide (Array2D< double > & A,
Array2D< double > & B 
)
+
+ +

Returns the elementwise division of two 2D Arrays.

+ +
+
+ +

◆ dotdivide() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dotdivide (Array1D< double > & A,
Array1D< double > & B 
)
+
+ +

Returns the elementwise division of two 1D Arrays.

+ +
+
+ +

◆ dotmult() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dotmult (Array2D< double > & A,
Array2D< double > & B 
)
+
+ +

Returns the elementwise multiplication of two 2D Arrays.

+ +
+
+ +

◆ dotmult() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dotmult (Array1D< double > & A,
Array1D< double > & B 
)
+
+ +

Returns the elementwise multiplication of two 1D Arrays.

+ +
+
+ +

◆ dotT()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dotT (Array2D< double > & A,
Array2D< double > & B 
)
+
+ +

Returns the matrix matrix^T product.

+ +
+
+ +

◆ evalLogMVN()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double evalLogMVN (Array1D< double > & x,
Array1D< double > & mu,
Array2D< double > & Sigma 
)
+
+ +

Evaluates the natural logarithm of a multivariate normal distribution.

+ +
+
+ +

◆ find() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void find (Array1D< T > & theta,
lmbda,
string type,
Array1D< int > & indx 
)
+
+ +

Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" ), larger or equal ( type="ge" ), smaller ( type="lt" ), smaller or equal ( type="le" ) than lmbda.

+ +
+
+ +

◆ find() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void find (Array1D< double > & theta,
double lmbda,
string type,
Array1D< int > & indx 
)
+
+ +
+
+ +

◆ find() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void find (Array1D< int > & theta,
int lmbda,
string type,
Array1D< int > & indx 
)
+
+ +
+
+ +

◆ flatten()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void flatten (Array2D< double > & arr_2,
Array1D< double > & arr_1 
)
+
+ +

Unfold/flatten a 2d array into a 1d array (double format)

+ +
+
+ +

◆ fold_1dto2d()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void fold_1dto2d (Array1D< double > & x1,
Array2D< double > & x2 
)
+
+ +

Fold a 1d array into a 2d array (double format)

+
Note
The dimension of the 1d array needs to be equal to the product of the dimensions of the 2d array
+ +
+
+ +

◆ generate_multigrid() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void generate_multigrid (Array2D< T > & multigrid,
Array2D< T > & grid 
)
+
+ +

Generates multigrid as a cartesian product of each column of grid.

+
Todo:
Should ideally be written in a recursive manner, similar to computeMultiIndexTP() in tools/multiindex.cpp
+ +
+
+ +

◆ generate_multigrid() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void generate_multigrid (Array2D< double > & multigrid,
Array2D< double > & grid 
)
+
+ +
+
+ +

◆ generate_multigrid() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void generate_multigrid (Array2D< int > & multigrid,
Array2D< int > & grid 
)
+
+ +
+
+ +

◆ getCol() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void getCol (Array2D< T > & arr2d,
int k,
Array1D< T > & arr1d 
)
+
+ +

Retrieves column 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'.

+ +
+
+ +

◆ getCol() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void getCol (Array2D< double > & arr2d,
int k,
Array1D< double > & arr1d 
)
+
+ +
+
+ +

◆ getCol() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void getCol (Array2D< int > & arr2d,
int k,
Array1D< int > & arr1d 
)
+
+ +
+
+ +

◆ getRow() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void getRow (Array2D< T > & arr2d,
int k,
Array1D< T > & arr1d 
)
+
+ +

Retrieves row 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'.

+ +
+
+ +

◆ getRow() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void getRow (Array2D< double > & arr2d,
int k,
Array1D< double > & arr1d 
)
+
+ +
+
+ +

◆ getRow() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void getRow (Array2D< int > & arr2d,
int k,
Array1D< int > & arr1d 
)
+
+ +
+
+ +

◆ intersect() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void intersect (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C,
Array1D< int > & iA,
Array1D< int > & iB 
)
+
+ +

Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order. It also returns the original locations of these entries in 1D arrays 'iA' and 'iB', respectively.

+
Note
Currently, duplicated entries in either 'A' and 'B' will be duplicated in 'C'
+ +
+
+ +

◆ intersect() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void intersect (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C 
)
+
+ +

Find common entries in 1D arrays 'A' and 'B' and return them in 'C', sorted in ascending order.

+
Note
Currently, duplicated entries in either 'A' and 'B' will be duplicated in 'C'
+ +
+
+ +

◆ INV()

+ +
+
+ + + + + + + + +
Array2D<double> INV (Array2D< double > & A)
+
+ +

Returns the inverse of a square 2D Array.

+ +
+
+ +

◆ is_equal() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_equal (Array1D< int > & a,
Array1D< int > & b 
)
+
+ +

Checks if two 1d int arrays are equal.

+ +
+
+ +

◆ is_equal() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_equal (Array1D< double > & a,
Array1D< double > & b 
)
+
+ +

Checks if two 1d double arrays are equal.

+ +
+
+ +

◆ is_less() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_less (Array1D< int > & a,
Array1D< int > & b 
)
+
+ +

Checks if one 1d int array is less than another (by first element, then by second, etc...)

+ +
+
+ +

◆ is_less() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_less (Array1D< double > & a,
Array1D< double > & b 
)
+
+ +

Checks if one 1d double array is less than another (by first element, then by second, etc...)

+ +
+
+ +

◆ logdeterm()

+ +
+
+ + + + + + + + +
double logdeterm (Array2D< double > & mat)
+
+ +

Log-determinant of a real symmetric positive-definite matrix.

+
Todo:
Check and catch the symmetric and positiv-definite conditions.
+ +
+
+ +

◆ LSTSQ()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void LSTSQ (Array2D< double > & A,
Array1D< double > & b,
Array1D< double > & x 
)
+
+ +

Least squares solution for overdetermined system. Note that A must be "taller than wide". Solution is returned in x.

+ +
+
+ +

◆ matPvec() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void matPvec (Array2D< T > & matrix,
const Array1D< T > & rc,
alpha,
char * RC 
)
+
+ +

Adds scaled row or column to all rows / columns of a matrix (double or int)

+
Note
RC is a character "R" or "C" for row or column, correspondingly
+ +
+
+ +

◆ matPvec() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void matPvec (Array2D< double > & matrix,
const Array1D< double > & rc,
double alpha,
char * RC 
)
+
+ +
+
+ +

◆ matPvec() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
template void matPvec (Array2D< int > & matrix,
const Array1D< int > & rc,
int alpha,
char * RC 
)
+
+ +
+
+ +

◆ MatTMat()

+ +
+
+ + + + + + + + +
Array2D<double> MatTMat (Array2D< double > & A)
+
+ +

Returns $A^T A$, where 'A' is a $\left[n\times k\right]$ 2D array.

+ +
+
+ +

◆ maxVal() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
T maxVal (const Array1D< T > & vector,
int * indx 
)
+
+ +

Returns maximum value in 'vector' and its location in *indx (double or int)

+ +
+
+ +

◆ maxVal() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template double maxVal (const Array1D< double > & vector,
int * indx 
)
+
+ +
+
+ +

◆ maxVal() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template int maxVal (const Array1D< int > & vector,
int * indx 
)
+
+ +
+
+ +

◆ merge() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void merge (Array2D< double > & x,
Array2D< double > & y,
Array2D< double > & xy 
)
+
+ +

Merge 2d double arrays (vertical stack)

+ +
+
+ +

◆ merge() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void merge (Array1D< double > & x,
Array1D< double > & y,
Array1D< double > & xy 
)
+
+ +

Merge 1d double arrays.

+ +
+
+ +

◆ merge() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void merge (Array1D< int > & x,
Array1D< int > & y,
Array1D< int > & xy 
)
+
+ +

Merge 1d int arrays.

+ +
+
+ +

◆ mtxdel()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> mtxdel (Array2D< double > & A,
int index,
int dim 
)
+
+ +

Deletes matrix columns or rows. Index specifies which column or row and dim = 1 deletes column, dim = 0 deletes the row.

+ +
+
+ +

◆ norm()

+ +
+
+ + + + + + + + +
double norm (Array1D< double > & x)
+
+ +

Returns norm of 1D Array (Euclidean)

+ +
+
+ +

◆ paddMatCol() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatCol (Array2D< double > & A,
Array1D< double > & x 
)
+
+ +

Padds 2D array 'A' with the column 'x'.

+
Note
the number of elements in 'x' should be the same as the number of rows in 'A'
+ +
+
+ +

◆ paddMatCol() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatCol (Array2D< int > & A,
Array1D< int > & x 
)
+
+ +

Padds 2D array 'A' with the column 'x'.

+
Note
the number of elements in 'x' should be the same as the number of rows in 'A'
+ +
+
+ +

◆ paddMatColScal()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void paddMatColScal (Array2D< double > & A,
Array1D< double > & x,
double scal 
)
+
+ +

Padds square 2D array 'A' $\left[n\times n\right]$ with the elements of 'x' and 'scal' as follows: $A_{n+1,i}=A_{i,n+1}=x_i$ and $A_{n+1,n+1}=scal$.

+ +
+
+ +

◆ paddMatRow() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatRow (Array2D< double > & A,
Array1D< double > & x 
)
+
+ +

Padds 2D array 'A' with the row 'x'.

+
Note
the number of elements in 'x' should be the same as the number of columns of 'A'
+ +
+
+ +

◆ paddMatRow() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatRow (Array2D< int > & A,
Array1D< int > & x 
)
+
+ +

Padds 2D array 'A' with the row 'x'.

+
Note
the number of elements in 'x' should be the same as the number of columns of 'A'
+ +
+
+ +

◆ paste() [1/4]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void paste (Array1D< T > & arr1,
Array1D< T > & arr2,
Array2D< T > & arr 
)
+
+ +

Paste two 1d arrays of same size into a single 2d array with second dimension equal to two.

+ +
+
+ +

◆ paste() [2/4]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void paste (Array1D< double > & arr1,
Array1D< double > & arr2,
Array2D< double > & arr 
)
+
+ +
+
+ +

◆ paste() [3/4]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void paste (Array1D< int > & arr1,
Array1D< int > & arr2,
Array2D< int > & arr 
)
+
+ +
+
+ +

◆ paste() [4/4]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void paste (Array2D< double > & x,
Array2D< double > & y,
Array2D< double > & xy 
)
+
+ +

Paste two 2D arrays next to each other (horizontal stack)

+ +
+
+ +

◆ printarray() [1/4]

+ +
+
+ + + + + + + + +
void printarray (Array1D< double > & x)
+
+ +

Prints 1D double Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ printarray() [2/4]

+ +
+
+ + + + + + + + +
void printarray (Array1D< int > & x)
+
+ +

Prints 1D int Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ printarray() [3/4]

+ +
+
+ + + + + + + + +
void printarray (Array2D< double > & x)
+
+ +

Prints 2D double Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ printarray() [4/4]

+ +
+
+ + + + + + + + +
void printarray (Array2D< int > & x)
+
+ +

Prints 2D int Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ prod_vecTmatvec()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double prod_vecTmatvec (Array1D< double > & a,
Array2D< double > & B,
Array1D< double > & c 
)
+
+ +

Returns $a^T B c$.

+ +
+
+ +

◆ prodAlphaMatMat()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatMat (Array2D< double > & A,
Array2D< double > & B,
double alpha,
Array2D< double > & C 
)
+
+ +

Returns $C=\alpha AB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements.

+ +
+
+ +

◆ prodAlphaMatTMat()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatTMat (Array2D< double > & A,
Array2D< double > & B,
double alpha,
Array2D< double > & C 
)
+
+ +

Returns $C=\alpha A^TB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements.

+ +
+
+ +

◆ prodAlphaMatTVec()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatTVec (Array2D< double > & A,
Array1D< double > & x,
double alpha,
Array1D< double > & y 
)
+
+ +

Returns $y=\alpha A^Tx$, where 'A' is a $\left[m\times n\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements.

+ +
+
+ +

◆ prodAlphaMatVec()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatVec (Array2D< double > & A,
Array1D< double > & x,
double alpha,
Array1D< double > & y 
)
+
+ +

Returns $y=\alpha Ax$, where 'A' is a $\left[n\times m\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements.

+ +
+
+ +

◆ QR()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void QR (Array2D< double > & B,
Array2D< double > & Q,
Array2D< double > & R 
)
+
+ +

Computes the QR factorization of a 2D Array (need not be square)

+ +
+
+ +

◆ quicksort3() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void quicksort3 (Array1D< double > & arr,
int l,
int r 
)
+
+ +

Quick-sort with 3-way partitioning of array between indices l and r.

+ +
+
+ +

◆ quicksort3() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void quicksort3 (Array2D< double > & arr,
int l,
int r,
int col 
)
+
+ +

Quick-sort with 3-way partitioning of 2d array between indices l and r, according to column col.

+ +
+
+ +

◆ quicksort3() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void quicksort3 (Array2D< double > & arr,
int l,
int r 
)
+
+ +

Quick-sort with 3-way partitioning of 2d array between indices l and r, and sorting is done comparing rows (by first element, then by second, etc...)

+ +
+
+ +

◆ scale() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> scale (Array1D< double > & x,
double alpha 
)
+
+ +

Returns 1D Arrays scaled by a double.

+ +
+
+ +

◆ scale() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> scale (Array2D< double > & x,
double alpha 
)
+
+ +

Returns 2D Array scaled by a double.

+ +
+
+ +

◆ scaleinplace() [1/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array1D< double > & x,
double alpha 
)
+
+ +

Multiply Array1D by double in place.

+ +
+
+ +

◆ scaleinplace() [2/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array1D< int > & x,
int alpha 
)
+
+ +

Multiply Array1D by int in place.

+ +
+
+ +

◆ scaleinplace() [3/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array2D< double > & x,
double alpha 
)
+
+ +

Multiply Array2D by double in place.

+ +
+
+ +

◆ scaleinplace() [4/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array2D< int > & x,
int alpha 
)
+
+ +

Multiply Array2D by int in place.

+ +
+
+ +

◆ select_kth()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double select_kth (int k,
Array1D< double > & arr 
)
+
+ +

Select the k-th smallest element of an array arr.

+ +
+
+ +

◆ setdiff()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void setdiff (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C 
)
+
+ +

Returns $ C=A\backslash B$ (C=Elements of A that are not in B); C is sorted in ascending order.

+ +
+
+ +

◆ setdiff_s()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void setdiff_s (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C 
)
+
+ +

Returns $ C=A\backslash B$ ( C=Elements of A that are not in B); C is sorted in ascending order.

+
Note
Assumes A is sorted and uses a faster algorithm than setdiff
+
Todo:
In future, this should sort A too and replace setdiff
+
Note
B is sorted on output as well
+ +
+
+ +

◆ shell_sort() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void shell_sort (int * a,
int n 
)
+
+ +

Sorts integer array.

+ +
+
+ +

◆ shell_sort() [2/3]

+ +
+
+ + + + + + + + +
void shell_sort (Array1D< int > & array)
+
+ +

Sorts integer array in ascending order.

+ +
+
+ +

◆ shell_sort() [3/3]

+ +
+
+ + + + + + + + +
void shell_sort (Array1D< double > & array)
+
+ +

Sorts double array in ascending order.

+ +
+
+ +

◆ shell_sort_all()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void shell_sort_all (Array2D< double > & array,
Array1D< int > & newInd,
Array1D< int > & oldInd 
)
+
+ +

Sorts double array in ascending order according to first column, then second column breaks the tie, and so on.

+ +
+
+ +

◆ shell_sort_col()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void shell_sort_col (Array2D< double > & array,
int col,
Array1D< int > & newInd,
Array1D< int > & oldInd 
)
+
+ +

Sorts double array in ascending order according to a given column.

+ +
+
+ +

◆ subMatrix_col() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void subMatrix_col (Array2D< T > & matrix,
Array1D< int > & ind,
Array2D< T > & submatrix 
)
+
+ +

Extracts from 'matrix' columns corresponding to indices 'ind' and returns them in 'submatrix' (double or int)

+ +
+
+ +

◆ subMatrix_col() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void subMatrix_col (Array2D< double > & matrix,
Array1D< int > & ind,
Array2D< double > & submatrix 
)
+
+ +
+
+ +

◆ subMatrix_col() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void subMatrix_col (Array2D< int > & matrix,
Array1D< int > & ind,
Array2D< int > & submatrix 
)
+
+ +
+
+ +

◆ subMatrix_row() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void subMatrix_row (Array2D< T > & matrix,
Array1D< int > & ind,
Array2D< T > & submatrix 
)
+
+ +

Extracts from 'matrix' rows corresponding to indices 'ind' and returns them in 'submatrix' (double or int)

+ +
+
+ +

◆ subMatrix_row() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void subMatrix_row (Array2D< double > & matrix,
Array1D< int > & ind,
Array2D< double > & submatrix 
)
+
+ +
+
+ +

◆ subMatrix_row() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void subMatrix_row (Array2D< int > & matrix,
Array1D< int > & ind,
Array2D< int > & submatrix 
)
+
+ +
+
+ +

◆ subtract() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> subtract (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Returns subtraction of two 1D Arrays (must be of the same shape)

+ +
+
+ +

◆ subtract() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> subtract (Array2D< double > & x,
Array2D< double > & y 
)
+
+ +

Returns subtraction of two 2D Arrays (must be of the same shape)

+ +
+
+ +

◆ subtractinplace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void subtractinplace (Array2D< double > & x,
Array2D< double > & y 
)
+
+ +

Subtract two 2D Arrays in place. Difference is returned as x.

+ +
+
+ +

◆ subtractinplace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void subtractinplace (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Subtract two 1D Arrays in place. Difference is returned as x.

+ +
+
+ +

◆ subVector() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void subVector (Array1D< T > & vector,
Array1D< int > & ind,
Array1D< T > & subvector 
)
+
+ +

Extracts from 'vector', elements corresponding to indices 'ind' and returns them in 'subvector' (double or int)

+ +
+
+ +

◆ subVector() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void subVector (Array1D< double > & vector,
Array1D< int > & ind,
Array1D< double > & subvector 
)
+
+ +
+
+ +

◆ subVector() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
template void subVector (Array1D< int > & vector,
Array1D< int > & ind,
Array1D< int > & subvector 
)
+
+ +
+
+ +

◆ SVD()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void SVD (Array2D< double > & A,
Array2D< double > & U,
Array1D< double > & S,
Array2D< double > & VT 
)
+
+ +

Computes the SVD calculation of a 2D Array (need not be square)

+ +
+
+ +

◆ swap() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void swap (Array1D< double > & arr,
int i,
int j 
)
+
+ +

Swap i-th and j-th elements of the array arr.

+ +
+
+ +

◆ swap() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void swap (Array2D< double > & arr,
int i,
int j 
)
+
+ +

Swap i-th and j-th rows of the 2d array arr.

+ +
+
+ +

◆ trace()

+ +
+
+ + + + + + + + +
double trace (Array2D< double > & mat)
+
+ +

Trace of a matrix.

+ +
+
+ +

◆ Trans()

+ +
+
+ + + + + + + + +
Array2D<double> Trans (Array2D< double > & A)
+
+ +

Returns the transpose of a 2D Array.

+ +
+
+ +

◆ transpose() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void transpose (Array2D< T > & x,
Array2D< T > & xt 
)
+
+ +

Transpose a 2d double or int array x and return the result in xt.

+ +
+
+ +

◆ transpose() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void transpose (Array2D< double > & x,
Array2D< double > & xt 
)
+
+ +
+
+ +

◆ transpose() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
template void transpose (Array2D< int > & x,
Array2D< int > & xt 
)
+
+ +
+
+ +

◆ vecIsInArray()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int vecIsInArray (Array1D< int > & vec,
Array2D< int > & array 
)
+
+ +

Checks if vec matches with any of the rows of array Returns the row number, or -1 if vec is not equal to any of the rows of array.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/arraytools_8h.html b/doc/doxygen/html/arraytools_8h.html new file mode 100644 index 00000000..3b1bad39 --- /dev/null +++ b/doc/doxygen/html/arraytools_8h.html @@ -0,0 +1,3678 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: arraytools.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
arraytools.h File Reference
+
+
+ +

Header file for array tools. +More...

+
#include <stdlib.h>
+#include "Array1D.h"
+#include "Array2D.h"
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

template<typename T >
void array1Dto2D (Array1D< T > &arr_1d, Array2D< T > &arr)
 Store a given 1d array in a 2d array with a single second dimension. More...
 
template<typename T >
void array2Dto1D (Array2D< T > &arr_2d, Array1D< T > &arr)
 Store a given 2d array with a single second dimension in a 1d array. More...
 
template<typename T >
void paste (Array1D< T > &arr1, Array1D< T > &arr2, Array2D< T > &arr)
 Paste two 1d arrays of same size into a single 2d array with second dimension equal to two. More...
 
template<typename T >
void generate_multigrid (Array2D< T > &multigrid, Array2D< T > &grid)
 Generates multigrid as a cartesian product of each column of grid. More...
 
void paste (Array2D< double > &x, Array2D< double > &y, Array2D< double > &xy)
 Paste two 2D arrays next to each other (horizontal stack) More...
 
void merge (Array2D< double > &x, Array2D< double > &y, Array2D< double > &xy)
 Merge 2d double arrays (vertical stack) More...
 
void merge (Array1D< double > &x, Array1D< double > &y, Array1D< double > &xy)
 Merge 1d double arrays. More...
 
void merge (Array1D< int > &x, Array1D< int > &y, Array1D< int > &xy)
 Merge 1d int arrays. More...
 
void append (Array1D< double > &x, Array1D< double > &y)
 Append array y to array x in place (double format) More...
 
void append (Array1D< int > &x, Array1D< int > &y)
 Append array y to array x in place (int format) More...
 
template<typename T >
void transpose (Array2D< T > &x, Array2D< T > &xt)
 Transpose a 2d double or int array x and return the result in xt. More...
 
void flatten (Array2D< double > &arr_2, Array1D< double > &arr_1)
 Unfold/flatten a 2d array into a 1d array (double format) More...
 
void fold_1dto2d (Array1D< double > &x1, Array2D< double > &x2)
 Fold a 1d array into a 2d array (double format) More...
 
void swap (Array1D< double > &arr, int i, int j)
 Swap i-th and j-th elements of the array arr. More...
 
void swap (Array2D< double > &arr, int i, int j)
 Swap i-th and j-th rows of the 2d array arr. More...
 
double access (int nx, int ny, Array1D< double > &arr_1, int i, int j)
 Access element $j+i\times ny$ from 1D array 'arr_1'. More...
 
template<typename T >
void getRow (Array2D< T > &arr2d, int k, Array1D< T > &arr1d)
 Retrieves row 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'. More...
 
template<typename T >
void getCol (Array2D< T > &arr2d, int k, Array1D< T > &arr1d)
 Retrieves column 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'. More...
 
template<typename T >
void addVal (int n, T *arr1d, T val)
 Adds 'val' to the first n elements of an array pointer (double or int) More...
 
template<typename T >
void addVal (Array1D< T > &arr1d, T val)
 Adds 'val' to all elements of 1D array arr1d (double or int) More...
 
template<typename T >
void addVal (Array2D< T > &arr2d, T val)
 Adds 'val' to all elements of 2D array arr2d (double or int) More...
 
template<typename T >
void subVector (Array1D< T > &vector, Array1D< int > &ind, Array1D< T > &subvector)
 Extracts from 'vector', elements corresponding to indices 'ind' and returns them in 'subvector' (double or int) More...
 
template<typename T >
void subMatrix_row (Array2D< T > &matrix, Array1D< int > &ind, Array2D< T > &submatrix)
 Extracts from 'matrix' rows corresponding to indices 'ind' and returns them in 'submatrix' (double or int) More...
 
template<typename T >
void subMatrix_col (Array2D< T > &matrix, Array1D< int > &ind, Array2D< T > &submatrix)
 Extracts from 'matrix' columns corresponding to indices 'ind' and returns them in 'submatrix' (double or int) More...
 
template<typename T >
void matPvec (Array2D< T > &matrix, const Array1D< T > &rc, T alpha, char *RC)
 Adds scaled row or column to all rows / columns of a matrix (double or int) More...
 
template<typename T >
maxVal (const Array1D< T > &vector, int *indx)
 Returns maximum value in 'vector' and its location in *indx (double or int) More...
 
void setdiff (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
 Returns $ C=A\backslash B$ (C=Elements of A that are not in B); C is sorted in ascending order. More...
 
void setdiff_s (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
 Returns $ C=A\backslash B$ ( C=Elements of A that are not in B); C is sorted in ascending order. More...
 
void shell_sort (int *a, int n)
 Sorts integer array. More...
 
void shell_sort (Array1D< int > &array)
 Sorts integer array in ascending order. More...
 
void shell_sort (Array1D< double > &array)
 Sorts double array in ascending order. More...
 
void shell_sort_col (Array2D< double > &array, int col, Array1D< int > &newInd, Array1D< int > &oldInd)
 Sorts double array in ascending order according to a given column. More...
 
void shell_sort_all (Array2D< double > &array, Array1D< int > &newInd, Array1D< int > &oldInd)
 Sorts double array in ascending order according to first column, then second column breaks the tie, and so on. More...
 
void quicksort3 (Array1D< double > &arr, int l, int r)
 Quick-sort with 3-way partitioning of array between indices l and r. More...
 
void quicksort3 (Array2D< double > &arr, int left, int right, int col)
 Quick-sort with 3-way partitioning of 2d array between indices l and r, according to column col. More...
 
void quicksort3 (Array2D< double > &arr, int left, int right)
 Quick-sort with 3-way partitioning of 2d array between indices l and r, and sorting is done comparing rows (by first element, then by second, etc...) More...
 
void intersect (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C, Array1D< int > &iA, Array1D< int > &iB)
 Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order. It also returns the original locations of these entries in 1D arrays 'iA' and 'iB', respectively. More...
 
void intersect (Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
 Find common entries in 1D arrays 'A' and 'B' and return them in 'C', sorted in ascending order. More...
 
template<typename T >
void find (Array1D< T > &theta, T lmbda, string type, Array1D< int > &indx)
 Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" ), larger or equal ( type="ge" ), smaller ( type="lt" ), smaller or equal ( type="le" ) than lmbda. More...
 
void prodAlphaMatVec (Array2D< double > &A, Array1D< double > &x, double alpha, Array1D< double > &y)
 Returns $y=\alpha Ax$, where 'A' is a $\left[n\times m\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements. More...
 
void prodAlphaMatTVec (Array2D< double > &A, Array1D< double > &x, double alpha, Array1D< double > &y)
 Returns $y=\alpha A^Tx$, where 'A' is a $\left[m\times n\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements. More...
 
void prodAlphaMatMat (Array2D< double > &A, Array2D< double > &B, double alpha, Array2D< double > &C)
 Returns $C=\alpha AB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements. More...
 
void prodAlphaMatTMat (Array2D< double > &A, Array2D< double > &B, double alpha, Array2D< double > &C)
 Returns $C=\alpha A^TB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements. More...
 
void addVecAlphaVecPow (Array1D< double > &x, double alpha, Array1D< double > &y, int ip)
 Implements $x_i=x_i+\alpha y_i^ip$, where 'x' and 'y' are 1D arrays with $n$ elements. More...
 
double prod_vecTmatvec (Array1D< double > &a, Array2D< double > &B, Array1D< double > &c)
 Returns $a^T B c$. More...
 
Array2D< double > MatTMat (Array2D< double > &A)
 Returns $A^T A$, where 'A' is a $\left[n\times k\right]$ 2D array. More...
 
template<typename T >
void delRow (Array2D< T > &A, int irow)
 Deletes row 'irow' from 2D array 'A'. More...
 
template<typename T >
void delCol (Array2D< T > &A, int icol)
 Deletes column 'icol' from 2D array 'A'. More...
 
template<typename T >
void delCol (Array1D< T > &x, int icol)
 Deletes element 'icol' from 1D array 'A'. More...
 
void paddMatRow (Array2D< double > &A, Array1D< double > &x)
 Padds 2D array 'A' with the row 'x'. More...
 
void paddMatCol (Array2D< double > &A, Array1D< double > &x)
 Padds 2D array 'A' with the column 'x'. More...
 
void paddMatRow (Array2D< int > &A, Array1D< int > &x)
 Padds 2D array 'A' with the row 'x'. More...
 
void paddMatCol (Array2D< int > &A, Array1D< int > &x)
 Padds 2D array 'A' with the column 'x'. More...
 
void paddMatColScal (Array2D< double > &A, Array1D< double > &x, double scal)
 Padds square 2D array 'A' $\left[n\times n\right]$ with the elements of 'x' and 'scal' as follows: $A_{n+1,i}=A_{i,n+1}=x_i$ and $A_{n+1,n+1}=scal$. More...
 
bool is_equal (Array1D< int > &a, Array1D< int > &b)
 Checks if two 1d int arrays are equal. More...
 
bool is_equal (Array1D< double > &a, Array1D< double > &b)
 Checks if two 1d double arrays are equal. More...
 
bool is_less (Array1D< int > &a, Array1D< int > &b)
 Checks if one 1d int array is less than another (by first element, then by second, etc...) More...
 
bool is_less (Array1D< double > &a, Array1D< double > &b)
 Checks if one 1d double array is less than another (by first element, then by second, etc...) More...
 
int vecIsInArray (Array1D< int > &vec, Array2D< int > &array)
 Checks if vec matches with any of the rows of array Returns the row number, or -1 if vec is not equal to any of the rows of array. More...
 
double select_kth (int k, Array1D< double > &arr)
 Select the k-th smallest element of an array arr. More...
 
double logdeterm (Array2D< double > &mat)
 Log-determinant of a real symmetric positive-definite matrix. More...
 
double trace (Array2D< double > &mat)
 Trace of a matrix. More...
 
double evalLogMVN (Array1D< double > &x, Array1D< double > &mu, Array2D< double > &Sigma)
 Evaluates the natural logarithm of a multivariate normal distribution. More...
 
Array2D< double > diag (Array1D< double > &diagonal_array)
 Returns a diagonal matrix with a given diagonal. More...
 
Array1D< double > copy (Array1D< double > &)
 Returns a copy of 1D array. More...
 
Array2D< double > copy (Array2D< double > &)
 Return a copy of 2D Array. More...
 
Array2D< double > mtxdel (Array2D< double > &, int index, int dim)
 Deletes matrix columns or rows. Index specifies which column or row and dim = 1 deletes column, dim = 0 deletes the row. More...
 
Array1D< double > add (Array1D< double > &, Array1D< double > &)
 Add two 1D Arrays and returns sum (must be of the same shape) More...
 
Array2D< double > add (Array2D< double > &, Array2D< double > &)
 Add two 2D Arrays and returns sum (must be of same shape) More...
 
void addinplace (Array2D< double > &x, Array2D< double > &y)
 Add two 2D Arrays in place. Summation is returned as x. More...
 
void addinplace (Array1D< double > &x, Array1D< double > &y)
 Add two 1D Arrays in place. Summation is returned as x. More...
 
Array1D< double > subtract (Array1D< double > &, Array1D< double > &)
 Returns subtraction of two 1D Arrays (must be of the same shape) More...
 
Array2D< double > subtract (Array2D< double > &, Array2D< double > &)
 Returns subtraction of two 2D Arrays (must be of the same shape) More...
 
void subtractinplace (Array2D< double > &x, Array2D< double > &y)
 Subtract two 2D Arrays in place. Difference is returned as x. More...
 
void subtractinplace (Array1D< double > &x, Array1D< double > &y)
 Subtract two 1D Arrays in place. Difference is returned as x. More...
 
Array1D< double > scale (Array1D< double > &, double)
 Returns 1D Arrays scaled by a double. More...
 
Array2D< double > scale (Array2D< double > &, double)
 Returns 2D Array scaled by a double. More...
 
void scaleinplace (Array1D< double > &, double)
 Multiply Array1D by double in place. More...
 
void scaleinplace (Array1D< int > &, int)
 Multiply Array1D by int in place. More...
 
void scaleinplace (Array2D< double > &, double)
 Multiply Array2D by double in place. More...
 
void scaleinplace (Array2D< int > &, int)
 Multiply Array2D by int in place. More...
 
Array2D< double > dotmult (Array2D< double > &A, Array2D< double > &B)
 Returns the elementwise multiplication of two 2D Arrays. More...
 
Array1D< double > dotmult (Array1D< double > &A, Array1D< double > &B)
 Returns the elementwise multiplication of two 1D Arrays. More...
 
Array2D< double > dotdivide (Array2D< double > &A, Array2D< double > &B)
 Returns the elementwise division of two 2D Arrays. More...
 
Array1D< double > dotdivide (Array1D< double > &A, Array1D< double > &B)
 Returns the elementwise division of two 1D Arrays. More...
 
double norm (Array1D< double > &)
 Returns norm of 1D Array (Euclidean) More...
 
double dist_sq (Array1D< double > &x, Array1D< double > &y, Array1D< double > &w)
 Weighted vector distance-squared. More...
 
Array2D< double > Trans (Array2D< double > &)
 Returns the transpose of a 2D Array. More...
 
double dot (Array1D< double > &, Array1D< double > &)
 Returns the dot product of two 1D Arrays (must be of the same length) More...
 
Array1D< double > dot (Array2D< double > &, Array1D< double > &)
 Returns the matrix vector product. More...
 
Array2D< double > dot (Array2D< double > &, Array2D< double > &)
 Returns the matrix matrix product. More...
 
Array2D< double > dotT (Array2D< double > &, Array2D< double > &)
 Returns the matrix matrix^T product. More...
 
Array2D< double > INV (Array2D< double > &A)
 Returns the inverse of a square 2D Array. More...
 
Array2D< double > AinvH (Array2D< double > &A, Array2D< double > &H)
 Solves linear system AX=H, i.e. returns A^(-1)*H, where A is real, symmetric and positive definite. More...
 
Array1D< double > Ainvb (Array2D< double > &A, Array1D< double > &b)
 Solves linear system Ax=b, i.e. return A^(-1)*b where A is real, symmetric and positive definite. More...
 
void LSTSQ (Array2D< double > &A, Array1D< double > &b, Array1D< double > &x)
 Least squares solution for overdetermined system. Note that A must be "taller than wide". Solution is returned in x. More...
 
void QR (Array2D< double > &B, Array2D< double > &Q, Array2D< double > &R)
 Computes the QR factorization of a 2D Array (need not be square) More...
 
void SVD (Array2D< double > &A, Array2D< double > &U, Array1D< double > &S, Array2D< double > &VT)
 Computes the SVD calculation of a 2D Array (need not be square) More...
 
void printarray (Array1D< double > &)
 Prints 1D double Array to screen (alternative to for loop using cout) More...
 
void printarray (Array1D< int > &)
 Prints 1D int Array to screen (alternative to for loop using cout) More...
 
void printarray (Array2D< double > &)
 Prints 2D double Array to screen (alternative to for loop using cout) More...
 
void printarray (Array2D< int > &)
 Prints 2D int Array to screen (alternative to for loop using cout) More...
 
+

Detailed Description

+

Header file for array tools.

+
Todo:

Some functions are not optimal in terms of array access.

+

Some functions should be templated and or moved to array class

+
+

Function Documentation

+ +

◆ access()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
double access (int nx,
int ny,
Array1D< double > & arr_1,
int i,
int j 
)
+
+ +

Access element $j+i\times ny$ from 1D array 'arr_1'.

+ +
+
+ +

◆ add() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> add (Array1D< double > & ,
Array1D< double > &  
)
+
+ +

Add two 1D Arrays and returns sum (must be of the same shape)

+ +
+
+ +

◆ add() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> add (Array2D< double > & ,
Array2D< double > &  
)
+
+ +

Add two 2D Arrays and returns sum (must be of same shape)

+ +
+
+ +

◆ addinplace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void addinplace (Array2D< double > & x,
Array2D< double > & y 
)
+
+ +

Add two 2D Arrays in place. Summation is returned as x.

+ +
+
+ +

◆ addinplace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void addinplace (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Add two 1D Arrays in place. Summation is returned as x.

+ +
+
+ +

◆ addVal() [1/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void addVal (int n,
T * arr1d,
val 
)
+
+ +

Adds 'val' to the first n elements of an array pointer (double or int)

+ +
+
+ +

◆ addVal() [2/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void addVal (Array1D< T > & arr1d,
val 
)
+
+ +

Adds 'val' to all elements of 1D array arr1d (double or int)

+ +
+
+ +

◆ addVal() [3/3]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void addVal (Array2D< T > & arr2d,
val 
)
+
+ +

Adds 'val' to all elements of 2D array arr2d (double or int)

+ +
+
+ +

◆ addVecAlphaVecPow()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void addVecAlphaVecPow (Array1D< double > & x,
double alpha,
Array1D< double > & y,
int ip 
)
+
+ +

Implements $x_i=x_i+\alpha y_i^ip$, where 'x' and 'y' are 1D arrays with $n$ elements.

+ +
+
+ +

◆ Ainvb()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> Ainvb (Array2D< double > & A,
Array1D< double > & b 
)
+
+ +

Solves linear system Ax=b, i.e. return A^(-1)*b where A is real, symmetric and positive definite.

+ +
+
+ +

◆ AinvH()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> AinvH (Array2D< double > & A,
Array2D< double > & H 
)
+
+ +

Solves linear system AX=H, i.e. returns A^(-1)*H, where A is real, symmetric and positive definite.

+ +
+
+ +

◆ append() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void append (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Append array y to array x in place (double format)

+ +
+
+ +

◆ append() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void append (Array1D< int > & x,
Array1D< int > & y 
)
+
+ +

Append array y to array x in place (int format)

+ +
+
+ +

◆ array1Dto2D()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void array1Dto2D (Array1D< T > & arr_1d,
Array2D< T > & arr 
)
+
+ +

Store a given 1d array in a 2d array with a single second dimension.

+ +
+
+ +

◆ array2Dto1D()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void array2Dto1D (Array2D< T > & arr_2d,
Array1D< T > & arr 
)
+
+ +

Store a given 2d array with a single second dimension in a 1d array.

+ +
+
+ +

◆ copy() [1/2]

+ +
+
+ + + + + + + + +
Array1D<double> copy (Array1D< double > & )
+
+ +

Returns a copy of 1D array.

+ +
+
+ +

◆ copy() [2/2]

+ +
+
+ + + + + + + + +
Array2D<double> copy (Array2D< double > & )
+
+ +

Return a copy of 2D Array.

+ +
+
+ +

◆ delCol() [1/2]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void delCol (Array2D< T > & A,
int icol 
)
+
+ +

Deletes column 'icol' from 2D array 'A'.

+
Todo:
This should move to Array2D class
+ +
+
+ +

◆ delCol() [2/2]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void delCol (Array1D< T > & x,
int icol 
)
+
+ +

Deletes element 'icol' from 1D array 'A'.

+
Todo:
This should move to Array1D class
+ +
+
+ +

◆ delRow()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void delRow (Array2D< T > & A,
int irow 
)
+
+ +

Deletes row 'irow' from 2D array 'A'.

+
Todo:
This should move to Array2D class
+ +
+
+ +

◆ diag()

+ +
+
+ + + + + + + + +
Array2D<double> diag (Array1D< double > & diagonal_array)
+
+ +

Returns a diagonal matrix with a given diagonal.

+ +
+
+ +

◆ dist_sq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double dist_sq (Array1D< double > & x,
Array1D< double > & y,
Array1D< double > & w 
)
+
+ +

Weighted vector distance-squared.

+ +
+
+ +

◆ dot() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double dot (Array1D< double > & ,
Array1D< double > &  
)
+
+ +

Returns the dot product of two 1D Arrays (must be of the same length)

+ +
+
+ +

◆ dot() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dot (Array2D< double > & ,
Array1D< double > &  
)
+
+ +

Returns the matrix vector product.

+ +
+
+ +

◆ dot() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dot (Array2D< double > & ,
Array2D< double > &  
)
+
+ +

Returns the matrix matrix product.

+ +
+
+ +

◆ dotdivide() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dotdivide (Array2D< double > & A,
Array2D< double > & B 
)
+
+ +

Returns the elementwise division of two 2D Arrays.

+ +
+
+ +

◆ dotdivide() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dotdivide (Array1D< double > & A,
Array1D< double > & B 
)
+
+ +

Returns the elementwise division of two 1D Arrays.

+ +
+
+ +

◆ dotmult() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dotmult (Array2D< double > & A,
Array2D< double > & B 
)
+
+ +

Returns the elementwise multiplication of two 2D Arrays.

+ +
+
+ +

◆ dotmult() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> dotmult (Array1D< double > & A,
Array1D< double > & B 
)
+
+ +

Returns the elementwise multiplication of two 1D Arrays.

+ +
+
+ +

◆ dotT()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> dotT (Array2D< double > & ,
Array2D< double > &  
)
+
+ +

Returns the matrix matrix^T product.

+ +
+
+ +

◆ evalLogMVN()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double evalLogMVN (Array1D< double > & x,
Array1D< double > & mu,
Array2D< double > & Sigma 
)
+
+ +

Evaluates the natural logarithm of a multivariate normal distribution.

+ +
+
+ +

◆ find()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void find (Array1D< T > & theta,
lmbda,
string type,
Array1D< int > & indx 
)
+
+ +

Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" ), larger or equal ( type="ge" ), smaller ( type="lt" ), smaller or equal ( type="le" ) than lmbda.

+ +
+
+ +

◆ flatten()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void flatten (Array2D< double > & arr_2,
Array1D< double > & arr_1 
)
+
+ +

Unfold/flatten a 2d array into a 1d array (double format)

+ +
+
+ +

◆ fold_1dto2d()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void fold_1dto2d (Array1D< double > & x1,
Array2D< double > & x2 
)
+
+ +

Fold a 1d array into a 2d array (double format)

+
Note
The dimension of the 1d array needs to be equal to the product of the dimensions of the 2d array
+ +
+
+ +

◆ generate_multigrid()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void generate_multigrid (Array2D< T > & multigrid,
Array2D< T > & grid 
)
+
+ +

Generates multigrid as a cartesian product of each column of grid.

+
Todo:
Should ideally be written in a recursive manner, similar to computeMultiIndexTP() in tools/multiindex.cpp
+ +
+
+ +

◆ getCol()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void getCol (Array2D< T > & arr2d,
int k,
Array1D< T > & arr1d 
)
+
+ +

Retrieves column 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'.

+ +
+
+ +

◆ getRow()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void getRow (Array2D< T > & arr2d,
int k,
Array1D< T > & arr1d 
)
+
+ +

Retrieves row 'k' from 2D array 'arr2d' and returns it in 1D array 'arr1d'.

+ +
+
+ +

◆ intersect() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void intersect (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C,
Array1D< int > & iA,
Array1D< int > & iB 
)
+
+ +

Finds common entries in 1D arrays 'A' and 'B' and returns them in 'C', sorted in ascending order. It also returns the original locations of these entries in 1D arrays 'iA' and 'iB', respectively.

+
Note
Currently, duplicated entries in either 'A' and 'B' will be duplicated in 'C'
+ +
+
+ +

◆ intersect() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void intersect (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C 
)
+
+ +

Find common entries in 1D arrays 'A' and 'B' and return them in 'C', sorted in ascending order.

+
Note
Currently, duplicated entries in either 'A' and 'B' will be duplicated in 'C'
+ +
+
+ +

◆ INV()

+ +
+
+ + + + + + + + +
Array2D<double> INV (Array2D< double > & A)
+
+ +

Returns the inverse of a square 2D Array.

+ +
+
+ +

◆ is_equal() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_equal (Array1D< int > & a,
Array1D< int > & b 
)
+
+ +

Checks if two 1d int arrays are equal.

+ +
+
+ +

◆ is_equal() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_equal (Array1D< double > & a,
Array1D< double > & b 
)
+
+ +

Checks if two 1d double arrays are equal.

+ +
+
+ +

◆ is_less() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_less (Array1D< int > & a,
Array1D< int > & b 
)
+
+ +

Checks if one 1d int array is less than another (by first element, then by second, etc...)

+ +
+
+ +

◆ is_less() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool is_less (Array1D< double > & a,
Array1D< double > & b 
)
+
+ +

Checks if one 1d double array is less than another (by first element, then by second, etc...)

+ +
+
+ +

◆ logdeterm()

+ +
+
+ + + + + + + + +
double logdeterm (Array2D< double > & mat)
+
+ +

Log-determinant of a real symmetric positive-definite matrix.

+
Todo:
Check and catch the symmetric and positiv-definite conditions.
+ +
+
+ +

◆ LSTSQ()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void LSTSQ (Array2D< double > & A,
Array1D< double > & b,
Array1D< double > & x 
)
+
+ +

Least squares solution for overdetermined system. Note that A must be "taller than wide". Solution is returned in x.

+ +
+
+ +

◆ matPvec()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void matPvec (Array2D< T > & matrix,
const Array1D< T > & rc,
alpha,
char * RC 
)
+
+ +

Adds scaled row or column to all rows / columns of a matrix (double or int)

+
Note
RC is a character "R" or "C" for row or column, correspondingly
+ +
+
+ +

◆ MatTMat()

+ +
+
+ + + + + + + + +
Array2D<double> MatTMat (Array2D< double > & A)
+
+ +

Returns $A^T A$, where 'A' is a $\left[n\times k\right]$ 2D array.

+ +
+
+ +

◆ maxVal()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
T maxVal (const Array1D< T > & vector,
int * indx 
)
+
+ +

Returns maximum value in 'vector' and its location in *indx (double or int)

+ +
+
+ +

◆ merge() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void merge (Array2D< double > & x,
Array2D< double > & y,
Array2D< double > & xy 
)
+
+ +

Merge 2d double arrays (vertical stack)

+ +
+
+ +

◆ merge() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void merge (Array1D< double > & x,
Array1D< double > & y,
Array1D< double > & xy 
)
+
+ +

Merge 1d double arrays.

+ +
+
+ +

◆ merge() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void merge (Array1D< int > & x,
Array1D< int > & y,
Array1D< int > & xy 
)
+
+ +

Merge 1d int arrays.

+ +
+
+ +

◆ mtxdel()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> mtxdel (Array2D< double > & ,
int index,
int dim 
)
+
+ +

Deletes matrix columns or rows. Index specifies which column or row and dim = 1 deletes column, dim = 0 deletes the row.

+ +
+
+ +

◆ norm()

+ +
+
+ + + + + + + + +
double norm (Array1D< double > & )
+
+ +

Returns norm of 1D Array (Euclidean)

+ +
+
+ +

◆ paddMatCol() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatCol (Array2D< double > & A,
Array1D< double > & x 
)
+
+ +

Padds 2D array 'A' with the column 'x'.

+
Note
the number of elements in 'x' should be the same as the number of rows in 'A'
+ +
+
+ +

◆ paddMatCol() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatCol (Array2D< int > & A,
Array1D< int > & x 
)
+
+ +

Padds 2D array 'A' with the column 'x'.

+
Note
the number of elements in 'x' should be the same as the number of rows in 'A'
+ +
+
+ +

◆ paddMatColScal()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void paddMatColScal (Array2D< double > & A,
Array1D< double > & x,
double scal 
)
+
+ +

Padds square 2D array 'A' $\left[n\times n\right]$ with the elements of 'x' and 'scal' as follows: $A_{n+1,i}=A_{i,n+1}=x_i$ and $A_{n+1,n+1}=scal$.

+ +
+
+ +

◆ paddMatRow() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatRow (Array2D< double > & A,
Array1D< double > & x 
)
+
+ +

Padds 2D array 'A' with the row 'x'.

+
Note
the number of elements in 'x' should be the same as the number of columns of 'A'
+ +
+
+ +

◆ paddMatRow() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void paddMatRow (Array2D< int > & A,
Array1D< int > & x 
)
+
+ +

Padds 2D array 'A' with the row 'x'.

+
Note
the number of elements in 'x' should be the same as the number of columns of 'A'
+ +
+
+ +

◆ paste() [1/2]

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void paste (Array1D< T > & arr1,
Array1D< T > & arr2,
Array2D< T > & arr 
)
+
+ +

Paste two 1d arrays of same size into a single 2d array with second dimension equal to two.

+ +
+
+ +

◆ paste() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void paste (Array2D< double > & x,
Array2D< double > & y,
Array2D< double > & xy 
)
+
+ +

Paste two 2D arrays next to each other (horizontal stack)

+ +
+
+ +

◆ printarray() [1/4]

+ +
+
+ + + + + + + + +
void printarray (Array1D< double > & )
+
+ +

Prints 1D double Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ printarray() [2/4]

+ +
+
+ + + + + + + + +
void printarray (Array1D< int > & )
+
+ +

Prints 1D int Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ printarray() [3/4]

+ +
+
+ + + + + + + + +
void printarray (Array2D< double > & )
+
+ +

Prints 2D double Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ printarray() [4/4]

+ +
+
+ + + + + + + + +
void printarray (Array2D< int > & )
+
+ +

Prints 2D int Array to screen (alternative to for loop using cout)

+ +
+
+ +

◆ prod_vecTmatvec()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double prod_vecTmatvec (Array1D< double > & a,
Array2D< double > & B,
Array1D< double > & c 
)
+
+ +

Returns $a^T B c$.

+ +
+
+ +

◆ prodAlphaMatMat()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatMat (Array2D< double > & A,
Array2D< double > & B,
double alpha,
Array2D< double > & C 
)
+
+ +

Returns $C=\alpha AB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements.

+ +
+
+ +

◆ prodAlphaMatTMat()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatTMat (Array2D< double > & A,
Array2D< double > & B,
double alpha,
Array2D< double > & C 
)
+
+ +

Returns $C=\alpha A^TB$, where 'A' and 'B' are $\left[m\times n\right]$ 2D arrays and 'alpha' is a scalar. The 2D array 'C' has $m\times m$ elements.

+ +
+
+ +

◆ prodAlphaMatTVec()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatTVec (Array2D< double > & A,
Array1D< double > & x,
double alpha,
Array1D< double > & y 
)
+
+ +

Returns $y=\alpha A^Tx$, where 'A' is a $\left[m\times n\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements.

+ +
+
+ +

◆ prodAlphaMatVec()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void prodAlphaMatVec (Array2D< double > & A,
Array1D< double > & x,
double alpha,
Array1D< double > & y 
)
+
+ +

Returns $y=\alpha Ax$, where 'A' is a $\left[n\times m\right]$ 2D array, 'x' is 1D array of size $m$ and 'alpha' is a scalar. The 1D array 'y' has $n$ elements.

+ +
+
+ +

◆ QR()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void QR (Array2D< double > & B,
Array2D< double > & Q,
Array2D< double > & R 
)
+
+ +

Computes the QR factorization of a 2D Array (need not be square)

+ +
+
+ +

◆ quicksort3() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void quicksort3 (Array1D< double > & arr,
int l,
int r 
)
+
+ +

Quick-sort with 3-way partitioning of array between indices l and r.

+ +
+
+ +

◆ quicksort3() [2/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void quicksort3 (Array2D< double > & arr,
int left,
int right,
int col 
)
+
+ +

Quick-sort with 3-way partitioning of 2d array between indices l and r, according to column col.

+ +
+
+ +

◆ quicksort3() [3/3]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void quicksort3 (Array2D< double > & arr,
int left,
int right 
)
+
+ +

Quick-sort with 3-way partitioning of 2d array between indices l and r, and sorting is done comparing rows (by first element, then by second, etc...)

+ +
+
+ +

◆ scale() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> scale (Array1D< double > & ,
double  
)
+
+ +

Returns 1D Arrays scaled by a double.

+ +
+
+ +

◆ scale() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> scale (Array2D< double > & ,
double  
)
+
+ +

Returns 2D Array scaled by a double.

+ +
+
+ +

◆ scaleinplace() [1/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array1D< double > & ,
double  
)
+
+ +

Multiply Array1D by double in place.

+ +
+
+ +

◆ scaleinplace() [2/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array1D< int > & ,
int  
)
+
+ +

Multiply Array1D by int in place.

+ +
+
+ +

◆ scaleinplace() [3/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array2D< double > & ,
double  
)
+
+ +

Multiply Array2D by double in place.

+ +
+
+ +

◆ scaleinplace() [4/4]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void scaleinplace (Array2D< int > & ,
int  
)
+
+ +

Multiply Array2D by int in place.

+ +
+
+ +

◆ select_kth()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double select_kth (int k,
Array1D< double > & arr 
)
+
+ +

Select the k-th smallest element of an array arr.

+ +
+
+ +

◆ setdiff()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void setdiff (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C 
)
+
+ +

Returns $ C=A\backslash B$ (C=Elements of A that are not in B); C is sorted in ascending order.

+ +
+
+ +

◆ setdiff_s()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void setdiff_s (Array1D< int > & A,
Array1D< int > & B,
Array1D< int > & C 
)
+
+ +

Returns $ C=A\backslash B$ ( C=Elements of A that are not in B); C is sorted in ascending order.

+
Note
Assumes A is sorted and uses a faster algorithm than setdiff
+
Todo:
In future, this should sort A too and replace setdiff
+
Note
B is sorted on output as well
+ +
+
+ +

◆ shell_sort() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void shell_sort (int * a,
int n 
)
+
+ +

Sorts integer array.

+ +
+
+ +

◆ shell_sort() [2/3]

+ +
+
+ + + + + + + + +
void shell_sort (Array1D< int > & array)
+
+ +

Sorts integer array in ascending order.

+ +
+
+ +

◆ shell_sort() [3/3]

+ +
+
+ + + + + + + + +
void shell_sort (Array1D< double > & array)
+
+ +

Sorts double array in ascending order.

+ +
+
+ +

◆ shell_sort_all()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void shell_sort_all (Array2D< double > & array,
Array1D< int > & newInd,
Array1D< int > & oldInd 
)
+
+ +

Sorts double array in ascending order according to first column, then second column breaks the tie, and so on.

+ +
+
+ +

◆ shell_sort_col()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void shell_sort_col (Array2D< double > & array,
int col,
Array1D< int > & newInd,
Array1D< int > & oldInd 
)
+
+ +

Sorts double array in ascending order according to a given column.

+ +
+
+ +

◆ subMatrix_col()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void subMatrix_col (Array2D< T > & matrix,
Array1D< int > & ind,
Array2D< T > & submatrix 
)
+
+ +

Extracts from 'matrix' columns corresponding to indices 'ind' and returns them in 'submatrix' (double or int)

+ +
+
+ +

◆ subMatrix_row()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void subMatrix_row (Array2D< T > & matrix,
Array1D< int > & ind,
Array2D< T > & submatrix 
)
+
+ +

Extracts from 'matrix' rows corresponding to indices 'ind' and returns them in 'submatrix' (double or int)

+ +
+
+ +

◆ subtract() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array1D<double> subtract (Array1D< double > & ,
Array1D< double > &  
)
+
+ +

Returns subtraction of two 1D Arrays (must be of the same shape)

+ +
+
+ +

◆ subtract() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> subtract (Array2D< double > & ,
Array2D< double > &  
)
+
+ +

Returns subtraction of two 2D Arrays (must be of the same shape)

+ +
+
+ +

◆ subtractinplace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void subtractinplace (Array2D< double > & x,
Array2D< double > & y 
)
+
+ +

Subtract two 2D Arrays in place. Difference is returned as x.

+ +
+
+ +

◆ subtractinplace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void subtractinplace (Array1D< double > & x,
Array1D< double > & y 
)
+
+ +

Subtract two 1D Arrays in place. Difference is returned as x.

+ +
+
+ +

◆ subVector()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + + + + + + + +
void subVector (Array1D< T > & vector,
Array1D< int > & ind,
Array1D< T > & subvector 
)
+
+ +

Extracts from 'vector', elements corresponding to indices 'ind' and returns them in 'subvector' (double or int)

+ +
+
+ +

◆ SVD()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void SVD (Array2D< double > & A,
Array2D< double > & U,
Array1D< double > & S,
Array2D< double > & VT 
)
+
+ +

Computes the SVD calculation of a 2D Array (need not be square)

+ +
+
+ +

◆ swap() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void swap (Array1D< double > & arr,
int i,
int j 
)
+
+ +

Swap i-th and j-th elements of the array arr.

+ +
+
+ +

◆ swap() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void swap (Array2D< double > & arr,
int i,
int j 
)
+
+ +

Swap i-th and j-th rows of the 2d array arr.

+ +
+
+ +

◆ trace()

+ +
+
+ + + + + + + + +
double trace (Array2D< double > & mat)
+
+ +

Trace of a matrix.

+ +
+
+ +

◆ Trans()

+ +
+
+ + + + + + + + +
Array2D<double> Trans (Array2D< double > & )
+
+ +

Returns the transpose of a 2D Array.

+ +
+
+ +

◆ transpose()

+ +
+
+
+template<typename T >
+ + + + + + + + + + + + + + + + + + +
void transpose (Array2D< T > & x,
Array2D< T > & xt 
)
+
+ +

Transpose a 2d double or int array x and return the result in xt.

+ +
+
+ +

◆ vecIsInArray()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int vecIsInArray (Array1D< int > & vec,
Array2D< int > & array 
)
+
+ +

Checks if vec matches with any of the rows of array Returns the row number, or -1 if vec is not equal to any of the rows of array.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/arraytools_8h_source.html b/doc/doxygen/html/arraytools_8h_source.html new file mode 100644 index 00000000..8e4e1b20 --- /dev/null +++ b/doc/doxygen/html/arraytools_8h_source.html @@ -0,0 +1,133 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: arraytools.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
arraytools.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
31 
32 #ifndef ARRAYTOOLS_H
33 #define ARRAYTOOLS_H
34 
35 #include <stdlib.h>
36 #include "Array1D.h"
37 #include "Array2D.h"
38 
40 template <typename T> void array1Dto2D(Array1D<T>& arr_1d,Array2D<T>& arr);
41 
43 template <typename T> void array2Dto1D(Array2D<T>& arr_2d,Array1D<T>& arr);
44 
46 template <typename T> void paste(Array1D<T>& arr1,Array1D<T>& arr2,Array2D<T>& arr);
47 
50 template <typename T> void generate_multigrid(Array2D<T>& multigrid,Array2D<T>& grid);
51 
54 
61 
65 void append(Array1D<int>& x, Array1D<int>& y);
66 
68 template <typename T> void transpose(Array2D<T> &x, Array2D<T> &xt);
69 
71 void flatten(Array2D<double>& arr_2, Array1D<double>& arr_1);
72 
77 
79 void swap(Array1D<double>& arr,int i,int j);
80 
82 void swap(Array2D<double>& arr,int i,int j);
83 
85 double access(int nx, int ny, Array1D<double>& arr_1, int i, int j);
86 
88 template <typename T> void getRow(Array2D<T> &arr2d, int k, Array1D<T> &arr1d);
89 
91 template <typename T> void getCol(Array2D<T> &arr2d, int k, Array1D<T> &arr1d);
92 
94 template <typename T> void addVal(int n, T *arr1d, T val) ;
95 
97 template <typename T> void addVal(Array1D<T> &arr1d, T val) ;
98 
100 template <typename T> void addVal(Array2D<T> &arr2d, T val) ;
101 
103 template <typename T> void subVector(Array1D<T> &vector, Array1D<int> &ind, Array1D<T> &subvector);
104 
106 template <typename T> void subMatrix_row(Array2D<T> &matrix, Array1D<int> &ind, Array2D<T> &submatrix);
107 
109 template <typename T> void subMatrix_col(Array2D<T> &matrix, Array1D<int> &ind, Array2D<T> &submatrix);
110 
113 template <typename T> void matPvec(Array2D<T> &matrix, const Array1D<T> &rc, T alpha, char *RC);
114 
116 template <typename T> T maxVal(const Array1D<T>& vector, int *indx) ;
117 
120 
126 
128 void shell_sort (int *a, int n) ;
130 void shell_sort(Array1D<int>& array);
132 void shell_sort(Array1D<double>& array);
134 void shell_sort_col(Array2D<double>& array,int col,Array1D<int>& newInd, Array1D<int>& oldInd);
136 void shell_sort_all(Array2D<double>& array,Array1D<int>& newInd, Array1D<int>& oldInd);
138 void quicksort3(Array1D<double>& arr, int l, int r);
140 void quicksort3(Array2D<double>& arr,int left, int right,int col);
142 void quicksort3(Array2D<double>& arr,int left, int right);
143 
151 
154 template <typename T> void find(Array1D<T> &theta, T lmbda, string type, Array1D<int> &indx) ;
155 
158 void prodAlphaMatVec (Array2D<double>& A, Array1D<double>& x, double alpha, Array1D<double>& y) ;
161 void prodAlphaMatTVec(Array2D<double>& A, Array1D<double>& x, double alpha, Array1D<double>& y) ;
164 void prodAlphaMatMat(Array2D<double>& A, Array2D<double>& B, double alpha, Array2D<double>& C);
167 void prodAlphaMatTMat(Array2D<double>& A, Array2D<double>& B, double alpha, Array2D<double>& C) ;
169 void addVecAlphaVecPow(Array1D<double>& x, double alpha, Array1D<double>& y, int ip) ;
174 
175 
178 template <typename T> void delRow(Array2D<T>& A, int irow) ;
179 
182 template <typename T> void delCol(Array2D<T> &A, int icol) ;
183 
186 template <typename T> void delCol(Array1D<T> &x, int icol) ;
187 
196 void paddMatRow(Array2D<int>& A, Array1D<int>& x) ;
199 void paddMatCol(Array2D<int>& A, Array1D<int>& x) ;
202 void paddMatColScal(Array2D<double>& A, Array1D<double>& x, double scal) ;
203 
205 bool is_equal(Array1D<int>& a, Array1D<int>& b);
209 bool is_less(Array1D<int>& a, Array1D<int>& b);
212 
215 int vecIsInArray(Array1D<int>& vec, Array2D<int>& array);
216 
218 double select_kth(int k, Array1D<double>& arr);
219 
222 double logdeterm(Array2D<double>& mat);
223 
225 double trace(Array2D<double>& mat);
226 
229 
231 Array2D<double> diag(Array1D<double>& diagonal_array);
232 /**********************************************************
233 NEW ROUTINES - Kenny
234 ***********************************************************/
235 
238 
241 
243 Array2D<double> mtxdel(Array2D<double>&, int index, int dim);
244 
247 
250 
253 
256 
259 
262 
265 
268 
271 
274 
276 void scaleinplace(Array1D<double>&, double);
277 
279 void scaleinplace(Array1D<int>&, int);
280 
282 void scaleinplace(Array2D<double>&, double);
283 
285 void scaleinplace(Array2D<int>&, int);
286 
289 
292 
295 
298 
300 double norm(Array1D<double>&);
301 
304 
307 
310 
313 
316 
319 
322 
325 
328 
331 
334 
337 
340 
342 void printarray(Array1D<int>&);
343 
346 
348 void printarray(Array2D<int>&);
349 
350 
351 //---------------------------------------------------------------------------------------
352 #endif // ARRAYTOOLS_H
Stores data of any type T in a 1D array.
Definition: Array1D.h:60
+
void SVD(Array2D< double > &A, Array2D< double > &U, Array1D< double > &S, Array2D< double > &VT)
Computes the SVD calculation of a 2D Array (need not be square)
Definition: arraytools.cpp:2268
+
void paddMatCol(Array2D< double > &A, Array1D< double > &x)
Padds 2D array &#39;A&#39; with the column &#39;x&#39;.
Definition: arraytools.cpp:1217
+
Array2D< double > mtxdel(Array2D< double > &, int index, int dim)
Deletes matrix columns or rows. Index specifies which column or row and dim = 1 deletes column...
Definition: arraytools.cpp:1600
+
void find(Array1D< T > &theta, T lmbda, string type, Array1D< int > &indx)
Return list of indices corresponding to elements of 1D array theta that are: larger ( type="gt" )...
Definition: arraytools.cpp:902
+
void quicksort3(Array1D< double > &arr, int l, int r)
Quick-sort with 3-way partitioning of array between indices l and r.
Definition: arraytools.cpp:754
+
void setdiff(Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
Returns (C=Elements of A that are not in B); C is sorted in ascending order.
Definition: arraytools.cpp:567
+
void subMatrix_row(Array2D< T > &matrix, Array1D< int > &ind, Array2D< T > &submatrix)
Extracts from &#39;matrix&#39; rows corresponding to indices &#39;ind&#39; and returns them in &#39;submatrix&#39; (double or...
Definition: arraytools.cpp:455
+
void scaleinplace(Array1D< double > &, double)
Multiply Array1D by double in place.
Definition: arraytools.cpp:1835
+
Array2D< double > MatTMat(Array2D< double > &A)
Returns , where &#39;A&#39; is a 2D array.
Definition: arraytools.cpp:1092
+
void fold_1dto2d(Array1D< double > &x1, Array2D< double > &x2)
Fold a 1d array into a 2d array (double format)
Definition: arraytools.cpp:317
+
void QR(Array2D< double > &B, Array2D< double > &Q, Array2D< double > &R)
Computes the QR factorization of a 2D Array (need not be square)
Definition: arraytools.cpp:2206
+
void shell_sort(int *a, int n)
Sorts integer array.
Definition: arraytools.cpp:608
+
void transpose(Array2D< T > &x, Array2D< T > &xt)
Transpose a 2d double or int array x and return the result in xt.
Definition: arraytools.cpp:278
+
Array2D< double > diag(Array1D< double > &diagonal_array)
Returns a diagonal matrix with a given diagonal.
Definition: arraytools.cpp:1566
+
void paddMatColScal(Array2D< double > &A, Array1D< double > &x, double scal)
Padds square 2D array &#39;A&#39; with the elements of &#39;x&#39; and &#39;scal&#39; as follows: and . ...
Definition: arraytools.cpp:1292
+
int vecIsInArray(Array1D< int > &vec, Array2D< int > &array)
Checks if vec matches with any of the rows of array Returns the row number, or -1 if vec is not equal...
Definition: arraytools.cpp:1404
+
void shell_sort_all(Array2D< double > &array, Array1D< int > &newInd, Array1D< int > &oldInd)
Sorts double array in ascending order according to first column, then second column breaks the tie...
Definition: arraytools.cpp:708
+
void prodAlphaMatTMat(Array2D< double > &A, Array2D< double > &B, double alpha, Array2D< double > &C)
Returns , where &#39;A&#39; and &#39;B&#39; are 2D arrays and &#39;alpha&#39; is a scalar. The 2D array &#39;C&#39; has elements...
Definition: arraytools.cpp:1033
+
double norm(Array1D< double > &)
Returns norm of 1D Array (Euclidean)
Definition: arraytools.cpp:1966
+
void LSTSQ(Array2D< double > &A, Array1D< double > &b, Array1D< double > &x)
Least squares solution for overdetermined system. Note that A must be "taller than wide"...
Definition: arraytools.cpp:2174
+
Array1D< double > scale(Array1D< double > &, double)
Returns 1D Arrays scaled by a double.
Definition: arraytools.cpp:1807
+
void merge(Array2D< double > &x, Array2D< double > &y, Array2D< double > &xy)
Merge 2d double arrays (vertical stack)
Definition: arraytools.cpp:178
+
Array2D< double > AinvH(Array2D< double > &A, Array2D< double > &H)
Solves linear system AX=H, i.e. returns A^(-1)*H, where A is real, symmetric and positive definite...
Definition: arraytools.cpp:2138
+
void setdiff_s(Array1D< int > &A, Array1D< int > &B, Array1D< int > &C)
Returns ( C=Elements of A that are not in B); C is sorted in ascending order.
Definition: arraytools.cpp:587
+
Array1D< double > copy(Array1D< double > &)
Returns a copy of 1D array.
Definition: arraytools.cpp:1583
+
void intersect(Array1D< int > &A, Array1D< int > &B, Array1D< int > &C, Array1D< int > &iA, Array1D< int > &iB)
Finds common entries in 1D arrays &#39;A&#39; and &#39;B&#39; and returns them in &#39;C&#39;, sorted in ascending order...
Definition: arraytools.cpp:836
+
void addVal(int n, T *arr1d, T val)
Adds &#39;val&#39; to the first n elements of an array pointer (double or int)
Definition: arraytools.cpp:399
+
void flatten(Array2D< double > &arr_2, Array1D< double > &arr_1)
Unfold/flatten a 2d array into a 1d array (double format)
Definition: arraytools.cpp:298
+
Definition: Array1D.h:471
+
Array2D< double > INV(Array2D< double > &A)
Returns the inverse of a square 2D Array.
Definition: arraytools.cpp:2108
+
void addVecAlphaVecPow(Array1D< double > &x, double alpha, Array1D< double > &y, int ip)
Implements , where &#39;x&#39; and &#39;y&#39; are 1D arrays with elements.
Definition: arraytools.cpp:1067
+
double dist_sq(Array1D< double > &x, Array1D< double > &y, Array1D< double > &w)
Weighted vector distance-squared.
Definition: arraytools.cpp:1973
+
void swap(Array1D< double > &arr, int i, int j)
Swap i-th and j-th elements of the array arr.
Definition: arraytools.cpp:336
+
void subVector(Array1D< T > &vector, Array1D< int > &ind, Array1D< T > &subvector)
Extracts from &#39;vector&#39;, elements corresponding to indices &#39;ind&#39; and returns them in &#39;subvector&#39; (doub...
Definition: arraytools.cpp:431
+
Array2D< double > dotmult(Array2D< double > &A, Array2D< double > &B)
Returns the elementwise multiplication of two 2D Arrays.
Definition: arraytools.cpp:1882
+
Stores data of any type T in a 2D array.
Definition: Array2D.h:59
+
void matPvec(Array2D< T > &matrix, const Array1D< T > &rc, T alpha, char *RC)
Adds scaled row or column to all rows / columns of a matrix (double or int)
Definition: arraytools.cpp:504
+
void prodAlphaMatTVec(Array2D< double > &A, Array1D< double > &x, double alpha, Array1D< double > &y)
Returns , where &#39;A&#39; is a 2D array, &#39;x&#39; is 1D array of size and &#39;alpha&#39; is a scalar. The 1D array &#39;y&#39; has elements.
Definition: arraytools.cpp:968
+
double trace(Array2D< double > &mat)
Trace of a matrix.
Definition: arraytools.cpp:1512
+
2D Array class for any type T
+
Array2D< double > dotT(Array2D< double > &, Array2D< double > &)
Returns the matrix matrix^T product.
Definition: arraytools.cpp:2083
+
Array1D< double > subtract(Array1D< double > &, Array1D< double > &)
Returns subtraction of two 1D Arrays (must be of the same shape)
Definition: arraytools.cpp:1721
+
Array2D< double > dotdivide(Array2D< double > &A, Array2D< double > &B)
Returns the elementwise division of two 2D Arrays.
Definition: arraytools.cpp:1924
+
void paddMatRow(Array2D< double > &A, Array1D< double > &x)
Padds 2D array &#39;A&#39; with the row &#39;x&#39;.
Definition: arraytools.cpp:1193
+
void delRow(Array2D< T > &A, int irow)
Deletes row &#39;irow&#39; from 2D array &#39;A&#39;.
Definition: arraytools.cpp:1114
+
void subtractinplace(Array2D< double > &x, Array2D< double > &y)
Subtract two 2D Arrays in place. Difference is returned as x.
Definition: arraytools.cpp:1765
+
static double x1[]
Definition: gkpclib.cpp:35
+
void append(Array1D< double > &x, Array1D< double > &y)
Append array y to array x in place (double format)
Definition: arraytools.cpp:247
+
void shell_sort_col(Array2D< double > &array, int col, Array1D< int > &newInd, Array1D< int > &oldInd)
Sorts double array in ascending order according to a given column.
Definition: arraytools.cpp:673
+
double evalLogMVN(Array1D< double > &x, Array1D< double > &mu, Array2D< double > &Sigma)
Evaluates the natural logarithm of a multivariate normal distribution.
Definition: arraytools.cpp:1524
+
Definition: Array1D.h:261
+
Array1D< double > add(Array1D< double > &, Array1D< double > &)
Add two 1D Arrays and returns sum (must be of the same shape)
Definition: arraytools.cpp:1632
+
void array1Dto2D(Array1D< T > &arr_1d, Array2D< T > &arr)
Store a given 1d array in a 2d array with a single second dimension.
Definition: arraytools.cpp:49
+
void getCol(Array2D< T > &arr2d, int k, Array1D< T > &arr1d)
Retrieves column &#39;k&#39; from 2D array &#39;arr2d&#39; and returns it in 1D array &#39;arr1d&#39;.
Definition: arraytools.cpp:386
+
void array2Dto1D(Array2D< T > &arr_2d, Array1D< T > &arr)
Store a given 2d array with a single second dimension in a 1d array.
Definition: arraytools.cpp:64
+
double logdeterm(Array2D< double > &mat)
Log-determinant of a real symmetric positive-definite matrix.
Definition: arraytools.cpp:1470
+
double prod_vecTmatvec(Array1D< double > &a, Array2D< double > &B, Array1D< double > &c)
Returns .
Definition: arraytools.cpp:1080
+
void prodAlphaMatVec(Array2D< double > &A, Array1D< double > &x, double alpha, Array1D< double > &y)
Returns , where &#39;A&#39; is a 2D array, &#39;x&#39; is 1D array of size and &#39;alpha&#39; is a scalar. The 1D array &#39;y&#39; has elements.
Definition: arraytools.cpp:936
+
bool is_less(Array1D< int > &a, Array1D< int > &b)
Checks if one 1d int array is less than another (by first element, then by second, etc...)
Definition: arraytools.cpp:1356
+
void addinplace(Array2D< double > &x, Array2D< double > &y)
Add two 2D Arrays in place. Summation is returned as x.
Definition: arraytools.cpp:1678
+
void prodAlphaMatMat(Array2D< double > &A, Array2D< double > &B, double alpha, Array2D< double > &C)
Returns , where &#39;A&#39; and &#39;B&#39; are 2D arrays and &#39;alpha&#39; is a scalar. The 2D array &#39;C&#39; has elements...
Definition: arraytools.cpp:999
+
double dot(Array1D< double > &, Array1D< double > &)
Returns the dot product of two 1D Arrays (must be of the same length)
Definition: arraytools.cpp:2003
+
void subMatrix_col(Array2D< T > &matrix, Array1D< int > &ind, Array2D< T > &submatrix)
Extracts from &#39;matrix&#39; columns corresponding to indices &#39;ind&#39; and returns them in &#39;submatrix&#39; (double...
Definition: arraytools.cpp:479
+
Array2D< double > Trans(Array2D< double > &)
Returns the transpose of a 2D Array.
Definition: arraytools.cpp:1987
+
bool is_equal(Array1D< int > &a, Array1D< int > &b)
Checks if two 1d int arrays are equal.
Definition: arraytools.cpp:1318
+
Array1D< double > Ainvb(Array2D< double > &A, Array1D< double > &b)
Solves linear system Ax=b, i.e. return A^(-1)*b where A is real, symmetric and positive definite...
Definition: arraytools.cpp:2156
+
void paste(Array1D< T > &arr1, Array1D< T > &arr2, Array2D< T > &arr)
Paste two 1d arrays of same size into a single 2d array with second dimension equal to two...
Definition: arraytools.cpp:85
+
1D Array class for any type T
+
void generate_multigrid(Array2D< T > &multigrid, Array2D< T > &grid)
Generates multigrid as a cartesian product of each column of grid.
Definition: arraytools.cpp:105
+
void printarray(Array1D< double > &)
Prints 1D double Array to screen (alternative to for loop using cout)
Definition: arraytools.cpp:2299
+
double select_kth(int k, Array1D< double > &arr)
Select the k-th smallest element of an array arr.
Definition: arraytools.cpp:1428
+
double access(int nx, int ny, Array1D< double > &arr_1, int i, int j)
Access element from 1D array &#39;arr_1&#39;.
Definition: arraytools.cpp:361
+
T maxVal(const Array1D< T > &vector, int *indx)
Returns maximum value in &#39;vector&#39; and its location in *indx (double or int)
Definition: arraytools.cpp:550
+
void delCol(Array2D< T > &A, int icol)
Deletes column &#39;icol&#39; from 2D array &#39;A&#39;.
Definition: arraytools.cpp:1143
+
void getRow(Array2D< T > &arr2d, int k, Array1D< T > &arr1d)
Retrieves row &#39;k&#39; from 2D array &#39;arr2d&#39; and returns it in 1D array &#39;arr1d&#39;.
Definition: arraytools.cpp:371
+
+ + + + diff --git a/doc/doxygen/html/bc_s.png b/doc/doxygen/html/bc_s.png new file mode 100644 index 00000000..224b29aa Binary files /dev/null and b/doc/doxygen/html/bc_s.png differ diff --git a/doc/doxygen/html/bcs_8cpp.html b/doc/doxygen/html/bcs_8cpp.html new file mode 100644 index 00000000..9d76bc82 --- /dev/null +++ b/doc/doxygen/html/bcs_8cpp.html @@ -0,0 +1,315 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: bcs.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
bcs.cpp File Reference
+
+
+ +

Implemenations of Bayesian compressive sensing algorithm. +More...

+
#include "stdlib.h"
+#include "stdio.h"
+#include "math.h"
+#include "assert.h"
+#include <sstream>
+#include <fstream>
+#include "bcs.h"
+#include "tools.h"
+#include "ftndefs.h"
+#include "deplapack.h"
+#include "arrayio.h"
+#include "arraytools.h"
+
+ + + + + + + +

+Functions

void BCS (Array2D< double > &PHI, Array1D< double > &y, double &sigma2, double eta, Array1D< double > &lambda_init, int adaptive, int optimal, double scale, int verbose, Array1D< double > &weights, Array1D< int > &used, Array1D< double > &errbars, Array1D< double > &basis, Array1D< double > &alpha, double &lambda)
 The implementation of the Bayesian Compressive Sensing algorithm using Laplace Priors. More...
 
void WBCS (Array2D< double > &PHI, Array1D< double > &y, double &sigma2, double eta, Array1D< double > &lambda_init, int adaptive, int optimal, double scale, int verbose, Array1D< double > &weights, Array1D< int > &used, Array1D< double > &errbars, Array1D< double > &basis, Array1D< double > &alpha, double &lambda, Array2D< double > &Sig)
 The implementation of the Bayesian Compressive Sensing algorithm using Laplace Priors. More...
 
+

Detailed Description

+

Implemenations of Bayesian compressive sensing algorithm.

+

Function Documentation

+ +

◆ BCS()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void BCS (Array2D< double > & PHI,
Array1D< double > & y,
double & sigma2,
double eta,
Array1D< double > & lambda_init,
int adaptive,
int optimal,
double scale,
int verbose,
Array1D< double > & weights,
Array1D< int > & used,
Array1D< double > & errbars,
Array1D< double > & basis,
Array1D< double > & alpha,
double & lambda 
)
+
+ +

The implementation of the Bayesian Compressive Sensing algorithm using Laplace Priors.

+

Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda.

+
Note
This function has been written relying on the algorithm and MATLAB code presented in http://ivpl.eecs.northwestern.edu/research/projects/bayesian-compressive-sensing-using-laplace-priors and references therein
+
Todo:
The array manipulations are not optimized - perhaps they need to be reconsidered using, say, fortran matrix-vector manipulation routines
+ +
+
+ +

◆ WBCS()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void WBCS (Array2D< double > & PHI,
Array1D< double > & y,
double & sigma2,
double eta,
Array1D< double > & lambda_init,
int adaptive,
int optimal,
double scale,
int verbose,
Array1D< double > & weights,
Array1D< int > & used,
Array1D< double > & errbars,
Array1D< double > & basis,
Array1D< double > & alpha,
double & lambda,
Array2D< double > & Sig 
)
+
+ +

The implementation of the Bayesian Compressive Sensing algorithm using Laplace Priors.

+

Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda.

+
Note
This function has been written relying on the algorithm and MATLAB code presented in http://ivpl.eecs.northwestern.edu/research/projects/bayesian-compressive-sensing-using-laplace-priors and references therein
+
Todo:
The array manipulations are not optimized - perhaps they need to be reconsidered using, say, fortran matrix-vector manipulation routines
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/bcs_8h.html b/doc/doxygen/html/bcs_8h.html new file mode 100644 index 00000000..df59d47e --- /dev/null +++ b/doc/doxygen/html/bcs_8h.html @@ -0,0 +1,328 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: bcs.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
bcs.h File Reference
+
+
+ +

Header for the implemenations of Bayesian compressive sensing algorithm. +More...

+
#include "Array1D.h"
+#include "Array2D.h"
+
+

Go to the source code of this file.

+ + + + +

+Macros

#define MAX_IT   1000
 
+ + + + + + + +

+Functions

void WBCS (Array2D< double > &PHI, Array1D< double > &y, double &sigma2, double eta, Array1D< double > &lambda_init, int adaptive, int optimal, double scale, int verbose, Array1D< double > &weights, Array1D< int > &used, Array1D< double > &errbars, Array1D< double > &basis, Array1D< double > &alpha, double &lambda, Array2D< double > &Sig)
 Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda. More...
 
void BCS (Array2D< double > &PHI, Array1D< double > &y, double &sigma2, double eta, Array1D< double > &lambda_init, int adaptive, int optimal, double scale, int verbose, Array1D< double > &weights, Array1D< int > &used, Array1D< double > &errbars, Array1D< double > &basis, Array1D< double > &alpha, double &lambda)
 Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda. More...
 
+

Detailed Description

+

Header for the implemenations of Bayesian compressive sensing algorithm.

+

Macro Definition Documentation

+ +

◆ MAX_IT

+ +
+
+ + + + +
#define MAX_IT   1000
+
+ +
+
+

Function Documentation

+ +

◆ BCS()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void BCS (Array2D< double > & PHI,
Array1D< double > & y,
double & sigma2,
double eta,
Array1D< double > & lambda_init,
int adaptive,
int optimal,
double scale,
int verbose,
Array1D< double > & weights,
Array1D< int > & used,
Array1D< double > & errbars,
Array1D< double > & basis,
Array1D< double > & alpha,
double & lambda 
)
+
+ +

Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda.

+

Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda.

+
Note
This function has been written relying on the algorithm and MATLAB code presented in http://ivpl.eecs.northwestern.edu/research/projects/bayesian-compressive-sensing-using-laplace-priors and references therein
+
Todo:
The array manipulations are not optimized - perhaps they need to be reconsidered using, say, fortran matrix-vector manipulation routines
+ +
+
+ +

◆ WBCS()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void WBCS (Array2D< double > & PHI,
Array1D< double > & y,
double & sigma2,
double eta,
Array1D< double > & lambda_init,
int adaptive,
int optimal,
double scale,
int verbose,
Array1D< double > & weights,
Array1D< int > & used,
Array1D< double > & errbars,
Array1D< double > & basis,
Array1D< double > & alpha,
double & lambda,
Array2D< double > & Sig 
)
+
+ +

Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda.

+

Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2, stopping criterion eta, hierarchical prior parameter lambda_init, adaptivity,optimality, scale and verbosity flags, produces weights of the retained bases, their corresponding number (in the array 'used'), errorbars, next projection basis (if adaptive), and estimates for prior hyperparameters alpha and lambda.

+
Note
This function has been written relying on the algorithm and MATLAB code presented in http://ivpl.eecs.northwestern.edu/research/projects/bayesian-compressive-sensing-using-laplace-priors and references therein
+
Todo:
The array manipulations are not optimized - perhaps they need to be reconsidered using, say, fortran matrix-vector manipulation routines
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/bcs_8h_source.html b/doc/doxygen/html/bcs_8h_source.html new file mode 100644 index 00000000..a5695cc3 --- /dev/null +++ b/doc/doxygen/html/bcs_8h_source.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: bcs.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
bcs.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
29 
30 #ifndef BCS_H
31 #define BCS_H
32 
33 #include "Array1D.h"
34 #include "Array2D.h"
35 
36 
37 #define MAX_IT 1000
38 
39 
44 void WBCS(Array2D<double> &PHI, Array1D<double> &y, double &sigma2,
45  double eta, Array1D<double> &lambda_init,
46  int adaptive, int optimal, double scale, int verbose,
47  Array1D<double> &weights, Array1D<int> &used,
48  Array1D<double> &errbars, Array1D<double> &basis,
49  Array1D<double> &alpha, double &lambda, Array2D<double> &Sig);
50 
55 void BCS(Array2D<double> &PHI, Array1D<double> &y, double &sigma2,
56  double eta, Array1D<double> &lambda_init,
57  int adaptive, int optimal, double scale, int verbose,
58  Array1D<double> &weights, Array1D<int> &used,
59  Array1D<double> &errbars, Array1D<double> &basis,
60  Array1D<double> &alpha, double &lambda) ;
61 
62 
63 #endif // BCS_H
Array1D< double > scale(Array1D< double > &x, double alpha)
Returns 1D Arrays scaled by a double.
Definition: arraytools.cpp:1807
+
void BCS(Array2D< double > &PHI, Array1D< double > &y, double &sigma2, double eta, Array1D< double > &lambda_init, int adaptive, int optimal, double scale, int verbose, Array1D< double > &weights, Array1D< int > &used, Array1D< double > &errbars, Array1D< double > &basis, Array1D< double > &alpha, double &lambda)
Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2...
Definition: bcs.cpp:81
+
Definition: Array1D.h:471
+ +
2D Array class for any type T
+
Definition: Array1D.h:261
+
void WBCS(Array2D< double > &PHI, Array1D< double > &y, double &sigma2, double eta, Array1D< double > &lambda_init, int adaptive, int optimal, double scale, int verbose, Array1D< double > &weights, Array1D< int > &used, Array1D< double > &errbars, Array1D< double > &basis, Array1D< double > &alpha, double &lambda, Array2D< double > &Sig)
Given the projection matrix PHI, the measurement vector y, initial noise variance sigma2...
Definition: bcs.cpp:503
+
1D Array class for any type T
+
+ + + + diff --git a/doc/doxygen/html/bdwn.png b/doc/doxygen/html/bdwn.png new file mode 100644 index 00000000..940a0b95 Binary files /dev/null and b/doc/doxygen/html/bdwn.png differ diff --git a/doc/doxygen/html/citelist.html b/doc/doxygen/html/citelist.html new file mode 100644 index 00000000..8b2e93fa --- /dev/null +++ b/doc/doxygen/html/citelist.html @@ -0,0 +1,59 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Bibliography + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Bibliography
+
+
+
+
[1]
+

Mark Orr. Introduction to radial basis function networks. Technical Report, Center for Cognitive Science, University of Edinburgh, 1996.

+

+
+
+
+ + + + diff --git a/doc/doxygen/html/classArray1D-members.html b/doc/doxygen/html/classArray1D-members.html new file mode 100644 index 00000000..9be12b4a --- /dev/null +++ b/doc/doxygen/html/classArray1D-members.html @@ -0,0 +1,88 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Array1D< T > Member List
+
+
+ +

This is the complete list of members for Array1D< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array1D()Array1D< T >inline
Array1D(const int &nx)Array1D< T >inline
Array1D(const int &nx, const T &t)Array1D< T >inline
Array1D(const Array1D &obj)Array1D< T >inline
Clear()Array1D< T >inline
data_Array1D< T >
DumpBinary(FILE *f_out) constArray1D< T >inline
DumpBinary(char *filename)Array1D< T >inline
DumpBinary4py(char *filename)Array1D< T >inline
erase(int ix)Array1D< T >inline
flatten()Array1D< T >inline
GetArrayPointer()Array1D< T >inline
GetConstArrayPointer() constArray1D< T >inline
insert(Array1D< T > &insarr, int ix)Array1D< T >inline
insert(const T &insval, int ix)Array1D< T >inline
Length() constArray1D< T >inline
operator()(int ix)Array1D< T >inline
operator()(int ix) constArray1D< T >inline
operator=(const Array1D &obj)Array1D< T >inline
operator[](int i)Array1D< T >inline
PushBack(const T &t)Array1D< T >inline
ReadBinary(FILE *f_in)Array1D< T >inline
ReadBinary(char *filename)Array1D< T >inline
ReadBinary4py(char *filename, int n)Array1D< T >inline
Resize(const int &nx)Array1D< T >inline
Resize(const int &nx, const T &t)Array1D< T >inline
setArray(vector< T > inarray)Array1D< T >inline
SetValue(const T &t)Array1D< T >inline
type()Array1D< T >inline
XSize() constArray1D< T >inline
xsize_Array1D< T >
~Array1D()Array1D< T >inline
+ + + + diff --git a/doc/doxygen/html/classArray1D.html b/doc/doxygen/html/classArray1D.html new file mode 100644 index 00000000..7d968178 --- /dev/null +++ b/doc/doxygen/html/classArray1D.html @@ -0,0 +1,1127 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array1D< T > Class Template Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Array1D< T > Class Template Reference
+
+
+ +

Stores data of any type T in a 1D array. + More...

+ +

#include <Array1D.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Array1D ()
 Default constructor, which does not allocate any memory. More...
 
 Array1D (const int &nx)
 Constructor that allocates the memory. More...
 
 Array1D (const int &nx, const T &t)
 Constructor that allocates and initializes the data to a value t. More...
 
Array1Doperator= (const Array1D &obj)
 Assignment operator copies the data structure by value. More...
 
 Array1D (const Array1D &obj)
 Copy constructor. More...
 
 ~Array1D ()
 Destructor that frees up the memory. More...
 
void Clear ()
 Function to clear the memory. More...
 
int XSize () const
 Returns size in the x-direction. More...
 
int Length () const
 Returns length (i.e. size in the x-direction) More...
 
void Resize (const int &nx)
 Resizes the array. More...
 
void Resize (const int &nx, const T &t)
 Resizes the array and sets ALL entries to the specified value. More...
 
void SetValue (const T &t)
 Set all values in the array to the given value. More...
 
void PushBack (const T &t)
 Add element to the end of the vector. More...
 
T * GetArrayPointer ()
 Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
const T * GetConstArrayPointer () const
 Return a const point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
T & operator() (int ix)
 
const T & operator() (int ix) const
 
void insert (Array1D< T > &insarr, int ix)
 Insert a given array to the position ix. More...
 
void insert (const T &insval, int ix)
 Insert a given value to the position ix. More...
 
void erase (int ix)
 Erase the value from the position ix. More...
 
void DumpBinary (FILE *f_out) const
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (FILE *f_in)
 Read contents of the array from a file in binary format. More...
 
T & operator[] (int i)
 
void DumpBinary (char *filename)
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (char *filename)
 
void DumpBinary4py (char *filename)
 
void ReadBinary4py (char *filename, int n)
 
void setArray (vector< T > inarray)
 
vector< T > flatten ()
 
string type ()
 
+ + + + + +

+Public Attributes

int xsize_
 
vector< T > data_
 
+

Detailed Description

+

template<typename T>
+class Array1D< T >

+ +

Stores data of any type T in a 1D array.

+

This class also provides a Fortran-like access operator () as well as a function to access the data in the array through a pointer that can be passed to F77 or C routines.

Author
Bert Debusschere bjdeb.nosp@m.us@s.nosp@m.andia.nosp@m..gov
+
Date
Apr 2005 - Nov 2007
+
Note
Inspired by Helgi Adalsteinsson's Array class implementation
+
Todo:
double check copy constructor
+

Constructor & Destructor Documentation

+ +

◆ Array1D() [1/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
Array1D< T >::Array1D ()
+
+inline
+
+ +

Default constructor, which does not allocate any memory.

+ +
+
+ +

◆ Array1D() [2/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
Array1D< T >::Array1D (const int & nx)
+
+inline
+
+ +

Constructor that allocates the memory.

+ +
+
+ +

◆ Array1D() [3/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Array1D< T >::Array1D (const int & nx,
const T & t 
)
+
+inline
+
+ +

Constructor that allocates and initializes the data to a value t.

+ +
+
+ +

◆ Array1D() [4/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
Array1D< T >::Array1D (const Array1D< T > & obj)
+
+inline
+
+ +

Copy constructor.

+ +
+
+ +

◆ ~Array1D()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
Array1D< T >::~Array1D ()
+
+inline
+
+ +

Destructor that frees up the memory.

+ +
+
+

Member Function Documentation

+ +

◆ Clear()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
void Array1D< T >::Clear ()
+
+inline
+
+ +

Function to clear the memory.

+ +
+
+ +

◆ DumpBinary() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::DumpBinary (FILE * f_out) const
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::DumpBinary (char * filename)
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary4py()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::DumpBinary4py (char * filename)
+
+inline
+
+ +
+
+ +

◆ erase()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::erase (int ix)
+
+inline
+
+ +

Erase the value from the position ix.

+ +
+
+ +

◆ flatten()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
vector<T> Array1D< T >::flatten ()
+
+inline
+
+ +
+
+ +

◆ GetArrayPointer()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
T* Array1D< T >::GetArrayPointer ()
+
+inline
+
+ +

Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ GetConstArrayPointer()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
const T* Array1D< T >::GetConstArrayPointer () const
+
+inline
+
+ +

Return a const point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ insert() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< T >::insert (Array1D< T > & insarr,
int ix 
)
+
+inline
+
+ +

Insert a given array to the position ix.

+
Note
ix=0 means insert at the beginning, ix=xsize_ means insert at the end
+ +
+
+ +

◆ insert() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< T >::insert (const T & insval,
int ix 
)
+
+inline
+
+ +

Insert a given value to the position ix.

+
Note
ix=0 means insert at the beginning, ix=xsize_ means insert at the end
+ +
+
+ +

◆ Length()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
int Array1D< T >::Length () const
+
+inline
+
+ +

Returns length (i.e. size in the x-direction)

+ +
+
+ +

◆ operator()() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
T& Array1D< T >::operator() (int ix)
+
+inline
+
+ +
+
+ +

◆ operator()() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
const T& Array1D< T >::operator() (int ix) const
+
+inline
+
+ +
+
+ +

◆ operator=()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
Array1D& Array1D< T >::operator= (const Array1D< T > & obj)
+
+inline
+
+ +

Assignment operator copies the data structure by value.

+ +
+
+ +

◆ operator[]()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
T& Array1D< T >::operator[] (int i)
+
+inline
+
+ +
+
+ +

◆ PushBack()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::PushBack (const T & t)
+
+inline
+
+ +

Add element to the end of the vector.

+ +
+
+ +

◆ ReadBinary() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::ReadBinary (FILE * f_in)
+
+inline
+
+ +

Read contents of the array from a file in binary format.

+ +
+
+ +

◆ ReadBinary() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::ReadBinary (char * filename)
+
+inline
+
+ +
+
+ +

◆ ReadBinary4py()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< T >::ReadBinary4py (char * filename,
int n 
)
+
+inline
+
+ +
+
+ +

◆ Resize() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::Resize (const int & nx)
+
+inline
+
+ +

Resizes the array.

+ +
+
+ +

◆ Resize() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< T >::Resize (const int & nx,
const T & t 
)
+
+inline
+
+ +

Resizes the array and sets ALL entries to the specified value.

+
Warning
All original data will get lost if this function is used!
+ +
+
+ +

◆ setArray()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::setArray (vector< T > inarray)
+
+inline
+
+ +
+
+ +

◆ SetValue()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array1D< T >::SetValue (const T & t)
+
+inline
+
+ +

Set all values in the array to the given value.

+ +
+
+ +

◆ type()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
string Array1D< T >::type ()
+
+inline
+
+ +
+
+ +

◆ XSize()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
int Array1D< T >::XSize () const
+
+inline
+
+ +

Returns size in the x-direction.

+ +
+
+

Member Data Documentation

+ +

◆ data_

+ +
+
+
+template<typename T>
+ + + + +
vector<T> Array1D< T >::data_
+
+ +
+
+ +

◆ xsize_

+ +
+
+
+template<typename T>
+ + + + +
int Array1D< T >::xsize_
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classArray1D_3_01double_01_4-members.html b/doc/doxygen/html/classArray1D_3_01double_01_4-members.html new file mode 100644 index 00000000..459e205b --- /dev/null +++ b/doc/doxygen/html/classArray1D_3_01double_01_4-members.html @@ -0,0 +1,90 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Array1D< double > Member List
+
+
+ +

This is the complete list of members for Array1D< double >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array1D()Array1D< double >inline
Array1D(const int &nx)Array1D< double >inline
Array1D(const int &nx, const double &t)Array1D< double >inline
Array1D(const Array1D &obj)Array1D< double >inline
Clear()Array1D< double >inline
data_Array1D< double >
DumpBinary(FILE *f_out) constArray1D< double >inline
DumpBinary(char *filename)Array1D< double >inline
DumpBinary4py(char *filename)Array1D< double >inline
erase(int ix)Array1D< double >inline
flatten()Array1D< double >inline
GetArrayPointer()Array1D< double >inline
GetConstArrayPointer() constArray1D< double >inline
getnpdblArray(double *outarray, int n)Array1D< double >inline
insert(Array1D< double > &insarr, int ix)Array1D< double >inline
insert(const double &insval, int ix)Array1D< double >inline
Length() constArray1D< double >inline
operator()(int ix)Array1D< double >inline
operator()(int ix) constArray1D< double >inline
operator=(const Array1D &obj)Array1D< double >inline
operator[](int i)Array1D< double >inline
PushBack(const double &t)Array1D< double >inline
ReadBinary(FILE *f_in)Array1D< double >inline
ReadBinary(char *filename)Array1D< double >inline
ReadBinary4py(char *filename, int n)Array1D< double >inline
Resize(const int &nx)Array1D< double >inline
Resize(const int &nx, const double &t)Array1D< double >inline
setArray(vector< double > inarray)Array1D< double >inline
setnpdblArray(double *inarray, int n)Array1D< double >inline
SetValue(const double &t)Array1D< double >inline
type()Array1D< double >inline
XSize() constArray1D< double >inline
xsize_Array1D< double >private
~Array1D()Array1D< double >inline
+ + + + diff --git a/doc/doxygen/html/classArray1D_3_01double_01_4.html b/doc/doxygen/html/classArray1D_3_01double_01_4.html new file mode 100644 index 00000000..b9c88b01 --- /dev/null +++ b/doc/doxygen/html/classArray1D_3_01double_01_4.html @@ -0,0 +1,1139 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array1D< double > Class Template Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Array1D< double > Class Template Reference
+
+
+ +

#include <Array1D.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Array1D ()
 Default constructor, which does not allocate any memory. More...
 
 Array1D (const int &nx)
 Constructor that allocates the memory. More...
 
 Array1D (const int &nx, const double &t)
 Constructor that allocates and initializes the data to a value t. More...
 
Array1Doperator= (const Array1D &obj)
 Assignment operator copies the data structure by value. More...
 
 Array1D (const Array1D &obj)
 Copy constructor. More...
 
 ~Array1D ()
 Destructor that frees up the memory. More...
 
void Clear ()
 Function to clear the memory. More...
 
int XSize () const
 Returns size in the x-direction. More...
 
int Length () const
 Returns length (i.e. size in the x-direction) More...
 
void Resize (const int &nx)
 Resizes the array. More...
 
void Resize (const int &nx, const double &t)
 Resizes the array and sets ALL entries to the specified value. More...
 
void SetValue (const double &t)
 Set all values in the array to the given value. More...
 
void PushBack (const double &t)
 Add element to the end of the vector. More...
 
double * GetArrayPointer ()
 Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
const double * GetConstArrayPointer () const
 Return a const point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
double & operator() (int ix)
 
const double & operator() (int ix) const
 
void insert (Array1D< double > &insarr, int ix)
 Insert a given array to the position ix. More...
 
void insert (const double &insval, int ix)
 Insert a given value to the position ix. More...
 
void erase (int ix)
 Erase the value from the position ix. More...
 
void DumpBinary (FILE *f_out) const
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (FILE *f_in)
 Read contents of the array from a file in binary format. More...
 
double & operator[] (int i)
 
void DumpBinary (char *filename)
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (char *filename)
 
void DumpBinary4py (char *filename)
 
void ReadBinary4py (char *filename, int n)
 
void setArray (vector< double > inarray)
 
void setnpdblArray (double *inarray, int n)
 
void getnpdblArray (double *outarray, int n)
 
vector< double > flatten ()
 
string type ()
 
+ + + +

+Public Attributes

vector< double > data_
 
+ + + +

+Private Attributes

int xsize_
 
+

Constructor & Destructor Documentation

+ +

◆ Array1D() [1/4]

+ +
+
+ + + + + +
+ + + + + + + +
Array1D< double >::Array1D ()
+
+inline
+
+ +

Default constructor, which does not allocate any memory.

+ +
+
+ +

◆ Array1D() [2/4]

+ +
+
+ + + + + +
+ + + + + + + + +
Array1D< double >::Array1D (const int & nx)
+
+inline
+
+ +

Constructor that allocates the memory.

+ +
+
+ +

◆ Array1D() [3/4]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Array1D< double >::Array1D (const int & nx,
const double & t 
)
+
+inline
+
+ +

Constructor that allocates and initializes the data to a value t.

+ +
+
+ +

◆ Array1D() [4/4]

+ +
+
+ + + + + +
+ + + + + + + + +
Array1D< double >::Array1D (const Array1D< double > & obj)
+
+inline
+
+ +

Copy constructor.

+ +
+
+ +

◆ ~Array1D()

+ +
+
+ + + + + +
+ + + + + + + +
Array1D< double >::~Array1D ()
+
+inline
+
+ +

Destructor that frees up the memory.

+ +
+
+

Member Function Documentation

+ +

◆ Clear()

+ +
+
+ + + + + +
+ + + + + + + +
void Array1D< double >::Clear ()
+
+inline
+
+ +

Function to clear the memory.

+ +
+
+ +

◆ DumpBinary() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::DumpBinary (FILE * f_out) const
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::DumpBinary (char * filename)
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary4py()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::DumpBinary4py (char * filename)
+
+inline
+
+ +
+
+ +

◆ erase()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::erase (int ix)
+
+inline
+
+ +

Erase the value from the position ix.

+ +
+
+ +

◆ flatten()

+ +
+
+ + + + + +
+ + + + + + + +
vector<double> Array1D< double >::flatten ()
+
+inline
+
+ +
+
+ +

◆ GetArrayPointer()

+ +
+
+ + + + + +
+ + + + + + + +
double* Array1D< double >::GetArrayPointer ()
+
+inline
+
+ +

Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ GetConstArrayPointer()

+ +
+
+ + + + + +
+ + + + + + + +
const double* Array1D< double >::GetConstArrayPointer () const
+
+inline
+
+ +

Return a const point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ getnpdblArray()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< double >::getnpdblArray (double * outarray,
int n 
)
+
+inline
+
+ +
+
+ +

◆ insert() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< double >::insert (Array1D< double > & insarr,
int ix 
)
+
+inline
+
+ +

Insert a given array to the position ix.

+
Note
ix=0 means insert at the beginning, ix=xsize_ means insert at the end
+ +
+
+ +

◆ insert() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< double >::insert (const double & insval,
int ix 
)
+
+inline
+
+ +

Insert a given value to the position ix.

+
Note
ix=0 means insert at the beginning, ix=xsize_ means insert at the end
+ +
+
+ +

◆ Length()

+ +
+
+ + + + + +
+ + + + + + + +
int Array1D< double >::Length () const
+
+inline
+
+ +

Returns length (i.e. size in the x-direction)

+ +
+
+ +

◆ operator()() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
double& Array1D< double >::operator() (int ix)
+
+inline
+
+ +
+
+ +

◆ operator()() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
const double& Array1D< double >::operator() (int ix) const
+
+inline
+
+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
Array1D& Array1D< double >::operator= (const Array1D< double > & obj)
+
+inline
+
+ +

Assignment operator copies the data structure by value.

+ +
+
+ +

◆ operator[]()

+ +
+
+ + + + + +
+ + + + + + + + +
double& Array1D< double >::operator[] (int i)
+
+inline
+
+ +
+
+ +

◆ PushBack()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::PushBack (const double & t)
+
+inline
+
+ +

Add element to the end of the vector.

+ +
+
+ +

◆ ReadBinary() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::ReadBinary (FILE * f_in)
+
+inline
+
+ +

Read contents of the array from a file in binary format.

+ +
+
+ +

◆ ReadBinary() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::ReadBinary (char * filename)
+
+inline
+
+ +
+
+ +

◆ ReadBinary4py()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< double >::ReadBinary4py (char * filename,
int n 
)
+
+inline
+
+ +
+
+ +

◆ Resize() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::Resize (const int & nx)
+
+inline
+
+ +

Resizes the array.

+ +
+
+ +

◆ Resize() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< double >::Resize (const int & nx,
const double & t 
)
+
+inline
+
+ +

Resizes the array and sets ALL entries to the specified value.

+
Warning
All original data will get lost if this function is used!
+ +
+
+ +

◆ setArray()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::setArray (vector< double > inarray)
+
+inline
+
+ +
+
+ +

◆ setnpdblArray()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< double >::setnpdblArray (double * inarray,
int n 
)
+
+inline
+
+ +
+
+ +

◆ SetValue()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< double >::SetValue (const double & t)
+
+inline
+
+ +

Set all values in the array to the given value.

+ +
+
+ +

◆ type()

+ +
+
+ + + + + +
+ + + + + + + +
string Array1D< double >::type ()
+
+inline
+
+ +
+
+ +

◆ XSize()

+ +
+
+ + + + + +
+ + + + + + + +
int Array1D< double >::XSize () const
+
+inline
+
+ +

Returns size in the x-direction.

+ +
+
+

Member Data Documentation

+ +

◆ data_

+ +
+
+ + + + +
vector<double> Array1D< double >::data_
+
+ +
+
+ +

◆ xsize_

+ +
+
+ + + + + +
+ + + + +
int Array1D< double >::xsize_
+
+private
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classArray1D_3_01int_01_4-members.html b/doc/doxygen/html/classArray1D_3_01int_01_4-members.html new file mode 100644 index 00000000..c49a835f --- /dev/null +++ b/doc/doxygen/html/classArray1D_3_01int_01_4-members.html @@ -0,0 +1,90 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Array1D< int > Member List
+
+
+ +

This is the complete list of members for Array1D< int >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array1D()Array1D< int >inline
Array1D(const int &nx)Array1D< int >inline
Array1D(const int &nx, const int &t)Array1D< int >inline
Array1D(const Array1D &obj)Array1D< int >inline
Clear()Array1D< int >inline
data_Array1D< int >
DumpBinary(FILE *f_out) constArray1D< int >inline
DumpBinary(char *filename)Array1D< int >inline
DumpBinary4py(char *filename)Array1D< int >inline
erase(int ix)Array1D< int >inline
flatten()Array1D< int >inline
GetArrayPointer()Array1D< int >inline
GetConstArrayPointer() constArray1D< int >inline
getnpintArray(long *outarray, int n)Array1D< int >inline
insert(Array1D< int > &insarr, int ix)Array1D< int >inline
insert(const int &insval, int ix)Array1D< int >inline
Length() constArray1D< int >inline
operator()(int ix)Array1D< int >inline
operator()(int ix) constArray1D< int >inline
operator=(const Array1D &obj)Array1D< int >inline
operator[](int i)Array1D< int >inline
PushBack(const int &t)Array1D< int >inline
ReadBinary(FILE *f_in)Array1D< int >inline
ReadBinary(char *filename)Array1D< int >inline
ReadBinary4py(char *filename, int n)Array1D< int >inline
Resize(const int &nx)Array1D< int >inline
Resize(const int &nx, const int &t)Array1D< int >inline
setArray(vector< int > inarray)Array1D< int >inline
setnpintArray(long *inarray, int n)Array1D< int >inline
SetValue(const int &t)Array1D< int >inline
type()Array1D< int >inline
XSize() constArray1D< int >inline
xsize_Array1D< int >private
~Array1D()Array1D< int >inline
+ + + + diff --git a/doc/doxygen/html/classArray1D_3_01int_01_4.html b/doc/doxygen/html/classArray1D_3_01int_01_4.html new file mode 100644 index 00000000..e059bb3e --- /dev/null +++ b/doc/doxygen/html/classArray1D_3_01int_01_4.html @@ -0,0 +1,1139 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array1D< int > Class Template Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Array1D< int > Class Template Reference
+
+
+ +

#include <Array1D.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Array1D ()
 Default constructor, which does not allocate any memory. More...
 
 Array1D (const int &nx)
 Constructor that allocates the memory. More...
 
 Array1D (const int &nx, const int &t)
 Constructor that allocates and initializes the data to a value t. More...
 
Array1Doperator= (const Array1D &obj)
 Assignment operator copies the data structure by value. More...
 
 Array1D (const Array1D &obj)
 Copy constructor. More...
 
 ~Array1D ()
 Destructor that frees up the memory. More...
 
void Clear ()
 Function to clear the memory. More...
 
int XSize () const
 Returns size in the x-direction. More...
 
int Length () const
 Returns length (i.e. size in the x-direction) More...
 
void Resize (const int &nx)
 Resizes the array. More...
 
void Resize (const int &nx, const int &t)
 Resizes the array and sets ALL entries to the specified value. More...
 
void SetValue (const int &t)
 Set all values in the array to the given value. More...
 
void PushBack (const int &t)
 Add element to the end of the vector. More...
 
int * GetArrayPointer ()
 Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
const int * GetConstArrayPointer () const
 Return a const point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
int & operator() (int ix)
 
const int & operator() (int ix) const
 
void insert (Array1D< int > &insarr, int ix)
 Insert a given array to the position ix. More...
 
void insert (const int &insval, int ix)
 Insert a given value to the position ix. More...
 
void erase (int ix)
 Erase the value from the position ix. More...
 
void DumpBinary (FILE *f_out) const
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (FILE *f_in)
 Read contents of the array from a file in binary format. More...
 
int & operator[] (int i)
 
void DumpBinary (char *filename)
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (char *filename)
 
void DumpBinary4py (char *filename)
 
void ReadBinary4py (char *filename, int n)
 
void setArray (vector< int > inarray)
 
void setnpintArray (long *inarray, int n)
 
void getnpintArray (long *outarray, int n)
 
vector< int > flatten ()
 
string type ()
 
+ + + +

+Public Attributes

vector< int > data_
 
+ + + +

+Private Attributes

int xsize_
 
+

Constructor & Destructor Documentation

+ +

◆ Array1D() [1/4]

+ +
+
+ + + + + +
+ + + + + + + +
Array1D< int >::Array1D ()
+
+inline
+
+ +

Default constructor, which does not allocate any memory.

+ +
+
+ +

◆ Array1D() [2/4]

+ +
+
+ + + + + +
+ + + + + + + + +
Array1D< int >::Array1D (const int & nx)
+
+inline
+
+ +

Constructor that allocates the memory.

+ +
+
+ +

◆ Array1D() [3/4]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Array1D< int >::Array1D (const int & nx,
const int & t 
)
+
+inline
+
+ +

Constructor that allocates and initializes the data to a value t.

+ +
+
+ +

◆ Array1D() [4/4]

+ +
+
+ + + + + +
+ + + + + + + + +
Array1D< int >::Array1D (const Array1D< int > & obj)
+
+inline
+
+ +

Copy constructor.

+ +
+
+ +

◆ ~Array1D()

+ +
+
+ + + + + +
+ + + + + + + +
Array1D< int >::~Array1D ()
+
+inline
+
+ +

Destructor that frees up the memory.

+ +
+
+

Member Function Documentation

+ +

◆ Clear()

+ +
+
+ + + + + +
+ + + + + + + +
void Array1D< int >::Clear ()
+
+inline
+
+ +

Function to clear the memory.

+ +
+
+ +

◆ DumpBinary() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::DumpBinary (FILE * f_out) const
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::DumpBinary (char * filename)
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary4py()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::DumpBinary4py (char * filename)
+
+inline
+
+ +
+
+ +

◆ erase()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::erase (int ix)
+
+inline
+
+ +

Erase the value from the position ix.

+ +
+
+ +

◆ flatten()

+ +
+
+ + + + + +
+ + + + + + + +
vector<int> Array1D< int >::flatten ()
+
+inline
+
+ +
+
+ +

◆ GetArrayPointer()

+ +
+
+ + + + + +
+ + + + + + + +
int* Array1D< int >::GetArrayPointer ()
+
+inline
+
+ +

Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ GetConstArrayPointer()

+ +
+
+ + + + + +
+ + + + + + + +
const int* Array1D< int >::GetConstArrayPointer () const
+
+inline
+
+ +

Return a const point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ getnpintArray()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< int >::getnpintArray (long * outarray,
int n 
)
+
+inline
+
+ +
+
+ +

◆ insert() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< int >::insert (Array1D< int > & insarr,
int ix 
)
+
+inline
+
+ +

Insert a given array to the position ix.

+
Note
ix=0 means insert at the beginning, ix=xsize_ means insert at the end
+ +
+
+ +

◆ insert() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< int >::insert (const int & insval,
int ix 
)
+
+inline
+
+ +

Insert a given value to the position ix.

+
Note
ix=0 means insert at the beginning, ix=xsize_ means insert at the end
+ +
+
+ +

◆ Length()

+ +
+
+ + + + + +
+ + + + + + + +
int Array1D< int >::Length () const
+
+inline
+
+ +

Returns length (i.e. size in the x-direction)

+ +
+
+ +

◆ operator()() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
int& Array1D< int >::operator() (int ix)
+
+inline
+
+ +
+
+ +

◆ operator()() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
const int& Array1D< int >::operator() (int ix) const
+
+inline
+
+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
Array1D& Array1D< int >::operator= (const Array1D< int > & obj)
+
+inline
+
+ +

Assignment operator copies the data structure by value.

+ +
+
+ +

◆ operator[]()

+ +
+
+ + + + + +
+ + + + + + + + +
int& Array1D< int >::operator[] (int i)
+
+inline
+
+ +
+
+ +

◆ PushBack()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::PushBack (const int & t)
+
+inline
+
+ +

Add element to the end of the vector.

+ +
+
+ +

◆ ReadBinary() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::ReadBinary (FILE * f_in)
+
+inline
+
+ +

Read contents of the array from a file in binary format.

+ +
+
+ +

◆ ReadBinary() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::ReadBinary (char * filename)
+
+inline
+
+ +
+
+ +

◆ ReadBinary4py()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< int >::ReadBinary4py (char * filename,
int n 
)
+
+inline
+
+ +
+
+ +

◆ Resize() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::Resize (const int & nx)
+
+inline
+
+ +

Resizes the array.

+ +
+
+ +

◆ Resize() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< int >::Resize (const int & nx,
const int & t 
)
+
+inline
+
+ +

Resizes the array and sets ALL entries to the specified value.

+
Warning
All original data will get lost if this function is used!
+ +
+
+ +

◆ setArray()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::setArray (vector< int > inarray)
+
+inline
+
+ +
+
+ +

◆ setnpintArray()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array1D< int >::setnpintArray (long * inarray,
int n 
)
+
+inline
+
+ +
+
+ +

◆ SetValue()

+ +
+
+ + + + + +
+ + + + + + + + +
void Array1D< int >::SetValue (const int & t)
+
+inline
+
+ +

Set all values in the array to the given value.

+ +
+
+ +

◆ type()

+ +
+
+ + + + + +
+ + + + + + + +
string Array1D< int >::type ()
+
+inline
+
+ +
+
+ +

◆ XSize()

+ +
+
+ + + + + +
+ + + + + + + +
int Array1D< int >::XSize () const
+
+inline
+
+ +

Returns size in the x-direction.

+ +
+
+

Member Data Documentation

+ +

◆ data_

+ +
+
+ + + + +
vector<int> Array1D< int >::data_
+
+ +
+
+ +

◆ xsize_

+ +
+
+ + + + + +
+ + + + +
int Array1D< int >::xsize_
+
+private
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classArray2D-members.html b/doc/doxygen/html/classArray2D-members.html new file mode 100644 index 00000000..fe0d79f3 --- /dev/null +++ b/doc/doxygen/html/classArray2D-members.html @@ -0,0 +1,97 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Array2D< T > Member List
+
+
+ +

This is the complete list of members for Array2D< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D()Array2D< T >inline
Array2D(const int &nx, const int &ny)Array2D< T >inline
Array2D(const int &nx, const int &ny, const T &t)Array2D< T >inline
Array2D(const Array2D &obj)Array2D< T >inline
arraycopyArray2D< T >
Clear()Array2D< T >inline
data_Array2D< T >
DumpBinary(FILE *f_out) constArray2D< T >inline
DumpBinary(char *filename)Array2D< T >inline
DumpBinary4py(char *filename)Array2D< T >inline
eraseCol(int iy)Array2D< T >inline
eraseRow(int ix)Array2D< T >inline
flatten()Array2D< T >inline
GetArrayPointer()Array2D< T >inline
GetConstArrayPointer() constArray2D< T >inline
getnpdblArray(double *outarray, int n1, int n2)Array2D< T >inline
getnpintArray(long *outarray, int n1, int n2)Array2D< T >inline
getRow(int row)Array2D< T >inline
insertCol(Array1D< T > &insarr, int iy)Array2D< T >inline
insertCol(Array2D< T > &insarr, int iy)Array2D< T >inline
insertRow(Array1D< T > &insarr, int ix)Array2D< T >inline
insertRow(Array2D< T > &insarr, int ix)Array2D< T >inline
operator()(int ix, int iy)Array2D< T >inline
operator()(int ix, int iy) constArray2D< T >inline
operator[](int ix)Array2D< T >inline
ReadBinary(FILE *f_in)Array2D< T >inline
ReadBinary(char *filename)Array2D< T >inline
ReadBinary4py(char *filename, int n1, int n2)Array2D< T >inline
Resize(const int &nx, const int &ny)Array2D< T >inline
Resize(const int &nx, const int &ny, const T &t)Array2D< T >inline
rowvecArray2D< T >
setArray(vector< T > inarray)Array2D< T >inline
setnpdblArray(double *inarray, int n1, int n2)Array2D< T >inline
setnpintArray(long *inarray, int n1, int n2)Array2D< T >inline
SetValue(const T &t)Array2D< T >inline
type()Array2D< T >inline
XSize() constArray2D< T >inline
xsize_Array2D< T >
YSize() constArray2D< T >inline
ysize_Array2D< T >
~Array2D()Array2D< T >inline
+ + + + diff --git a/doc/doxygen/html/classArray2D.html b/doc/doxygen/html/classArray2D.html new file mode 100644 index 00000000..44f0a07c --- /dev/null +++ b/doc/doxygen/html/classArray2D.html @@ -0,0 +1,1502 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array2D< T > Class Template Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Array2D< T > Class Template Reference
+
+
+ +

Stores data of any type T in a 2D array. + More...

+ +

#include <Array2D.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Array2D ()
 Default constructor, which does not allocate any memory. More...
 
 Array2D (const int &nx, const int &ny)
 Constructor that allocates the memory. More...
 
 Array2D (const int &nx, const int &ny, const T &t)
 Constructor that allocates and initializes the data to a constant t. More...
 
 Array2D (const Array2D &obj)
 Copy constructor. More...
 
 ~Array2D ()
 Destructor that frees up the memory. More...
 
void Clear ()
 Function to clear the memory. More...
 
int XSize () const
 Returns size in the x-direction. More...
 
int YSize () const
 Returns size in the y-direction. More...
 
void Resize (const int &nx, const int &ny)
 Resizes the array. More...
 
void Resize (const int &nx, const int &ny, const T &t)
 Resizes the array and sets ALL entries to the specified value. More...
 
void SetValue (const T &t)
 Set all values in the array to the given value. More...
 
T * GetArrayPointer ()
 Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
const T * GetConstArrayPointer () const
 Return a cont point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
T & operator() (int ix, int iy)
 C-like () operator to access values in the 2D data array. More...
 
const T & operator() (int ix, int iy) const
 
void insertRow (Array1D< T > &insarr, int ix)
 Insert array insarr as a row into position ix. More...
 
void insertRow (Array2D< T > &insarr, int ix)
 Insert a 2d-array insarr into a row position ix. More...
 
void eraseRow (int ix)
 Erase the row ix. More...
 
void insertCol (Array1D< T > &insarr, int iy)
 
void insertCol (Array2D< T > &insarr, int iy)
 Insert a 2d-array insarr into a column position iy. More...
 
void eraseCol (int iy)
 Erase the column iy. More...
 
void DumpBinary (FILE *f_out) const
 Dump contents of the array to a file in binary format. More...
 
void ReadBinary (FILE *f_in)
 Read contents of the array from a file in binary format. More...
 
Array1D< T > & operator[] (int ix)
 
void getRow (int row)
 
void DumpBinary (char *filename)
 
void ReadBinary (char *filename)
 
void DumpBinary4py (char *filename)
 
void ReadBinary4py (char *filename, int n1, int n2)
 
void setArray (vector< T > inarray)
 
void setnpdblArray (double *inarray, int n1, int n2)
 
void getnpdblArray (double *outarray, int n1, int n2)
 
void setnpintArray (long *inarray, int n1, int n2)
 
void getnpintArray (long *outarray, int n1, int n2)
 
vector< T > flatten ()
 
string type ()
 
+ + + + + + + + + + + +

+Public Attributes

int xsize_
 
int ysize_
 
vector< T > data_
 
Array1D< T > arraycopy
 
Array1D< T > rowvec
 
+

Detailed Description

+

template<typename T>
+class Array2D< T >

+ +

Stores data of any type T in a 2D array.

+

This class also provides a Fortran-like access operator () as well as a function to access the data in the array through a pointer that can be passed to F77 or C routines.

Author
Bert Debusschere bjdeb.nosp@m.us@s.nosp@m.andia.nosp@m..gov
+
Date
Jan 2005
+
Note
Inspired by Helgi Adalsteinsson's Array class implementation
+
Todo:
Define copy constructor
+

Constructor & Destructor Documentation

+ +

◆ Array2D() [1/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
Array2D< T >::Array2D ()
+
+inline
+
+ +

Default constructor, which does not allocate any memory.

+ +
+
+ +

◆ Array2D() [2/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Array2D< T >::Array2D (const int & nx,
const int & ny 
)
+
+inline
+
+ +

Constructor that allocates the memory.

+ +
+
+ +

◆ Array2D() [3/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Array2D< T >::Array2D (const int & nx,
const int & ny,
const T & t 
)
+
+inline
+
+ +

Constructor that allocates and initializes the data to a constant t.

+ +
+
+ +

◆ Array2D() [4/4]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
Array2D< T >::Array2D (const Array2D< T > & obj)
+
+inline
+
+ +

Copy constructor.

+ +
+
+ +

◆ ~Array2D()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
Array2D< T >::~Array2D ()
+
+inline
+
+ +

Destructor that frees up the memory.

+ +
+
+

Member Function Documentation

+ +

◆ Clear()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
void Array2D< T >::Clear ()
+
+inline
+
+ +

Function to clear the memory.

+ +
+
+ +

◆ DumpBinary() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::DumpBinary (FILE * f_out) const
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpBinary() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::DumpBinary (char * filename)
+
+inline
+
+ +
+
+ +

◆ DumpBinary4py()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::DumpBinary4py (char * filename)
+
+inline
+
+ +
+
+ +

◆ eraseCol()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::eraseCol (int iy)
+
+inline
+
+ +

Erase the column iy.

+ +
+
+ +

◆ eraseRow()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::eraseRow (int ix)
+
+inline
+
+ +

Erase the row ix.

+ +
+
+ +

◆ flatten()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
vector<T> Array2D< T >::flatten ()
+
+inline
+
+ +
+
+ +

◆ GetArrayPointer()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
T* Array2D< T >::GetArrayPointer ()
+
+inline
+
+ +

Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ GetConstArrayPointer()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
const T* Array2D< T >::GetConstArrayPointer () const
+
+inline
+
+ +

Return a cont point to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ getnpdblArray()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array2D< T >::getnpdblArray (double * outarray,
int n1,
int n2 
)
+
+inline
+
+ +
+
+ +

◆ getnpintArray()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array2D< T >::getnpintArray (long * outarray,
int n1,
int n2 
)
+
+inline
+
+ +
+
+ +

◆ getRow()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::getRow (int row)
+
+inline
+
+ +
+
+ +

◆ insertCol() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array2D< T >::insertCol (Array1D< T > & insarr,
int iy 
)
+
+inline
+
+ +
+
+ +

◆ insertCol() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array2D< T >::insertCol (Array2D< T > & insarr,
int iy 
)
+
+inline
+
+ +

Insert a 2d-array insarr into a column position iy.

+ +
+
+ +

◆ insertRow() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array2D< T >::insertRow (Array1D< T > & insarr,
int ix 
)
+
+inline
+
+ +

Insert array insarr as a row into position ix.

+ +
+
+ +

◆ insertRow() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array2D< T >::insertRow (Array2D< T > & insarr,
int ix 
)
+
+inline
+
+ +

Insert a 2d-array insarr into a row position ix.

+ +
+
+ +

◆ operator()() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
T& Array2D< T >::operator() (int ix,
int iy 
)
+
+inline
+
+ +

C-like () operator to access values in the 2D data array.

+ +
+
+ +

◆ operator()() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
const T& Array2D< T >::operator() (int ix,
int iy 
) const
+
+inline
+
+ +
+
+ +

◆ operator[]()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
Array1D<T>& Array2D< T >::operator[] (int ix)
+
+inline
+
+ +
+
+ +

◆ ReadBinary() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::ReadBinary (FILE * f_in)
+
+inline
+
+ +

Read contents of the array from a file in binary format.

+ +
+
+ +

◆ ReadBinary() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::ReadBinary (char * filename)
+
+inline
+
+ +
+
+ +

◆ ReadBinary4py()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array2D< T >::ReadBinary4py (char * filename,
int n1,
int n2 
)
+
+inline
+
+ +
+
+ +

◆ Resize() [1/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Array2D< T >::Resize (const int & nx,
const int & ny 
)
+
+inline
+
+ +

Resizes the array.

+
Warning
In its current implementation, most of the original data
+ +
+
+ +

◆ Resize() [2/2]

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array2D< T >::Resize (const int & nx,
const int & ny,
const T & t 
)
+
+inline
+
+ +

Resizes the array and sets ALL entries to the specified value.

+
Warning
All original data will get lost if this function is used!
+ +
+
+ +

◆ setArray()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::setArray (vector< T > inarray)
+
+inline
+
+ +
+
+ +

◆ setnpdblArray()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array2D< T >::setnpdblArray (double * inarray,
int n1,
int n2 
)
+
+inline
+
+ +
+
+ +

◆ setnpintArray()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array2D< T >::setnpintArray (long * inarray,
int n1,
int n2 
)
+
+inline
+
+ +
+
+ +

◆ SetValue()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + + +
void Array2D< T >::SetValue (const T & t)
+
+inline
+
+ +

Set all values in the array to the given value.

+ +
+
+ +

◆ type()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
string Array2D< T >::type ()
+
+inline
+
+ +
+
+ +

◆ XSize()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
int Array2D< T >::XSize () const
+
+inline
+
+ +

Returns size in the x-direction.

+ +
+
+ +

◆ YSize()

+ +
+
+
+template<typename T>
+ + + + + +
+ + + + + + + +
int Array2D< T >::YSize () const
+
+inline
+
+ +

Returns size in the y-direction.

+ +
+
+

Member Data Documentation

+ +

◆ arraycopy

+ +
+
+
+template<typename T>
+ + + + +
Array1D<T> Array2D< T >::arraycopy
+
+ +
+
+ +

◆ data_

+ +
+
+
+template<typename T>
+ + + + +
vector<T> Array2D< T >::data_
+
+ +
+
+ +

◆ rowvec

+ +
+
+
+template<typename T>
+ + + + +
Array1D<T> Array2D< T >::rowvec
+
+ +
+
+ +

◆ xsize_

+ +
+
+
+template<typename T>
+ + + + +
int Array2D< T >::xsize_
+
+ +
+
+ +

◆ ysize_

+ +
+
+
+template<typename T>
+ + + + +
int Array2D< T >::ysize_
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classArray3D-members.html b/doc/doxygen/html/classArray3D-members.html new file mode 100644 index 00000000..54262338 --- /dev/null +++ b/doc/doxygen/html/classArray3D-members.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Array3D< T > Member List
+
+
+ +

This is the complete list of members for Array3D< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Array3D()Array3D< T >inline
Array3D(const size_t &nx, const size_t &ny, const size_t &nz)Array3D< T >inline
Array3D(const size_t &nx, const size_t &ny, const size_t &nz, const T &t)Array3D< T >inline
Array3D(const Array3D &obj)Array3D< T >inlineprivate
Clear()Array3D< T >inline
data_Array3D< T >private
DumpBinary(FILE *f_out) constArray3D< T >inline
DumpText(std::ofstream &f_out) constArray3D< T >inline
GetArrayPointer()Array3D< T >inline
GetConstArrayPointer() constArray3D< T >inline
operator()(size_t ix, size_t iy, size_t iz)Array3D< T >inline
operator()(size_t ix, size_t iy, size_t iz) constArray3D< T >inline
ReadBinary(std::ifstream &f_in)Array3D< T >inline
ReadText(FILE *f_in)Array3D< T >inline
Resize(const size_t &nx, const size_t &ny, const size_t &nz)Array3D< T >inline
Resize(const size_t &nx, const size_t &ny, const size_t &nz, const T &t)Array3D< T >inline
SetValue(const T &t)Array3D< T >inline
XSize() constArray3D< T >inline
xsize_Array3D< T >private
YSize() constArray3D< T >inline
ysize_Array3D< T >private
ZSize() constArray3D< T >inline
zsize_Array3D< T >private
~Array3D()Array3D< T >inline
+ + + + diff --git a/doc/doxygen/html/classArray3D.html b/doc/doxygen/html/classArray3D.html new file mode 100644 index 00000000..3e0271b0 --- /dev/null +++ b/doc/doxygen/html/classArray3D.html @@ -0,0 +1,973 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Array3D< T > Class Template Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Array3D< T > Class Template Reference
+
+
+ +

Stores data of any type T in a 3D array. + More...

+ +

#include <Array3D.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Array3D ()
 Default constructor, which does not allocate any memory. More...
 
 Array3D (const size_t &nx, const size_t &ny, const size_t &nz)
 Constructor that allocates the memory. More...
 
 Array3D (const size_t &nx, const size_t &ny, const size_t &nz, const T &t)
 Constructor that allocates and initializes the data. More...
 
 ~Array3D ()
 Destructor that frees up the memory. More...
 
void Clear ()
 Function to clear the memory. More...
 
size_t XSize () const
 Returns size in the x-direction. More...
 
size_t YSize () const
 Returns size in the y-direction. More...
 
size_t ZSize () const
 Returns size in the z-direction. More...
 
void Resize (const size_t &nx, const size_t &ny, const size_t &nz)
 Resizes the array. More...
 
void Resize (const size_t &nx, const size_t &ny, const size_t &nz, const T &t)
 Resizes the array and sets ALL entries to the specified value. More...
 
void SetValue (const T &t)
 Set all values in the array to the given value. More...
 
T * GetArrayPointer ()
 Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
const T * GetConstArrayPointer () const
 Return a const pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program). More...
 
T & operator() (size_t ix, size_t iy, size_t iz)
 Fortran-like () operator to access values in the 3D data array. More...
 
const T & operator() (size_t ix, size_t iy, size_t iz) const
 Fortran-like () const operator to access values in the 3D data array. More...
 
void DumpBinary (FILE *f_out) const
 Dump contents of the array to a file in binary format. More...
 
void DumpText (std::ofstream &f_out) const
 Dump contents of the array to a file in text format Added by Maher Salloum When post-processing (in matlab for example), one has to transpose each 2-D sub-matrix imported from the text file. More...
 
void ReadText (FILE *f_in)
 Read contents of the array from a file in binary format. More...
 
void ReadBinary (std::ifstream &f_in)
 Read contents of the array from a file in text format Added by Maher Salloum. More...
 
+ + + + +

+Private Member Functions

 Array3D (const Array3D &obj)
 Copy constructor, which is made private so it would not be used inadvertently (until we define a proper copy constructor) More...
 
+ + + + + + + + + + + + + +

+Private Attributes

size_t xsize_
 Number of elements in the x-dimension. More...
 
size_t ysize_
 Number of elements in the y-dimension. More...
 
size_t zsize_
 Number of elements in the z-dimension. More...
 
vector< T > data_
 Data in the array with size = xsize_ * ysize_ * zsize_. More...
 
+

Detailed Description

+

template<typename T>
+class Array3D< T >

+ +

Stores data of any type T in a 3D array.

+

This class also provides a Fortran-like access operator () as well as a function to access the data in the array through a pointer that can be passed to F77 or C routines.

Author
Bert Debusschere bjdeb.nosp@m.us@s.nosp@m.andia.nosp@m..gov
+
Date
Jan 2005
+
Note
Inspired by Helgi Adalsteinsson's Array class implementation
+
Todo:

Define copy constructor

+

Several functions, e.g. insert/erase columns/rows, available in Array1D and Array2D, are missing.

+
+

Constructor & Destructor Documentation

+ +

◆ Array3D() [1/4]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
Array3D< T >::Array3D ()
+
+inline
+
+ +

Default constructor, which does not allocate any memory.

+ +
+
+ +

◆ Array3D() [2/4]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
Array3D< T >::Array3D (const size_t & nx,
const size_t & ny,
const size_t & nz 
)
+
+inline
+
+ +

Constructor that allocates the memory.

+ +
+
+ +

◆ Array3D() [3/4]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array3D< T >::Array3D (const size_t & nx,
const size_t & ny,
const size_t & nz,
const T & t 
)
+
+inline
+
+ +

Constructor that allocates and initializes the data.

+ +
+
+ +

◆ ~Array3D()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
Array3D< T >::~Array3D ()
+
+inline
+
+ +

Destructor that frees up the memory.

+ +
+
+ +

◆ Array3D() [4/4]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + +
Array3D< T >::Array3D (const Array3D< T > & obj)
+
+inlineprivate
+
+ +

Copy constructor, which is made private so it would not be used inadvertently (until we define a proper copy constructor)

+ +
+
+

Member Function Documentation

+ +

◆ Clear()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
void Array3D< T >::Clear ()
+
+inline
+
+ +

Function to clear the memory.

+ +
+
+ +

◆ DumpBinary()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + +
void Array3D< T >::DumpBinary (FILE * f_out) const
+
+inline
+
+ +

Dump contents of the array to a file in binary format.

+ +
+
+ +

◆ DumpText()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + +
void Array3D< T >::DumpText (std::ofstream & f_out) const
+
+inline
+
+ +

Dump contents of the array to a file in text format Added by Maher Salloum When post-processing (in matlab for example), one has to transpose each 2-D sub-matrix imported from the text file.

+ +
+
+ +

◆ GetArrayPointer()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
T* Array3D< T >::GetArrayPointer ()
+
+inline
+
+ +

Return a pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ GetConstArrayPointer()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
const T* Array3D< T >::GetConstArrayPointer () const
+
+inline
+
+ +

Return a const pointer to the first element of the data in the vector so we can use it access the data in array format (e.g. for passing it to a Fortran program).

+ +
+
+ +

◆ operator()() [1/2]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
T& Array3D< T >::operator() (size_t ix,
size_t iy,
size_t iz 
)
+
+inline
+
+ +

Fortran-like () operator to access values in the 3D data array.

+

If "my_data" is an object of type Array3D, then its array values can be accessed as my_data(ix,iy,iz), where ix, iy, iz are the indices in the x, y, and z dimensions respectively.

+ +
+
+ +

◆ operator()() [2/2]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
const T& Array3D< T >::operator() (size_t ix,
size_t iy,
size_t iz 
) const
+
+inline
+
+ +

Fortran-like () const operator to access values in the 3D data array.

+

If "my_data" is an object of type Array3D, then its array values can be accessed as my_data(ix,iy,iz), where ix, iy, iz are the indices in the x, y, and z dimensions respectively.

+ +
+
+ +

◆ ReadBinary()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + +
void Array3D< T >::ReadBinary (std::ifstream & f_in)
+
+inline
+
+ +

Read contents of the array from a file in text format Added by Maher Salloum.

+ +
+
+ +

◆ ReadText()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + +
void Array3D< T >::ReadText (FILE * f_in)
+
+inline
+
+ +

Read contents of the array from a file in binary format.

+ +
+
+ +

◆ Resize() [1/2]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Array3D< T >::Resize (const size_t & nx,
const size_t & ny,
const size_t & nz 
)
+
+inline
+
+ +

Resizes the array.

+
Warning
In its current implementation, most of the original data will get lost if the xsize or ysize changes as this changes the indexing for all entries.
+
Todo:
Write a better implementation that preserves the original data by copying it to a temporary array and putting the elements back where they were before. This would bring this resize() command more closely in line with vector::resize() function in the original vector class.
+ +
+
+ +

◆ Resize() [2/2]

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Array3D< T >::Resize (const size_t & nx,
const size_t & ny,
const size_t & nz,
const T & t 
)
+
+inline
+
+ +

Resizes the array and sets ALL entries to the specified value.

+
Warning
All original data will get lost if this function is used!
+
Todo:
Write an implementation that is more closely follows the resize command in the vector class, which keeps the original elements and only initializes the new elements.
+ +
+
+ +

◆ SetValue()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + + +
void Array3D< T >::SetValue (const T & t)
+
+inline
+
+ +

Set all values in the array to the given value.

+ +
+
+ +

◆ XSize()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
size_t Array3D< T >::XSize () const
+
+inline
+
+ +

Returns size in the x-direction.

+ +
+
+ +

◆ YSize()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
size_t Array3D< T >::YSize () const
+
+inline
+
+ +

Returns size in the y-direction.

+ +
+
+ +

◆ ZSize()

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + + + + +
size_t Array3D< T >::ZSize () const
+
+inline
+
+ +

Returns size in the z-direction.

+ +
+
+

Member Data Documentation

+ +

◆ data_

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + +
vector<T> Array3D< T >::data_
+
+private
+
+ +

Data in the array with size = xsize_ * ysize_ * zsize_.

+

The data is stored with the fastest running index in the x-dimension then the y-dimension and the slowest one in the z-dimension. The indices in every dimension run from 0 to their respective "size-1"

+ +
+
+ +

◆ xsize_

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + +
size_t Array3D< T >::xsize_
+
+private
+
+ +

Number of elements in the x-dimension.

+ +
+
+ +

◆ ysize_

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + +
size_t Array3D< T >::ysize_
+
+private
+
+ +

Number of elements in the y-dimension.

+ +
+
+ +

◆ zsize_

+ +
+
+
+template<typename T >
+ + + + + +
+ + + + +
size_t Array3D< T >::zsize_
+
+private
+
+ +

Number of elements in the z-dimension.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classDFI-members.html b/doc/doxygen/html/classDFI-members.html new file mode 100644 index 00000000..08d967bc --- /dev/null +++ b/doc/doxygen/html/classDFI-members.html @@ -0,0 +1,69 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
DFI Member List
+
+
+ +

This is the complete list of members for DFI, including all inherited members.

+ + + + + + + + + + + + + + +
DFI(DFIInner &)DFI
dfi_inner_DFI
eval(Array1D< double > &)DFIvirtual
getMLE(Array1D< double > &xstart)DFI
nBetaDFI
nCallsDFI
runChain(int nCalls, Array1D< double > gammas, Array1D< double > start, int seed, int node)DFI
sdimDFI
sigma_DFI
z_DFI
zdimDFI
~DFI()DFIinline
~LikelihoodBase()LikelihoodBaseinlinevirtual
+ + + + diff --git a/doc/doxygen/html/classDFI.html b/doc/doxygen/html/classDFI.html new file mode 100644 index 00000000..60f76cfe --- /dev/null +++ b/doc/doxygen/html/classDFI.html @@ -0,0 +1,342 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: DFI Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

#include <dfi.h>

+
+Inheritance diagram for DFI:
+
+
+ + +LikelihoodBase + +
+ + + + + + + + + + + + + + + +

+Public Member Functions

 DFI (DFIInner &)
 
 ~DFI ()
 
double eval (Array1D< double > &)
 
void runChain (int nCalls, Array1D< double > gammas, Array1D< double > start, int seed, int node)
 
void getMLE (Array1D< double > &xstart)
 
- Public Member Functions inherited from LikelihoodBase
virtual ~LikelihoodBase ()
 
+ + + + + + + + + + + + + + + +

+Public Attributes

int zdim
 
int sdim
 
int nBeta
 
DFIInnerdfi_inner_
 
int nCalls
 
Array1D< double > z_
 
Array1D< double > sigma_
 
+

Constructor & Destructor Documentation

+ +

◆ DFI()

+ +
+
+ + + + + + + + +
DFI::DFI (DFIInnerdfi_inner)
+
+ +
+
+ +

◆ ~DFI()

+ +
+
+ + + + + +
+ + + + + + + +
DFI::~DFI ()
+
+inline
+
+ +
+
+

Member Function Documentation

+ +

◆ eval()

+ +
+
+ + + + + +
+ + + + + + + + +
double DFI::eval (Array1D< double > & zs)
+
+virtual
+
+ +

Reimplemented from LikelihoodBase.

+ +
+
+ +

◆ getMLE()

+ +
+
+ + + + + + + + +
void DFI::getMLE (Array1D< double > & xstart)
+
+ +
+
+ +

◆ runChain()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void DFI::runChain (int nCalls,
Array1D< double > gammas,
Array1D< double > start,
int seed,
int node 
)
+
+ +
+
+

Member Data Documentation

+ +

◆ dfi_inner_

+ +
+
+ + + + +
DFIInner* DFI::dfi_inner_
+
+ +
+
+ +

◆ nBeta

+ +
+
+ + + + +
int DFI::nBeta
+
+ +
+
+ +

◆ nCalls

+ +
+
+ + + + +
int DFI::nCalls
+
+ +
+
+ +

◆ sdim

+ +
+
+ + + + +
int DFI::sdim
+
+ +
+
+ +

◆ sigma_

+ +
+
+ + + + +
Array1D<double> DFI::sigma_
+
+ +
+
+ +

◆ z_

+ +
+
+ + + + +
Array1D<double> DFI::z_
+
+ +
+
+ +

◆ zdim

+ +
+
+ + + + +
int DFI::zdim
+
+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classDFI.png b/doc/doxygen/html/classDFI.png new file mode 100644 index 00000000..97c7e780 Binary files /dev/null and b/doc/doxygen/html/classDFI.png differ diff --git a/doc/doxygen/html/classDFIInner-members.html b/doc/doxygen/html/classDFIInner-members.html new file mode 100644 index 00000000..5e0eb898 --- /dev/null +++ b/doc/doxygen/html/classDFIInner-members.html @@ -0,0 +1,79 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
DFIInner Member List
+
+ + + + + diff --git a/doc/doxygen/html/classDFIInner.html b/doc/doxygen/html/classDFIInner.html new file mode 100644 index 00000000..6645f404 --- /dev/null +++ b/doc/doxygen/html/classDFIInner.html @@ -0,0 +1,483 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: DFIInner Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
DFIInner Class Reference
+
+
+ +

#include <dfi.h>

+
+Inheritance diagram for DFIInner:
+
+
+ + +LikelihoodBase + +
+ + + + + + + + + + + + + + + + + +

+Public Member Functions

 DFIInner (DFISetupBase &d)
 
 DFIInner ()
 
 ~DFIInner ()
 
double eval (Array1D< double > &)
 
void getSamples ()
 
double S ()
 
- Public Member Functions inherited from LikelihoodBase
virtual ~LikelihoodBase ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

int ndim
 
int nBurn
 
int nCalls
 
Array1D< double > beta0_
 
Array1D< double > gammas_
 
Array1D< MCMC::chainstatesamples_
 
DFISetupBased_
 
Array1D< double > z_
 
Array1D< double > sigma_
 
Array1D< double > means_
 
Array1D< double > stds_
 
Array1D< double > quants
 
Array1D< double > means0
 
Array1D< double > stds0
 
double delta1
 
double delta2
 
+

Constructor & Destructor Documentation

+ +

◆ DFIInner() [1/2]

+ +
+
+ + + + + + + + +
DFIInner::DFIInner (DFISetupBased)
+
+ +
+
+ +

◆ DFIInner() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
DFIInner::DFIInner ()
+
+inline
+
+ +
+
+ +

◆ ~DFIInner()

+ +
+
+ + + + + +
+ + + + + + + +
DFIInner::~DFIInner ()
+
+inline
+
+ +
+
+

Member Function Documentation

+ +

◆ eval()

+ +
+
+ + + + + +
+ + + + + + + + +
double DFIInner::eval (Array1D< double > & beta)
+
+virtual
+
+ +

Reimplemented from LikelihoodBase.

+ +
+
+ +

◆ getSamples()

+ +
+
+ + + + + + + +
void DFIInner::getSamples ()
+
+ +
+
+ +

◆ S()

+ +
+
+ + + + + + + +
double DFIInner::S ()
+
+ +
+
+

Member Data Documentation

+ +

◆ beta0_

+ +
+
+ + + + +
Array1D<double> DFIInner::beta0_
+
+ +
+
+ +

◆ d_

+ +
+
+ + + + +
DFISetupBase* DFIInner::d_
+
+ +
+
+ +

◆ delta1

+ +
+
+ + + + +
double DFIInner::delta1
+
+ +
+
+ +

◆ delta2

+ +
+
+ + + + +
double DFIInner::delta2
+
+ +
+
+ +

◆ gammas_

+ +
+
+ + + + +
Array1D<double> DFIInner::gammas_
+
+ +
+
+ +

◆ means0

+ +
+
+ + + + +
Array1D<double> DFIInner::means0
+
+ +
+
+ +

◆ means_

+ +
+
+ + + + +
Array1D<double> DFIInner::means_
+
+ +
+
+ +

◆ nBurn

+ +
+
+ + + + +
int DFIInner::nBurn
+
+ +
+
+ +

◆ nCalls

+ +
+
+ + + + +
int DFIInner::nCalls
+
+ +
+
+ +

◆ ndim

+ +
+
+ + + + +
int DFIInner::ndim
+
+ +
+
+ +

◆ quants

+ +
+
+ + + + +
Array1D<double> DFIInner::quants
+
+ +
+
+ +

◆ samples_

+ +
+
+ + + + +
Array1D<MCMC::chainstate> DFIInner::samples_
+
+ +
+
+ +

◆ sigma_

+ +
+
+ + + + +
Array1D<double> DFIInner::sigma_
+
+ +
+
+ +

◆ stds0

+ +
+
+ + + + +
Array1D<double> DFIInner::stds0
+
+ +
+
+ +

◆ stds_

+ +
+
+ + + + +
Array1D<double> DFIInner::stds_
+
+ +
+
+ +

◆ z_

+ +
+
+ + + + +
Array1D<double> DFIInner::z_
+
+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classDFIInner.png b/doc/doxygen/html/classDFIInner.png new file mode 100644 index 00000000..edb51eac Binary files /dev/null and b/doc/doxygen/html/classDFIInner.png differ diff --git a/doc/doxygen/html/classDFISetup-members.html b/doc/doxygen/html/classDFISetup-members.html new file mode 100644 index 00000000..9a3ab1d2 --- /dev/null +++ b/doc/doxygen/html/classDFISetup-members.html @@ -0,0 +1,61 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
DFISetup Member List
+
+
+ +

This is the complete list of members for DFISetup, including all inherited members.

+ + + + + + +
DFISetup()DFISetupinline
f(Array1D< double > &, Array1D< double > &, Array1D< double > &)DFISetupvirtual
fun(double x)DFISetupinline
S(Array1D< MCMC::chainstate > inner_samples)DFISetupvirtual
~DFISetup()DFISetupinline
+ + + + diff --git a/doc/doxygen/html/classDFISetup.html b/doc/doxygen/html/classDFISetup.html new file mode 100644 index 00000000..8f1734e9 --- /dev/null +++ b/doc/doxygen/html/classDFISetup.html @@ -0,0 +1,232 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: DFISetup Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
DFISetup Class Reference
+
+
+
+Inheritance diagram for DFISetup:
+
+
+ + +DFISetupBase + +
+ + + + + + + + + + + + +

+Public Member Functions

 DFISetup ()
 
 ~DFISetup ()
 
double f (Array1D< double > &, Array1D< double > &, Array1D< double > &)
 
double S (Array1D< MCMC::chainstate > inner_samples)
 
double fun (double x)
 
+

Constructor & Destructor Documentation

+ +

◆ DFISetup()

+ +
+
+ + + + + +
+ + + + + + + +
DFISetup::DFISetup ()
+
+inline
+
+ +
+
+ +

◆ ~DFISetup()

+ +
+
+ + + + + +
+ + + + + + + +
DFISetup::~DFISetup ()
+
+inline
+
+ +
+
+

Member Function Documentation

+ +

◆ f()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
double DFISetup::f (Array1D< double > & beta,
Array1D< double > & z,
Array1D< double > & sigma 
)
+
+virtual
+
+ +

Reimplemented from DFISetupBase.

+ +
+
+ +

◆ fun()

+ +
+
+ + + + + +
+ + + + + + + + +
double DFISetup::fun (double x)
+
+inline
+
+ +
+
+ +

◆ S()

+ +
+
+ + + + + +
+ + + + + + + + +
double DFISetup::S (Array1D< MCMC::chainstateinner_samples)
+
+virtual
+
+ +

Reimplemented from DFISetupBase.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classDFISetup.png b/doc/doxygen/html/classDFISetup.png new file mode 100644 index 00000000..e8198be6 Binary files /dev/null and b/doc/doxygen/html/classDFISetup.png differ diff --git a/doc/doxygen/html/classDFISetupBase-members.html b/doc/doxygen/html/classDFISetupBase-members.html new file mode 100644 index 00000000..9ce78db2 --- /dev/null +++ b/doc/doxygen/html/classDFISetupBase-members.html @@ -0,0 +1,58 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
DFISetupBase Member List
+
+
+ +

This is the complete list of members for DFISetupBase, including all inherited members.

+ + + +
f(Array1D< double > &, Array1D< double > &, Array1D< double > &)DFISetupBaseinlinevirtual
S(Array1D< MCMC::chainstate > inner_samples)DFISetupBaseinlinevirtual
+ + + + diff --git a/doc/doxygen/html/classDFISetupBase.html b/doc/doxygen/html/classDFISetupBase.html new file mode 100644 index 00000000..8d04c1d7 --- /dev/null +++ b/doc/doxygen/html/classDFISetupBase.html @@ -0,0 +1,151 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: DFISetupBase Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
DFISetupBase Class Reference
+
+
+ +

#include <dfi.h>

+
+Inheritance diagram for DFISetupBase:
+
+
+ + +DFISetup + +
+ + + + + + +

+Public Member Functions

virtual double f (Array1D< double > &, Array1D< double > &, Array1D< double > &)
 
virtual double S (Array1D< MCMC::chainstate > inner_samples)
 
+

Member Function Documentation

+ +

◆ f()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
virtual double DFISetupBase::f (Array1D< double > & ,
Array1D< double > & ,
Array1D< double > &  
)
+
+inlinevirtual
+
+ +

Reimplemented in DFISetup.

+ +
+
+ +

◆ S()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual double DFISetupBase::S (Array1D< MCMC::chainstateinner_samples)
+
+inlinevirtual
+
+ +

Reimplemented in DFISetup.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classDFISetupBase.png b/doc/doxygen/html/classDFISetupBase.png new file mode 100644 index 00000000..2ac9a08e Binary files /dev/null and b/doc/doxygen/html/classDFISetupBase.png differ diff --git a/doc/doxygen/html/classGproc-members.html b/doc/doxygen/html/classGproc-members.html new file mode 100644 index 00000000..ae5ecb7b --- /dev/null +++ b/doc/doxygen/html/classGproc-members.html @@ -0,0 +1,113 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Gproc Member List
+
+
+ +

This is the complete list of members for Gproc, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A_Gprocprivate
Ainv_Gprocprivate
Ainvd_Gprocprivate
AinvH_Gprocprivate
AinvyHbhat_Gprocprivate
al_Gprocprivate
be_Gprocprivate
bhat_Gprocprivate
BuildGP()Gproc
BuildGP_inv()Gproc
computeDataCov_(Array2D< double > &xdata, Array1D< double > &param, Array2D< double > &A)Gprocprivate
cov_Gprocprivate
covariance(Array1D< double > &x1, Array1D< double > &x2, Array1D< double > &param)Gprocprivate
covType_Gprocprivate
dataVar_Gprocprivate
EvalGP(Array2D< double > &xgrid, string msc, Array1D< double > &mst)Gproc
EvalGP_inv(Array2D< double > &xgrid, string msc, Array1D< double > &mst)Gproc
findBestCorrParam()Gproc
getA(Array2D< double > &acor)Gprocinline
getAl() constGprocinline
getBe() constGprocinline
getCov(Array2D< double > &cov)Gprocinline
getNdim() constGprocinline
getNPC() constGprocinline
getNpt() constGprocinline
getParam(Array1D< double > &param)Gprocinline
getSig2hat() constGprocinline
getSttPars(Array1D< double > &sttmat)Gproc
getVar(Array1D< double > &var)Gprocinline
getVst(Array2D< double > &vst)Gprocinline
getXYCov(Array2D< double > &xgrid, Array2D< double > &xycov)Gproc
Gproc(const string covtype, PCSet *PCModel, Array1D< double > &param)Gproc
H_Gprocprivate
Hbhat_Gprocprivate
Ht_Gprocprivate
HtAinvd_Gprocprivate
HtAinvH_Gprocprivate
mst_Gprocprivate
ndim_Gprocprivate
npc_Gprocprivate
npt_Gprocprivate
param_Gprocprivate
PCModel_Gprocprivate
setCorrParam(Array1D< double > param)Gprocinline
SetupData(Array2D< double > &xdata, Array1D< double > &ydata, Array1D< double > &datavar)Gproc
SetupPrior()Gproc
sig2hat_Gprocprivate
var_Gprocprivate
Vinv_Gprocprivate
Vinvz_Gprocprivate
Vst_Gprocprivate
Vstinv_Gprocprivate
xdata_Gprocprivate
ydata_Gprocprivate
yHbhat_Gprocprivate
z_Gprocprivate
~Gproc()Gprocinline
+ + + + diff --git a/doc/doxygen/html/classGproc.html b/doc/doxygen/html/classGproc.html new file mode 100644 index 00000000..437f175d --- /dev/null +++ b/doc/doxygen/html/classGproc.html @@ -0,0 +1,1744 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Gproc Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Class for Gaussian processes. + More...

+ +

#include <gproc.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Gproc (const string covtype, PCSet *PCModel, Array1D< double > &param)
 Constructor: initialize with covariance type, trend function basis and roughness parameter vector. More...
 
 ~Gproc ()
 Destructor: cleans up all memory and destroys object. More...
 
void SetupPrior ()
 Setup the prior. More...
 
void SetupData (Array2D< double > &xdata, Array1D< double > &ydata, Array1D< double > &datavar)
 Setup the data. More...
 
void setCorrParam (Array1D< double > param)
 Set the roughness parameter vector. More...
 
void BuildGP ()
 Build Gaussian Process regressor, i.e. compute internally all necessary matrices and vectors that describe the posterior GP. More...
 
void BuildGP_inv ()
 Build Gaussian Process regressor, i.e. compute internally all necessary matrices and vectors that describe the posterior GP. More...
 
void EvalGP (Array2D< double > &xgrid, string msc, Array1D< double > &mst)
 Evaluate the Gaussian Process at a given grid msc controls whether only mean will be computed, or standard devation and covariance as well. More...
 
void EvalGP_inv (Array2D< double > &xgrid, string msc, Array1D< double > &mst)
 Evaluate the Gaussian Process at a given grid msc controls whether only mean will be computed, or standard devation and covariance as well. More...
 
int getNpt () const
 Get the number of data points. More...
 
int getNdim () const
 Get the dimensionality. More...
 
int getNPC () const
 Get the number of basis terms in the trend. More...
 
double getAl () const
 Get alpha parameter. More...
 
double getBe () const
 Get beta parameter. More...
 
double getSig2hat () const
 Get Sigma-hat-squared, i.e. the posterior variance factor. More...
 
void getVst (Array2D< double > &vst)
 Get $V^*$, an auxiliary matrix. More...
 
void getA (Array2D< double > &acor)
 Get the correlation matrix $A$. More...
 
void getParam (Array1D< double > &param)
 Get the roughness parameters. More...
 
void getCov (Array2D< double > &cov)
 Get the posterior covariance matrix. More...
 
void getVar (Array1D< double > &var)
 Get the posterior variance vector. More...
 
void getXYCov (Array2D< double > &xgrid, Array2D< double > &xycov)
 Get the covariance in a different format, with the x,x' values. More...
 
void getSttPars (Array1D< double > &sttmat)
 Get the Student-t parameters. More...
 
void findBestCorrParam ()
 Function to find the best values for roughness parameters. More...
 
+ + + + + + + +

+Private Member Functions

double covariance (Array1D< double > &x1, Array1D< double > &x2, Array1D< double > &param)
 Prior covariance function. More...
 
void computeDataCov_ (Array2D< double > &xdata, Array1D< double > &param, Array2D< double > &A)
 Compute the data covariance $A$. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

Array2D< double > xdata_
 xdata array More...
 
Array1D< double > ydata_
 ydata array More...
 
Array1D< double > dataVar_
 Data noise 'nugget'. More...
 
int npc_
 Number of bases in the mean trend. More...
 
Array2D< double > Vinv_
 Inverse of the mean trend coefficient prior covariance. More...
 
Array1D< double > z_
 Prior mean of the mean trend. More...
 
double al_
 Prior parameter $\alpha$. More...
 
double be_
 Prior parameter $\beta$. More...
 
double sig2hat_
 Posterior variance factor. More...
 
int npt_
 Number of data points. More...
 
int ndim_
 Dimensionality. More...
 
string covType_
 Covariance type, only 'SqExp' implemented so far. More...
 
PCSetPCModel_
 Basis set for the trend function. More...
 
Array1D< double > mst_
 Mean of the Student-t posterior. More...
 
Array1D< double > var_
 Variance of the Student-t posterior. More...
 
Array2D< double > cov_
 Covariance of the Student-t posterior. More...
 
Array1D< double > param_
 Roughness parameter vector. More...
 
Array2D< double > H_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > Ht_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > A_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > Ainv_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > Ainvd_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > Vinvz_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > HtAinvd_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > AinvH_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > HtAinvH_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > Vst_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > bhat_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > Hbhat_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > yHbhat_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array1D< double > AinvyHbhat_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
Array2D< double > Vstinv_
 Auxiliary matrices or vectors, see the UQTk Manual. More...
 
+

Detailed Description

+

Class for Gaussian processes.

+

Constructor & Destructor Documentation

+ +

◆ Gproc()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Gproc::Gproc (const string covtype,
PCSetPCModel,
Array1D< double > & param 
)
+
+ +

Constructor: initialize with covariance type, trend function basis and roughness parameter vector.

+ +
+
+ +

◆ ~Gproc()

+ +
+
+ + + + + +
+ + + + + + + +
Gproc::~Gproc ()
+
+inline
+
+ +

Destructor: cleans up all memory and destroys object.

+ +
+
+

Member Function Documentation

+ +

◆ BuildGP()

+ +
+
+ + + + + + + +
void Gproc::BuildGP ()
+
+ +

Build Gaussian Process regressor, i.e. compute internally all necessary matrices and vectors that describe the posterior GP.

+ +
+
+ +

◆ BuildGP_inv()

+ +
+
+ + + + + + + +
void Gproc::BuildGP_inv ()
+
+ +

Build Gaussian Process regressor, i.e. compute internally all necessary matrices and vectors that describe the posterior GP.

+
Note
This is an older implementation with explicit inversion of measurement matrix
+
Todo:
Need formal timing analysis to understand in which situations this version is preferred
+ +
+
+ +

◆ computeDataCov_()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Gproc::computeDataCov_ (Array2D< double > & xdata,
Array1D< double > & param,
Array2D< double > & A 
)
+
+private
+
+ +

Compute the data covariance $A$.

+ +
+
+ +

◆ covariance()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
double Gproc::covariance (Array1D< double > & x1,
Array1D< double > & x2,
Array1D< double > & param 
)
+
+private
+
+ +

Prior covariance function.

+
Todo:
put an 'if' check for covtype_
+ +
+
+ +

◆ EvalGP()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Gproc::EvalGP (Array2D< double > & xgrid,
string msc,
Array1D< double > & mst 
)
+
+ +

Evaluate the Gaussian Process at a given grid msc controls whether only mean will be computed, or standard devation and covariance as well.

+ +
+
+ +

◆ EvalGP_inv()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Gproc::EvalGP_inv (Array2D< double > & xgrid,
string msc,
Array1D< double > & mst 
)
+
+ +

Evaluate the Gaussian Process at a given grid msc controls whether only mean will be computed, or standard devation and covariance as well.

+
Note
This is an older implementation with explicit inversion of measurement matrix
+
Todo:
Need formal timing analysis to understand in which situations this version is preferred
+ +
+
+ +

◆ findBestCorrParam()

+ +
+
+ + + + + + + +
void Gproc::findBestCorrParam ()
+
+ +

Function to find the best values for roughness parameters.

+ +
+
+ +

◆ getA()

+ +
+
+ + + + + +
+ + + + + + + + +
void Gproc::getA (Array2D< double > & acor)
+
+inline
+
+ +

Get the correlation matrix $A$.

+ +
+
+ +

◆ getAl()

+ +
+
+ + + + + +
+ + + + + + + +
double Gproc::getAl () const
+
+inline
+
+ +

Get alpha parameter.

+ +
+
+ +

◆ getBe()

+ +
+
+ + + + + +
+ + + + + + + +
double Gproc::getBe () const
+
+inline
+
+ +

Get beta parameter.

+ +
+
+ +

◆ getCov()

+ +
+
+ + + + + +
+ + + + + + + + +
void Gproc::getCov (Array2D< double > & cov)
+
+inline
+
+ +

Get the posterior covariance matrix.

+ +
+
+ +

◆ getNdim()

+ +
+
+ + + + + +
+ + + + + + + +
int Gproc::getNdim () const
+
+inline
+
+ +

Get the dimensionality.

+ +
+
+ +

◆ getNPC()

+ +
+
+ + + + + +
+ + + + + + + +
int Gproc::getNPC () const
+
+inline
+
+ +

Get the number of basis terms in the trend.

+ +
+
+ +

◆ getNpt()

+ +
+
+ + + + + +
+ + + + + + + +
int Gproc::getNpt () const
+
+inline
+
+ +

Get the number of data points.

+ +
+
+ +

◆ getParam()

+ +
+
+ + + + + +
+ + + + + + + + +
void Gproc::getParam (Array1D< double > & param)
+
+inline
+
+ +

Get the roughness parameters.

+ +
+
+ +

◆ getSig2hat()

+ +
+
+ + + + + +
+ + + + + + + +
double Gproc::getSig2hat () const
+
+inline
+
+ +

Get Sigma-hat-squared, i.e. the posterior variance factor.

+ +
+
+ +

◆ getSttPars()

+ +
+
+ + + + + + + + +
void Gproc::getSttPars (Array1D< double > & sttmat)
+
+ +

Get the Student-t parameters.

+
Todo:
check that full cov_ already defined(i.e. msc) not just diagonal
+ +
+
+ +

◆ getVar()

+ +
+
+ + + + + +
+ + + + + + + + +
void Gproc::getVar (Array1D< double > & var)
+
+inline
+
+ +

Get the posterior variance vector.

+ +
+
+ +

◆ getVst()

+ +
+
+ + + + + +
+ + + + + + + + +
void Gproc::getVst (Array2D< double > & vst)
+
+inline
+
+ +

Get $V^*$, an auxiliary matrix.

+ +
+
+ +

◆ getXYCov()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Gproc::getXYCov (Array2D< double > & xgrid,
Array2D< double > & xycov 
)
+
+ +

Get the covariance in a different format, with the x,x' values.

+
Todo:
check that full cov_ already defined(i.e. msc) not just diagonal
+ +
+
+ +

◆ setCorrParam()

+ +
+
+ + + + + +
+ + + + + + + + +
void Gproc::setCorrParam (Array1D< double > param)
+
+inline
+
+ +

Set the roughness parameter vector.

+ +
+
+ +

◆ SetupData()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Gproc::SetupData (Array2D< double > & xdata,
Array1D< double > & ydata,
Array1D< double > & datavar 
)
+
+ +

Setup the data.

+ +
+
+ +

◆ SetupPrior()

+ +
+
+ + + + + + + +
void Gproc::SetupPrior ()
+
+ +

Setup the prior.

+ +
+
+

Member Data Documentation

+ +

◆ A_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::A_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ Ainv_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::Ainv_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ Ainvd_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::Ainvd_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ AinvH_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::AinvH_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ AinvyHbhat_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::AinvyHbhat_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ al_

+ +
+
+ + + + + +
+ + + + +
double Gproc::al_
+
+private
+
+ +

Prior parameter $\alpha$.

+ +
+
+ +

◆ be_

+ +
+
+ + + + + +
+ + + + +
double Gproc::be_
+
+private
+
+ +

Prior parameter $\beta$.

+ +
+
+ +

◆ bhat_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::bhat_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ cov_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::cov_
+
+private
+
+ +

Covariance of the Student-t posterior.

+ +
+
+ +

◆ covType_

+ +
+
+ + + + + +
+ + + + +
string Gproc::covType_
+
+private
+
+ +

Covariance type, only 'SqExp' implemented so far.

+ +
+
+ +

◆ dataVar_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::dataVar_
+
+private
+
+ +

Data noise 'nugget'.

+ +
+
+ +

◆ H_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::H_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ Hbhat_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::Hbhat_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ Ht_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::Ht_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ HtAinvd_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::HtAinvd_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ HtAinvH_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::HtAinvH_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ mst_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::mst_
+
+private
+
+ +

Mean of the Student-t posterior.

+ +
+
+ +

◆ ndim_

+ +
+
+ + + + + +
+ + + + +
int Gproc::ndim_
+
+private
+
+ +

Dimensionality.

+ +
+
+ +

◆ npc_

+ +
+
+ + + + + +
+ + + + +
int Gproc::npc_
+
+private
+
+ +

Number of bases in the mean trend.

+ +
+
+ +

◆ npt_

+ +
+
+ + + + + +
+ + + + +
int Gproc::npt_
+
+private
+
+ +

Number of data points.

+ +
+
+ +

◆ param_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::param_
+
+private
+
+ +

Roughness parameter vector.

+ +
+
+ +

◆ PCModel_

+ +
+
+ + + + + +
+ + + + +
PCSet* Gproc::PCModel_
+
+private
+
+ +

Basis set for the trend function.

+ +
+
+ +

◆ sig2hat_

+ +
+
+ + + + + +
+ + + + +
double Gproc::sig2hat_
+
+private
+
+ +

Posterior variance factor.

+ +
+
+ +

◆ var_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::var_
+
+private
+
+ +

Variance of the Student-t posterior.

+ +
+
+ +

◆ Vinv_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::Vinv_
+
+private
+
+ +

Inverse of the mean trend coefficient prior covariance.

+ +
+
+ +

◆ Vinvz_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::Vinvz_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ Vst_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::Vst_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ Vstinv_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::Vstinv_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ xdata_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Gproc::xdata_
+
+private
+
+ +

xdata array

+ +
+
+ +

◆ ydata_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::ydata_
+
+private
+
+ +

ydata array

+ +
+
+ +

◆ yHbhat_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::yHbhat_
+
+private
+
+ +

Auxiliary matrices or vectors, see the UQTk Manual.

+ +
+
+ +

◆ z_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Gproc::z_
+
+private
+
+ +

Prior mean of the mean trend.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classKLDecompUni-members.html b/doc/doxygen/html/classKLDecompUni-members.html new file mode 100644 index 00000000..e7f97343 --- /dev/null +++ b/doc/doxygen/html/classKLDecompUni-members.html @@ -0,0 +1,88 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
KLDecompUni Member List
+
+
+ +

This is the complete list of members for KLDecompUni, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
absTol_KLDecompUniprivate
decompose(const Array2D< double > &corr, const int &nKL)KLDecompUni
decompose(const double *corr, const int &nKL)KLDecompUni
decomposed_KLDecompUniprivate
eig_info_KLDecompUniprivate
eig_values_KLDecompUniprivate
eigenvalues() constKLDecompUni
eigenvalues(const int nEIG, double *eigs) constKLDecompUni
eigRange_KLDecompUniprivate
ifail_KLDecompUniprivate
il_KLDecompUniprivate
Init()KLDecompUni
iu_KLDecompUniprivate
jobz_KLDecompUniprivate
KL_modes_KLDecompUniprivate
KLDecompUni(const Array1D< double > &tSamples)KLDecompUni
KLDecompUni()KLDecompUni
KLDecompUni(const KLDecompUni &)KLDecompUniinlineprivate
KLmodes() constKLDecompUni
KLmodes(const int npts, const int nKL, double *klModes) constKLDecompUni
KLproject(const Array2D< double > &realiz, Array2D< double > &xi)KLDecompUni
meanRealiz(const Array2D< double > &realiz, Array1D< double > &mean_realiz)KLDecompUni
SetWeights(const Array1D< double > &weights)KLDecompUni
SetWeights(const double *weights, const int npts)KLDecompUni
truncRealiz(const Array1D< double > &meanrea, const Array2D< double > &xi, const int &nKL, Array2D< double > &trunc_realiz)KLDecompUni
uplo_KLDecompUniprivate
vl_KLDecompUniprivate
vu_KLDecompUniprivate
w_KLDecompUniprivate
wh_KLDecompUniprivate
whcwh_KLDecompUniprivate
~KLDecompUni()KLDecompUniinline
+ + + + diff --git a/doc/doxygen/html/classKLDecompUni.html b/doc/doxygen/html/classKLDecompUni.html new file mode 100644 index 00000000..6ef27be0 --- /dev/null +++ b/doc/doxygen/html/classKLDecompUni.html @@ -0,0 +1,1006 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: KLDecompUni Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Computes the Karhunen-Loeve decomposition of a univariate stochastic process. + More...

+ +

#include <kle.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 KLDecompUni (const Array1D< double > &tSamples)
 Constructor that takes the autocorrelation matrix "corr" ( $C$) of the process we are studying as well as the array "tsamples" ( $t$) with the points in time where snapshots of the system were taken. More...
 
 KLDecompUni ()
 
 ~KLDecompUni ()
 Destructor. More...
 
void Init ()
 
void SetWeights (const Array1D< double > &weights)
 Set weights for computing the integral needed for Nystrom's method for solving the Fredholm integral equation. More...
 
void SetWeights (const double *weights, const int npts)
 Set weights for computing the integral needed for Nystrom's method for solving the Fredholm integral equation. More...
 
int decompose (const Array2D< double > &corr, const int &nKL)
 Perform KL decomposition into nKL modes and return actual number of modes that were obtained. More...
 
int decompose (const double *corr, const int &nKL)
 Perform KL decomposition into nKL modes and return actual number of modes that were obtained. More...
 
void KLproject (const Array2D< double > &realiz, Array2D< double > &xi)
 Project realizations $F(t,\theta_l)$ to the KL modes and store them in xi ( $\xi_k$) More...
 
const Array1D< double > & eigenvalues () const
 Get eigenvalues in descending order. More...
 
void eigenvalues (const int nEIG, double *eigs) const
 
const Array2D< double > & KLmodes () const
 Get associated KL modes. More...
 
void KLmodes (const int npts, const int nKL, double *klModes) const
 Get associated KL modes. More...
 
void meanRealiz (const Array2D< double > &realiz, Array1D< double > &mean_realiz)
 Calculate (in meanRealiz) the mean realizations. More...
 
void truncRealiz (const Array1D< double > &meanrea, const Array2D< double > &xi, const int &nKL, Array2D< double > &trunc_realiz)
 Returns the truncated KL sum. More...
 
+ + + + +

+Private Member Functions

 KLDecompUni (const KLDecompUni &)
 Dummy default constructor, which should not be used as it is not well defined. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

bool decomposed_
 Flag to determine whether KL decomposition has taken place (and consequently that the interal data structures contain meaningful eigenvalues and vectors ... ) More...
 
Array2D< double > whcwh_
 Matrix to hold the upper triangular part of the matrix to get eigenvalues of. More...
 
Array1D< double > w_
 Array to hold weights for Nystrom's method for Fredholm integral equation solution. More...
 
Array1D< double > wh_
 Array to hold square roots of weights. More...
 
char jobz_
 Option to determine what to compute (eigenvalues and eigenvectors) More...
 
char eigRange_
 Option to set the type of range for eigenvalues. More...
 
char uplo_
 Option to indicate how matrix is stored. More...
 
double vl_
 Lower bound for range of eigenvalues. More...
 
double vu_
 Upper bound for range of eigenvalues. More...
 
int il_
 Lower index of range of eigenvalues requested. More...
 
int iu_
 Upper index of range of eigenvalues requested. More...
 
double absTol_
 Absolute tolerance for convergence. More...
 
Array1D< double > eig_values_
 Array to store eigenvalues. More...
 
Array2D< double > KL_modes_
 Matrix to store KL modes. More...
 
int eig_info_
 info on success of the eigenvector solutions More...
 
Array1D< int > ifail_
 Array to store indices of eigenvectors that failed to converge. More...
 
+

Detailed Description

+

Computes the Karhunen-Loeve decomposition of a univariate stochastic process.

+

+\[ F(t,\theta) = \left < F(t,\theta) \right >_{\theta} + \sum_{k=1}^{\infty} \sqrt{\lambda_k} f_k(t) \xi_k\] +

+

Constructor & Destructor Documentation

+ +

◆ KLDecompUni() [1/3]

+ +
+
+ + + + + + + + +
KLDecompUni::KLDecompUni (const Array1D< double > & tSamples)
+
+ +

Constructor that takes the autocorrelation matrix "corr" ( $C$) of the process we are studying as well as the array "tsamples" ( $t$) with the points in time where snapshots of the system were taken.

+

Constructs weights ( $w$) needed for the Nystrom method to solve the Fredholm integral equation

+\[ \int C(s,t)f(t)dt=\lambda f(s) \rightarrow \sum w_j C(s_i,t_j) f_k(t_j) = \lambda_k f_k(s_i)\] +

+ +
+
+ +

◆ KLDecompUni() [2/3]

+ +
+
+ + + + + + + +
KLDecompUni::KLDecompUni ()
+
+ +
+
+ +

◆ ~KLDecompUni()

+ +
+
+ + + + + +
+ + + + + + + +
KLDecompUni::~KLDecompUni ()
+
+inline
+
+ +

Destructor.

+ +
+
+ +

◆ KLDecompUni() [3/3]

+ +
+
+ + + + + +
+ + + + + + + + +
KLDecompUni::KLDecompUni (const KLDecompUni)
+
+inlineprivate
+
+ +

Dummy default constructor, which should not be used as it is not well defined.

+

Dummy copy constructor, which should not be used as it is currently not well defined

+ +
+
+

Member Function Documentation

+ +

◆ decompose() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
int KLDecompUni::decompose (const Array2D< double > & corr,
const int & nKL 
)
+
+ +

Perform KL decomposition into nKL modes and return actual number of modes that were obtained.

+

Further manipulation of the discretized Fredholm equation leads to the eigenvalue problem

+\[A g=\lambda g \] +

+

where $A=W K W$ and $g=Wf$, with $W$ being the diagonal matrix, $W_{ii}=\sqrt{w_i}$ and $K_{ij}=Cov(t_i,t_j)$. Solutions consist of pairs of eigenvalues $\lambda_k$ and KL modes $f_k=W^{-1}g_k$.

+ +
+
+ +

◆ decompose() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
int KLDecompUni::decompose (const double * corr,
const int & nKL 
)
+
+ +

Perform KL decomposition into nKL modes and return actual number of modes that were obtained.

+

Further manipulation of the discretized Fredholm equation leads to the eigenvalue problem

+\[A g=\lambda g \] +

+

where $A=W K W$ and $g=Wf$, with $W$ being the diagonal matrix, $W_{ii}=\sqrt{w_i}$ and $K_{ij}=Cov(t_i,t_j)$. Solutions consist of pairs of eigenvalues $\lambda_k$ and KL modes $f_k=W^{-1}g_k$.

+ +
+
+ +

◆ eigenvalues() [1/2]

+ +
+
+ + + + + + + +
const Array1D< double > & KLDecompUni::eigenvalues () const
+
+ +

Get eigenvalues in descending order.

+ +
+
+ +

◆ eigenvalues() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void KLDecompUni::eigenvalues (const int nEIG,
double * eigs 
) const
+
+ +
+
+ +

◆ Init()

+ +
+
+ + + + + + + +
void KLDecompUni::Init ()
+
+ +
+
+ +

◆ KLmodes() [1/2]

+ +
+
+ + + + + + + +
const Array2D< double > & KLDecompUni::KLmodes () const
+
+ +

Get associated KL modes.

+ +
+
+ +

◆ KLmodes() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void KLDecompUni::KLmodes (const int npts,
const int nKL,
double * klModes 
) const
+
+ +

Get associated KL modes.

+ +
+
+ +

◆ KLproject()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void KLDecompUni::KLproject (const Array2D< double > & realiz,
Array2D< double > & xi 
)
+
+ +

Project realizations $F(t,\theta_l)$ to the KL modes and store them in xi ( $\xi_k$)

+

Samples of random variables $\xi_k$ are obtained by projecting realizations of the random process $F$ on the eigenmodes $f_k$

+\[ \left.\xi_k\right\vert_{\theta_l}=\left <F(t,\theta_l)-\left < F(t,\theta) \right >_{\theta}, f_k(t) \right >_t/\sqrt{\lambda_k} \] +

+

... or numerically

+\[ \left.\xi_k\right\vert_{\theta_l}=\sum_{i=1}^{N_p} w_i\left(F(t_i,\theta_l)-\left < F(t_i,\theta) \right >_{\theta} \right) f_k(t_i)/\sqrt{\lambda_k} \] +

+ +
+
+ +

◆ meanRealiz()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void KLDecompUni::meanRealiz (const Array2D< double > & realiz,
Array1D< double > & mean_realiz 
)
+
+ +

Calculate (in meanRealiz) the mean realizations.

+ +
+
+ +

◆ SetWeights() [1/2]

+ +
+
+ + + + + + + + +
void KLDecompUni::SetWeights (const Array1D< double > & weights)
+
+ +

Set weights for computing the integral needed for Nystrom's method for solving the Fredholm integral equation.

+ +
+
+ +

◆ SetWeights() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void KLDecompUni::SetWeights (const double * weights,
const int npts 
)
+
+ +

Set weights for computing the integral needed for Nystrom's method for solving the Fredholm integral equation.

+ +
+
+ +

◆ truncRealiz()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void KLDecompUni::truncRealiz (const Array1D< double > & meanrea,
const Array2D< double > & xi,
const int & nKL,
Array2D< double > & trunc_realiz 
)
+
+ +

Returns the truncated KL sum.

+

+\[ F(t_i,\theta_l) = \left < F(t_i,\theta) \right >_{\theta} + \sum_{k=1}^{nKL} \sqrt{\lambda_k} f_k(t_i) \left. \xi_k\right\vert_{\theta_l} \] +

+ +
+
+

Member Data Documentation

+ +

◆ absTol_

+ +
+
+ + + + + +
+ + + + +
double KLDecompUni::absTol_
+
+private
+
+ +

Absolute tolerance for convergence.

+ +
+
+ +

◆ decomposed_

+ +
+
+ + + + + +
+ + + + +
bool KLDecompUni::decomposed_
+
+private
+
+ +

Flag to determine whether KL decomposition has taken place (and consequently that the interal data structures contain meaningful eigenvalues and vectors ... )

+ +
+
+ +

◆ eig_info_

+ +
+
+ + + + + +
+ + + + +
int KLDecompUni::eig_info_
+
+private
+
+ +

info on success of the eigenvector solutions

+ +
+
+ +

◆ eig_values_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> KLDecompUni::eig_values_
+
+private
+
+ +

Array to store eigenvalues.

+ +
+
+ +

◆ eigRange_

+ +
+
+ + + + + +
+ + + + +
char KLDecompUni::eigRange_
+
+private
+
+ +

Option to set the type of range for eigenvalues.

+ +
+
+ +

◆ ifail_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> KLDecompUni::ifail_
+
+private
+
+ +

Array to store indices of eigenvectors that failed to converge.

+ +
+
+ +

◆ il_

+ +
+
+ + + + + +
+ + + + +
int KLDecompUni::il_
+
+private
+
+ +

Lower index of range of eigenvalues requested.

+ +
+
+ +

◆ iu_

+ +
+
+ + + + + +
+ + + + +
int KLDecompUni::iu_
+
+private
+
+ +

Upper index of range of eigenvalues requested.

+ +
+
+ +

◆ jobz_

+ +
+
+ + + + + +
+ + + + +
char KLDecompUni::jobz_
+
+private
+
+ +

Option to determine what to compute (eigenvalues and eigenvectors)

+ +
+
+ +

◆ KL_modes_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> KLDecompUni::KL_modes_
+
+private
+
+ +

Matrix to store KL modes.

+ +
+
+ +

◆ uplo_

+ +
+
+ + + + + +
+ + + + +
char KLDecompUni::uplo_
+
+private
+
+ +

Option to indicate how matrix is stored.

+ +
+
+ +

◆ vl_

+ +
+
+ + + + + +
+ + + + +
double KLDecompUni::vl_
+
+private
+
+ +

Lower bound for range of eigenvalues.

+ +
+
+ +

◆ vu_

+ +
+
+ + + + + +
+ + + + +
double KLDecompUni::vu_
+
+private
+
+ +

Upper bound for range of eigenvalues.

+ +
+
+ +

◆ w_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> KLDecompUni::w_
+
+private
+
+ +

Array to hold weights for Nystrom's method for Fredholm integral equation solution.

+ +
+
+ +

◆ wh_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> KLDecompUni::wh_
+
+private
+
+ +

Array to hold square roots of weights.

+ +
+
+ +

◆ whcwh_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> KLDecompUni::whcwh_
+
+private
+
+ +

Matrix to hold the upper triangular part of the matrix to get eigenvalues of.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__ABC-members.html b/doc/doxygen/html/classLik__ABC-members.html new file mode 100644 index 00000000..fb64d6d6 --- /dev/null +++ b/doc/doxygen/html/classLik__ABC-members.html @@ -0,0 +1,103 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_ABC Member List
+
+
+ +

This is the complete list of members for Lik_ABC, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
abceps_Lik_ABCprivate
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_ABCvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_ABC(double eps)Lik_ABCinline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_ABC()Lik_ABCinline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__ABC.html b/doc/doxygen/html/classLik__ABC.html new file mode 100644 index 00000000..5ded3a3b --- /dev/null +++ b/doc/doxygen/html/classLik__ABC.html @@ -0,0 +1,340 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_ABC Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_ABC Class Reference
+
+
+ +

Derived class for ABC likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_ABC:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_ABC (double eps)
 Constructor given ABC epsilon. More...
 
 ~Lik_ABC ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + +

+Private Attributes

double abceps_
 ABC epsilon. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for ABC likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_ABC()

+ +
+
+ + + + + +
+ + + + + + + + +
Lik_ABC::Lik_ABC (double eps)
+
+inline
+
+ +

Constructor given ABC epsilon.

+ +
+
+ +

◆ ~Lik_ABC()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_ABC::~Lik_ABC ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_ABC::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+

Member Data Documentation

+ +

◆ abceps_

+ +
+
+ + + + + +
+ + + + +
double Lik_ABC::abceps_
+
+private
+
+ +

ABC epsilon.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__ABC.png b/doc/doxygen/html/classLik__ABC.png new file mode 100644 index 00000000..6e632528 Binary files /dev/null and b/doc/doxygen/html/classLik__ABC.png differ diff --git a/doc/doxygen/html/classLik__ABCm-members.html b/doc/doxygen/html/classLik__ABCm-members.html new file mode 100644 index 00000000..329df292 --- /dev/null +++ b/doc/doxygen/html/classLik__ABCm-members.html @@ -0,0 +1,103 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_ABCm Member List
+
+
+ +

This is the complete list of members for Lik_ABCm, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
abceps_Lik_ABCmprivate
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_ABCmvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_ABCm(double eps)Lik_ABCminline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_ABCm()Lik_ABCminline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__ABCm.html b/doc/doxygen/html/classLik__ABCm.html new file mode 100644 index 00000000..bfeb3d63 --- /dev/null +++ b/doc/doxygen/html/classLik__ABCm.html @@ -0,0 +1,340 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_ABCm Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_ABCm Class Reference
+
+
+ +

Derived class for ABC-mean likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_ABCm:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_ABCm (double eps)
 Constructor given ABC epsilon. More...
 
 ~Lik_ABCm ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + +

+Private Attributes

double abceps_
 ABC epsilon. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for ABC-mean likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_ABCm()

+ +
+
+ + + + + +
+ + + + + + + + +
Lik_ABCm::Lik_ABCm (double eps)
+
+inline
+
+ +

Constructor given ABC epsilon.

+ +
+
+ +

◆ ~Lik_ABCm()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_ABCm::~Lik_ABCm ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_ABCm::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+

Member Data Documentation

+ +

◆ abceps_

+ +
+
+ + + + + +
+ + + + +
double Lik_ABCm::abceps_
+
+private
+
+ +

ABC epsilon.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__ABCm.png b/doc/doxygen/html/classLik__ABCm.png new file mode 100644 index 00000000..f6b612c1 Binary files /dev/null and b/doc/doxygen/html/classLik__ABCm.png differ diff --git a/doc/doxygen/html/classLik__Classical-members.html b/doc/doxygen/html/classLik__Classical-members.html new file mode 100644 index 00000000..10bd7049 --- /dev/null +++ b/doc/doxygen/html/classLik__Classical-members.html @@ -0,0 +1,102 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_Classical Member List
+
+
+ +

This is the complete list of members for Lik_Classical, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_Classicalvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_Classical()Lik_Classicalinline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_Classical()Lik_Classicalinline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__Classical.html b/doc/doxygen/html/classLik__Classical.html new file mode 100644 index 00000000..1a2856d7 --- /dev/null +++ b/doc/doxygen/html/classLik__Classical.html @@ -0,0 +1,307 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_Classical Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_Classical Class Reference
+
+
+ +

Derived class for classical likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_Classical:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_Classical ()
 Constructor. More...
 
 ~Lik_Classical ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for classical likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_Classical()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_Classical::Lik_Classical ()
+
+inline
+
+ +

Constructor.

+ +
+
+ +

◆ ~Lik_Classical()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_Classical::~Lik_Classical ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_Classical::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__Classical.png b/doc/doxygen/html/classLik__Classical.png new file mode 100644 index 00000000..b87a9a4a Binary files /dev/null and b/doc/doxygen/html/classLik__Classical.png differ diff --git a/doc/doxygen/html/classLik__Full-members.html b/doc/doxygen/html/classLik__Full-members.html new file mode 100644 index 00000000..d22d91ce --- /dev/null +++ b/doc/doxygen/html/classLik__Full-members.html @@ -0,0 +1,104 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_Full Member List
+
+
+ +

This is the complete list of members for Lik_Full, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bdw_Lik_Fullprivate
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_Fullvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_Full(double bdw, int nsam)Lik_Fullinline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
nsam_Lik_Fullprivate
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_Full()Lik_Fullinline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__Full.html b/doc/doxygen/html/classLik__Full.html new file mode 100644 index 00000000..727a80ae --- /dev/null +++ b/doc/doxygen/html/classLik__Full.html @@ -0,0 +1,377 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_Full Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_Full Class Reference
+
+
+ +

Derived class for full likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_Full:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_Full (double bdw, int nsam)
 Constructor given KDE bandwidth and sample size. More...
 
 ~Lik_Full ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + + + + +

+Private Attributes

double bdw_
 KDE bandwidth. More...
 
int nsam_
 KDE sample size. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for full likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_Full()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Lik_Full::Lik_Full (double bdw,
int nsam 
)
+
+inline
+
+ +

Constructor given KDE bandwidth and sample size.

+ +
+
+ +

◆ ~Lik_Full()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_Full::~Lik_Full ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_Full::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+

Member Data Documentation

+ +

◆ bdw_

+ +
+
+ + + + + +
+ + + + +
double Lik_Full::bdw_
+
+private
+
+ +

KDE bandwidth.

+ +
+
+ +

◆ nsam_

+ +
+
+ + + + + +
+ + + + +
int Lik_Full::nsam_
+
+private
+
+ +

KDE sample size.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__Full.png b/doc/doxygen/html/classLik__Full.png new file mode 100644 index 00000000..20f66ba1 Binary files /dev/null and b/doc/doxygen/html/classLik__Full.png differ diff --git a/doc/doxygen/html/classLik__GausMarg-members.html b/doc/doxygen/html/classLik__GausMarg-members.html new file mode 100644 index 00000000..a9fabf72 --- /dev/null +++ b/doc/doxygen/html/classLik__GausMarg-members.html @@ -0,0 +1,102 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_GausMarg Member List
+
+
+ +

This is the complete list of members for Lik_GausMarg, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_GausMargvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_GausMarg()Lik_GausMarginline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_GausMarg()Lik_GausMarginline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__GausMarg.html b/doc/doxygen/html/classLik__GausMarg.html new file mode 100644 index 00000000..c2ae399e --- /dev/null +++ b/doc/doxygen/html/classLik__GausMarg.html @@ -0,0 +1,307 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_GausMarg Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_GausMarg Class Reference
+
+
+ +

Derived class for gaussian-marginal likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_GausMarg:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_GausMarg ()
 Constructor. More...
 
 ~Lik_GausMarg ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for gaussian-marginal likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_GausMarg()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_GausMarg::Lik_GausMarg ()
+
+inline
+
+ +

Constructor.

+ +
+
+ +

◆ ~Lik_GausMarg()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_GausMarg::~Lik_GausMarg ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_GausMarg::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__GausMarg.png b/doc/doxygen/html/classLik__GausMarg.png new file mode 100644 index 00000000..30b5f456 Binary files /dev/null and b/doc/doxygen/html/classLik__GausMarg.png differ diff --git a/doc/doxygen/html/classLik__GausMargD-members.html b/doc/doxygen/html/classLik__GausMargD-members.html new file mode 100644 index 00000000..5b82b34b --- /dev/null +++ b/doc/doxygen/html/classLik__GausMargD-members.html @@ -0,0 +1,102 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_GausMargD Member List
+
+
+ +

This is the complete list of members for Lik_GausMargD, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_GausMargDvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_GausMargD()Lik_GausMargDinline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_GausMargD()Lik_GausMargDinline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__GausMargD.html b/doc/doxygen/html/classLik__GausMargD.html new file mode 100644 index 00000000..09bab1ff --- /dev/null +++ b/doc/doxygen/html/classLik__GausMargD.html @@ -0,0 +1,306 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_GausMargD Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_GausMargD Class Reference
+
+
+ +

Derived class for gaussian-marginal likelihood with discrete parameter. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_GausMargD:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_GausMargD ()
 Constructor. More...
 
 ~Lik_GausMargD ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for gaussian-marginal likelihood with discrete parameter.

+

Constructor & Destructor Documentation

+ +

◆ Lik_GausMargD()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_GausMargD::Lik_GausMargD ()
+
+inline
+
+ +

Constructor.

+ +
+
+ +

◆ ~Lik_GausMargD()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_GausMargD::~Lik_GausMargD ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_GausMargD::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classLik__GausMargD.png b/doc/doxygen/html/classLik__GausMargD.png new file mode 100644 index 00000000..2c151950 Binary files /dev/null and b/doc/doxygen/html/classLik__GausMargD.png differ diff --git a/doc/doxygen/html/classLik__Koh-members.html b/doc/doxygen/html/classLik__Koh-members.html new file mode 100644 index 00000000..dbada890 --- /dev/null +++ b/doc/doxygen/html/classLik__Koh-members.html @@ -0,0 +1,103 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_Koh Member List
+
+
+ +

This is the complete list of members for Lik_Koh, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chDim_Postprotected
corLength_Lik_Kohprivate
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_Kohvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_Koh(double corLength)Lik_Kohinline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_Koh()Lik_Kohinline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__Koh.html b/doc/doxygen/html/classLik__Koh.html new file mode 100644 index 00000000..8d13d54b --- /dev/null +++ b/doc/doxygen/html/classLik__Koh.html @@ -0,0 +1,337 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_Koh Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_Koh Class Reference
+
+
+ +

Derived class for Kennedy-O'Hagan likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_Koh:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_Koh (double corLength)
 Constructor given correlation length. More...
 
 ~Lik_Koh ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + +

+Private Attributes

double corLength_
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for Kennedy-O'Hagan likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_Koh()

+ +
+
+ + + + + +
+ + + + + + + + +
Lik_Koh::Lik_Koh (double corLength)
+
+inline
+
+ +

Constructor given correlation length.

+ +
+
+ +

◆ ~Lik_Koh()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_Koh::~Lik_Koh ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_Koh::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+

Member Data Documentation

+ +

◆ corLength_

+ +
+
+ + + + + +
+ + + + +
double Lik_Koh::corLength_
+
+private
+
+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__Koh.png b/doc/doxygen/html/classLik__Koh.png new file mode 100644 index 00000000..4b57b8d4 Binary files /dev/null and b/doc/doxygen/html/classLik__Koh.png differ diff --git a/doc/doxygen/html/classLik__MVN-members.html b/doc/doxygen/html/classLik__MVN-members.html new file mode 100644 index 00000000..c9098006 --- /dev/null +++ b/doc/doxygen/html/classLik__MVN-members.html @@ -0,0 +1,103 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_MVN Member List
+
+
+ +

This is the complete list of members for Lik_MVN, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_MVNvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_MVN(double nugget)Lik_MVNinline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
nugget_Lik_MVNprivate
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_MVN()Lik_MVNinline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__MVN.html b/doc/doxygen/html/classLik__MVN.html new file mode 100644 index 00000000..42cd8f11 --- /dev/null +++ b/doc/doxygen/html/classLik__MVN.html @@ -0,0 +1,340 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_MVN Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_MVN Class Reference
+
+
+ +

Derived class for mvn likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_MVN:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_MVN (double nugget)
 Constructor given fiagonal nugget. More...
 
 ~Lik_MVN ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + +

+Private Attributes

double nugget_
 Nugget size. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for mvn likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_MVN()

+ +
+
+ + + + + +
+ + + + + + + + +
Lik_MVN::Lik_MVN (double nugget)
+
+inline
+
+ +

Constructor given fiagonal nugget.

+ +
+
+ +

◆ ~Lik_MVN()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_MVN::~Lik_MVN ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_MVN::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+

Member Data Documentation

+ +

◆ nugget_

+ +
+
+ + + + + +
+ + + + +
double Lik_MVN::nugget_
+
+private
+
+ +

Nugget size.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__MVN.png b/doc/doxygen/html/classLik__MVN.png new file mode 100644 index 00000000..83190df6 Binary files /dev/null and b/doc/doxygen/html/classLik__MVN.png differ diff --git a/doc/doxygen/html/classLik__Marg-members.html b/doc/doxygen/html/classLik__Marg-members.html new file mode 100644 index 00000000..6591db53 --- /dev/null +++ b/doc/doxygen/html/classLik__Marg-members.html @@ -0,0 +1,104 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lik_Marg Member List
+
+
+ +

This is the complete list of members for Lik_Marg, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bdw_Lik_Margprivate
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Lik_Margvirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
Lik_Marg(double bdw, int nsam)Lik_Marginline
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
nsam_Lik_Margprivate
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Lik_Marg()Lik_Marginline
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classLik__Marg.html b/doc/doxygen/html/classLik__Marg.html new file mode 100644 index 00000000..b63f92a0 --- /dev/null +++ b/doc/doxygen/html/classLik__Marg.html @@ -0,0 +1,377 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lik_Marg Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
Lik_Marg Class Reference
+
+
+ +

Derived class for marginal likelihood. + More...

+ +

#include <post.h>

+
+Inheritance diagram for Lik_Marg:
+
+
+ + +Post + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lik_Marg (double bdw, int nsam)
 Constructor given KDE bandwidth and sample size. More...
 
 ~Lik_Marg ()
 Destructor. More...
 
double evalLogLik (Array1D< double > &m)
 Evaluate log-likelihood. More...
 
- Public Member Functions inherited from Post
 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
+ + + + + + + +

+Private Attributes

double bdw_
 KDE bandwidth. More...
 
int nsam_
 KDE sample size. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Post
Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+

Detailed Description

+

Derived class for marginal likelihood.

+

Constructor & Destructor Documentation

+ +

◆ Lik_Marg()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
Lik_Marg::Lik_Marg (double bdw,
int nsam 
)
+
+inline
+
+ +

Constructor given KDE bandwidth and sample size.

+ +
+
+ +

◆ ~Lik_Marg()

+ +
+
+ + + + + +
+ + + + + + + +
Lik_Marg::~Lik_Marg ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
double Lik_Marg::evalLogLik (Array1D< double > & m)
+
+virtual
+
+ +

Evaluate log-likelihood.

+ +

Reimplemented from Post.

+ +
+
+

Member Data Documentation

+ +

◆ bdw_

+ +
+
+ + + + + +
+ + + + +
double Lik_Marg::bdw_
+
+private
+
+ +

KDE bandwidth.

+ +
+
+ +

◆ nsam_

+ +
+
+ + + + + +
+ + + + +
int Lik_Marg::nsam_
+
+private
+
+ +

KDE sample size.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLik__Marg.png b/doc/doxygen/html/classLik__Marg.png new file mode 100644 index 00000000..b63ed3cb Binary files /dev/null and b/doc/doxygen/html/classLik__Marg.png differ diff --git a/doc/doxygen/html/classLikelihoodBase-members.html b/doc/doxygen/html/classLikelihoodBase-members.html new file mode 100644 index 00000000..26c16156 --- /dev/null +++ b/doc/doxygen/html/classLikelihoodBase-members.html @@ -0,0 +1,58 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
LikelihoodBase Member List
+
+
+ +

This is the complete list of members for LikelihoodBase, including all inherited members.

+ + + +
eval(Array1D< double > &)LikelihoodBaseinlinevirtual
~LikelihoodBase()LikelihoodBaseinlinevirtual
+ + + + diff --git a/doc/doxygen/html/classLikelihoodBase.html b/doc/doxygen/html/classLikelihoodBase.html new file mode 100644 index 00000000..d265ed1a --- /dev/null +++ b/doc/doxygen/html/classLikelihoodBase.html @@ -0,0 +1,134 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: LikelihoodBase Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
LikelihoodBase Class Reference
+
+
+ +

#include <mcmc.h>

+
+Inheritance diagram for LikelihoodBase:
+
+
+ + +DFI +DFIInner + +
+ + + + + + +

+Public Member Functions

virtual double eval (Array1D< double > &)
 
virtual ~LikelihoodBase ()
 
+

Constructor & Destructor Documentation

+ +

◆ ~LikelihoodBase()

+ +
+
+ + + + + +
+ + + + + + + +
virtual LikelihoodBase::~LikelihoodBase ()
+
+inlinevirtual
+
+ +
+
+

Member Function Documentation

+ +

◆ eval()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual double LikelihoodBase::eval (Array1D< double > & )
+
+inlinevirtual
+
+ +

Reimplemented in DFI, and DFIInner.

+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classLikelihoodBase.png b/doc/doxygen/html/classLikelihoodBase.png new file mode 100644 index 00000000..d484e4db Binary files /dev/null and b/doc/doxygen/html/classLikelihoodBase.png differ diff --git a/doc/doxygen/html/classLreg-members.html b/doc/doxygen/html/classLreg-members.html new file mode 100644 index 00000000..d18274c3 --- /dev/null +++ b/doc/doxygen/html/classLreg-members.html @@ -0,0 +1,108 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Lreg Member List
+
+
+ +

This is the complete list of members for Lreg, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A_Lregprotected
A_inv_Lregprotected
BCS_BuildRegr(Array1D< int > &selected, double eta)Lreg
bdata_Lregprotected
coef_Lregprotected
coef_cov_Lregprotected
coef_erb_Lregprotected
computeErrorMetrics(string method)Lreg
computeRVE(Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)Lreg
dataSetFlag_Lregprivate
diagP_Lregprotected
diagPFlag_Lregprotected
EvalBases(Array2D< double > &xx, Array2D< double > &bb)Lreginlinevirtual
EvalRegr(Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)Lreg
GetCoef(Array1D< double > &coef)Lreginline
GetCoefCov(Array2D< double > &coef_cov)Lreginline
getDiagP()Lreg
GetMindex(Array2D< int > &mindex)Lreginlinevirtual
GetNbas() constLreginline
GetNdim() constLreginline
GetNpt() constLreginline
getResid()Lreg
GetSigma2() constLreginline
Hty_Lregprotected
InitRegr()Lreg
Lreg()Lreginline
LSQ_BuildRegr()Lreg
LSQ_computeBestLambda()Lreg
LSQ_computeBestLambdas()Lreg
LSQ_computeGCV()Lregprivate
LSQ_computeLOO()Lregprivate
nbas_Lregprotected
ndim_Lregprotected
npt_Lregprotected
Proj(Array1D< double > &array, Array1D< double > &proj_array)Lreg
regMode_Lregprivate
resid_Lregprotected
residFlag_Lregprotected
SetCenters(Array2D< double > &centers)Lreginlinevirtual
SetMindex(Array2D< int > &mindex)Lreginlinevirtual
SetParamsRBF()Lreginlinevirtual
SetRegMode(string regmode)Lreginline
SetRegWeights(Array1D< double > &weights)Lreg
SetupData(Array2D< double > &xdata, Array1D< double > &ydata)Lreg
SetupData(Array2D< double > &xdata, Array2D< double > &ydata)Lreg
SetWidths(Array1D< double > &widths)Lreginlinevirtual
sigma2_Lregprotected
StripBases(Array1D< int > &used)Lreginlinevirtual
weights_Lregprotected
xdata_Lregprotected
ydata_Lregprotected
~Lreg()Lreginline
+ + + + diff --git a/doc/doxygen/html/classLreg.html b/doc/doxygen/html/classLreg.html new file mode 100644 index 00000000..357afb45 --- /dev/null +++ b/doc/doxygen/html/classLreg.html @@ -0,0 +1,1603 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Lreg Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Class for linear parameteric regression. + More...

+ +

#include <lreg.h>

+
+Inheritance diagram for Lreg:
+
+
+ + +PCreg +PLreg +RBFreg + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Lreg ()
 Constructor. More...
 
 ~Lreg ()
 Destrcutor. More...
 
virtual void SetMindex (Array2D< int > &mindex)
 Set multiindex. More...
 
virtual void GetMindex (Array2D< int > &mindex)
 Get multiindex. More...
 
virtual void SetCenters (Array2D< double > &centers)
 Set centers (for RBF) More...
 
virtual void SetWidths (Array1D< double > &widths)
 Set widths (for RBF) More...
 
virtual void SetParamsRBF ()
 Set parameters (for RBF) More...
 
virtual void EvalBases (Array2D< double > &xx, Array2D< double > &bb)
 Evaluate bases. More...
 
virtual void StripBases (Array1D< int > &used)
 Strip bases. More...
 
void InitRegr ()
 Initialize. More...
 
void SetupData (Array2D< double > &xdata, Array1D< double > &ydata)
 Setup data (1d ydata) More...
 
void SetupData (Array2D< double > &xdata, Array2D< double > &ydata)
 Setup data (2d ydata) More...
 
void SetRegMode (string regmode)
 Set the regression mode. More...
 
void SetRegWeights (Array1D< double > &weights)
 Set weights. More...
 
void BCS_BuildRegr (Array1D< int > &selected, double eta)
 Build BCS regression. More...
 
void LSQ_BuildRegr ()
 Build LSQ regression. More...
 
void EvalRegr (Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)
 Evaluate the regression expansion. More...
 
int GetNpt () const
 Get the number of points. More...
 
int GetNdim () const
 Get dimensionality. More...
 
int GetNbas () const
 Get the number of bases. More...
 
double GetSigma2 () const
 Get the variance. More...
 
void GetCoefCov (Array2D< double > &coef_cov)
 Get coefficient covariance. More...
 
void GetCoef (Array1D< double > &coef)
 Get coefficients. More...
 
void Proj (Array1D< double > &array, Array1D< double > &proj_array)
 Project. More...
 
Array1D< double > LSQ_computeBestLambdas ()
 Compute the best values for regulariation parameter vector lambda, for LSQ. More...
 
double LSQ_computeBestLambda ()
 Compute the best value for regulariation parameter lambda, for LSQ. More...
 
void getResid ()
 Compute the residual vector, if not already computed. More...
 
void getDiagP ()
 Compute the diagonal of projection matrix, if not already computed. More...
 
Array1D< double > computeErrorMetrics (string method)
 Compote error according to a selected metrics. More...
 
double computeRVE (Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)
 Compute validation error. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Protected Attributes

Array2D< double > xdata_
 xdata array More...
 
Array1D< double > ydata_
 ydata array More...
 
int npt_
 Number of samples. More...
 
int nbas_
 Number of bases. More...
 
int ndim_
 Dimensionality. More...
 
double sigma2_
 Variance. More...
 
Array1D< double > weights_
 Weights. More...
 
Array1D< double > resid_
 Residuals. More...
 
bool residFlag_
 Flag to indicate whether residual is computed. More...
 
Array1D< double > diagP_
 Diagonal of projection matrix. More...
 
bool diagPFlag_
 Flag to indicate whether diagonal of projetion matrix is computed. More...
 
Array2D< double > bdata_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_inv_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > coef_cov_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > Hty_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_erb_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
+ + + + + + + +

+Private Member Functions

double LSQ_computeLOO ()
 Compute Leave-one-out error for LSQ. More...
 
double LSQ_computeGCV ()
 COmpute generalized-cross-validation error for LSQ. More...
 
+ + + + + + + +

+Private Attributes

bool dataSetFlag_
 Flag to indicate whether data has been set or not. More...
 
string regMode_
 Regression mode (m, ms, msc for mean-only, mean+variance, mean+covariance) More...
 
+

Detailed Description

+

Class for linear parameteric regression.

+

Constructor & Destructor Documentation

+ +

◆ Lreg()

+ +
+
+ + + + + +
+ + + + + + + +
Lreg::Lreg ()
+
+inline
+
+ +

Constructor.

+ +
+
+ +

◆ ~Lreg()

+ +
+
+ + + + + +
+ + + + + + + +
Lreg::~Lreg ()
+
+inline
+
+ +

Destrcutor.

+ +
+
+

Member Function Documentation

+ +

◆ BCS_BuildRegr()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Lreg::BCS_BuildRegr (Array1D< int > & selected,
double eta 
)
+
+ +

Build BCS regression.

+ +
+
+ +

◆ computeErrorMetrics()

+ +
+
+ + + + + + + + +
Array1D< double > Lreg::computeErrorMetrics (string method)
+
+ +

Compote error according to a selected metrics.

+ +
+
+ +

◆ computeRVE()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double Lreg::computeRVE (Array2D< double > & xval,
Array1D< double > & yval,
Array1D< double > & yval_regr 
)
+
+ +

Compute validation error.

+ +
+
+ +

◆ EvalBases()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
virtual void Lreg::EvalBases (Array2D< double > & xx,
Array2D< double > & bb 
)
+
+inlinevirtual
+
+ +

Evaluate bases.

+ +

Reimplemented in PLreg, PCreg, and RBFreg.

+ +
+
+ +

◆ EvalRegr()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Lreg::EvalRegr (Array2D< double > & xcheck,
Array1D< double > & ycheck,
Array1D< double > & yvar,
Array2D< double > & ycov 
)
+
+ +

Evaluate the regression expansion.

+ +
+
+ +

◆ GetCoef()

+ +
+
+ + + + + +
+ + + + + + + + +
void Lreg::GetCoef (Array1D< double > & coef)
+
+inline
+
+ +

Get coefficients.

+ +
+
+ +

◆ GetCoefCov()

+ +
+
+ + + + + +
+ + + + + + + + +
void Lreg::GetCoefCov (Array2D< double > & coef_cov)
+
+inline
+
+ +

Get coefficient covariance.

+ +
+
+ +

◆ getDiagP()

+ +
+
+ + + + + + + +
void Lreg::getDiagP ()
+
+ +

Compute the diagonal of projection matrix, if not already computed.

+ +
+
+ +

◆ GetMindex()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual void Lreg::GetMindex (Array2D< int > & mindex)
+
+inlinevirtual
+
+ +

Get multiindex.

+ +

Reimplemented in PLreg, and PCreg.

+ +
+
+ +

◆ GetNbas()

+ +
+
+ + + + + +
+ + + + + + + +
int Lreg::GetNbas () const
+
+inline
+
+ +

Get the number of bases.

+ +
+
+ +

◆ GetNdim()

+ +
+
+ + + + + +
+ + + + + + + +
int Lreg::GetNdim () const
+
+inline
+
+ +

Get dimensionality.

+ +
+
+ +

◆ GetNpt()

+ +
+
+ + + + + +
+ + + + + + + +
int Lreg::GetNpt () const
+
+inline
+
+ +

Get the number of points.

+ +
+
+ +

◆ getResid()

+ +
+
+ + + + + + + +
void Lreg::getResid ()
+
+ +

Compute the residual vector, if not already computed.

+ +
+
+ +

◆ GetSigma2()

+ +
+
+ + + + + +
+ + + + + + + +
double Lreg::GetSigma2 () const
+
+inline
+
+ +

Get the variance.

+ +
+
+ +

◆ InitRegr()

+ +
+
+ + + + + + + +
void Lreg::InitRegr ()
+
+ +

Initialize.

+ +
+
+ +

◆ LSQ_BuildRegr()

+ +
+
+ + + + + + + +
void Lreg::LSQ_BuildRegr ()
+
+ +

Build LSQ regression.

+ +
+
+ +

◆ LSQ_computeBestLambda()

+ +
+
+ + + + + + + +
double Lreg::LSQ_computeBestLambda ()
+
+ +

Compute the best value for regulariation parameter lambda, for LSQ.

+ +
+
+ +

◆ LSQ_computeBestLambdas()

+ +
+
+ + + + + + + +
Array1D< double > Lreg::LSQ_computeBestLambdas ()
+
+ +

Compute the best values for regulariation parameter vector lambda, for LSQ.

+ +
+
+ +

◆ LSQ_computeGCV()

+ +
+
+ + + + + +
+ + + + + + + +
double Lreg::LSQ_computeGCV ()
+
+private
+
+ +

COmpute generalized-cross-validation error for LSQ.

+ +
+
+ +

◆ LSQ_computeLOO()

+ +
+
+ + + + + +
+ + + + + + + +
double Lreg::LSQ_computeLOO ()
+
+private
+
+ +

Compute Leave-one-out error for LSQ.

+ +
+
+ +

◆ Proj()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Lreg::Proj (Array1D< double > & array,
Array1D< double > & proj_array 
)
+
+ +

Project.

+ +
+
+ +

◆ SetCenters()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual void Lreg::SetCenters (Array2D< double > & centers)
+
+inlinevirtual
+
+ +

Set centers (for RBF)

+ +

Reimplemented in RBFreg.

+ +
+
+ +

◆ SetMindex()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual void Lreg::SetMindex (Array2D< int > & mindex)
+
+inlinevirtual
+
+ +

Set multiindex.

+ +

Reimplemented in PLreg, and PCreg.

+ +
+
+ +

◆ SetParamsRBF()

+ +
+
+ + + + + +
+ + + + + + + +
virtual void Lreg::SetParamsRBF ()
+
+inlinevirtual
+
+ +

Set parameters (for RBF)

+ +
+
+ +

◆ SetRegMode()

+ +
+
+ + + + + +
+ + + + + + + + +
void Lreg::SetRegMode (string regmode)
+
+inline
+
+ +

Set the regression mode.

+ +
+
+ +

◆ SetRegWeights()

+ +
+
+ + + + + + + + +
void Lreg::SetRegWeights (Array1D< double > & weights)
+
+ +

Set weights.

+ +
+
+ +

◆ SetupData() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Lreg::SetupData (Array2D< double > & xdata,
Array1D< double > & ydata 
)
+
+ +

Setup data (1d ydata)

+ +
+
+ +

◆ SetupData() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Lreg::SetupData (Array2D< double > & xdata,
Array2D< double > & ydata 
)
+
+ +

Setup data (2d ydata)

+ +
+
+ +

◆ SetWidths()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual void Lreg::SetWidths (Array1D< double > & widths)
+
+inlinevirtual
+
+ +

Set widths (for RBF)

+ +

Reimplemented in RBFreg.

+ +
+
+ +

◆ StripBases()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual void Lreg::StripBases (Array1D< int > & used)
+
+inlinevirtual
+
+ +

Strip bases.

+ +

Reimplemented in PLreg, PCreg, and RBFreg.

+ +
+
+

Member Data Documentation

+ +

◆ A_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Lreg::A_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ A_inv_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Lreg::A_inv_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ bdata_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Lreg::bdata_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ coef_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::coef_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ coef_cov_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Lreg::coef_cov_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ coef_erb_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::coef_erb_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ dataSetFlag_

+ +
+
+ + + + + +
+ + + + +
bool Lreg::dataSetFlag_
+
+private
+
+ +

Flag to indicate whether data has been set or not.

+ +
+
+ +

◆ diagP_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::diagP_
+
+protected
+
+ +

Diagonal of projection matrix.

+ +
+
+ +

◆ diagPFlag_

+ +
+
+ + + + + +
+ + + + +
bool Lreg::diagPFlag_
+
+protected
+
+ +

Flag to indicate whether diagonal of projetion matrix is computed.

+ +
+
+ +

◆ Hty_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::Hty_
+
+protected
+
+ +

Auxiliary matrix or vector; see UQTk Manual.

+ +
+
+ +

◆ nbas_

+ +
+
+ + + + + +
+ + + + +
int Lreg::nbas_
+
+protected
+
+ +

Number of bases.

+ +
+
+ +

◆ ndim_

+ +
+
+ + + + + +
+ + + + +
int Lreg::ndim_
+
+protected
+
+ +

Dimensionality.

+ +
+
+ +

◆ npt_

+ +
+
+ + + + + +
+ + + + +
int Lreg::npt_
+
+protected
+
+ +

Number of samples.

+ +
+
+ +

◆ regMode_

+ +
+
+ + + + + +
+ + + + +
string Lreg::regMode_
+
+private
+
+ +

Regression mode (m, ms, msc for mean-only, mean+variance, mean+covariance)

+ +
+
+ +

◆ resid_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::resid_
+
+protected
+
+ +

Residuals.

+ +
+
+ +

◆ residFlag_

+ +
+
+ + + + + +
+ + + + +
bool Lreg::residFlag_
+
+protected
+
+ +

Flag to indicate whether residual is computed.

+ +
+
+ +

◆ sigma2_

+ +
+
+ + + + + +
+ + + + +
double Lreg::sigma2_
+
+protected
+
+ +

Variance.

+ +
+
+ +

◆ weights_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::weights_
+
+protected
+
+ +

Weights.

+ +
+
+ +

◆ xdata_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Lreg::xdata_
+
+protected
+
+ +

xdata array

+ +
+
+ +

◆ ydata_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Lreg::ydata_
+
+protected
+
+ +

ydata array

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classLreg.png b/doc/doxygen/html/classLreg.png new file mode 100644 index 00000000..1ba4ec34 Binary files /dev/null and b/doc/doxygen/html/classLreg.png differ diff --git a/doc/doxygen/html/classMCMC-members.html b/doc/doxygen/html/classMCMC-members.html new file mode 100644 index 00000000..a2e0cafc --- /dev/null +++ b/doc/doxygen/html/classMCMC-members.html @@ -0,0 +1,147 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
MCMC Member List
+
+
+ +

This is the complete list of members for MCMC, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
accRatio_MCMCprivate
adaptstepInit_MCMCprivate
appendMAP()MCMC
chainDim_MCMCprivate
chaindimInit_MCMCprivate
currState_MCMCprivate
default_eps_cov_MCMCprivate
default_eps_mala_MCMCprivate
default_gamma_MCMCprivate
default_method_MCMCprivate
epscovInit_MCMCprivate
epsMALA_MCMCprivate
epsMalaInit_MCMCprivate
evalGradLogPosterior(Array1D< double > &m, Array1D< double > &grads)MCMC
evallogMVN_diag(Array1D< double > &x, Array1D< double > &mu, Array1D< double > &sig2)MCMCprivate
evalLogPosterior(Array1D< double > &m)MCMC
FLAGMCMCprivate
fullChain_MCMCprivate
gammaInit_MCMCprivate
getAcceptRatio(double *accrat)MCMC
GetChainDim() constMCMCinline
getChainPropCov(Array2D< double > &propcov)MCMC
getFilename()MCMCinline
getFullChain(Array1D< chainstate > &readchain)MCMCinline
getMode(Array1D< double > &MAPparams)MCMC
getSamples(int burnin, int every, Array2D< double > &samples)MCMC
getSamples(Array2D< double > &samples)MCMC
gradflag_MCMCprivate
gradlogPosterior_MCMCprivate
inDomain(Array1D< double > &m)MCMC
initAdaptSteps(int adaptstart, int adaptstep, int adaptend)MCMC
initAMGamma(double gamma)MCMC
initChainPropCov(Array2D< double > &propcov)MCMC
initChainPropCovDiag(Array1D< double > &sig)MCMC
initDefaults()MCMC
initEpsCov(double eps_cov)MCMC
initEpsMALA(double eps_mala)MCMC
initMethod(string method)MCMC
L_MCMCprivate
lastwrite_MCMCprivate
logPosterior_MCMCprivate
Lower_MCMCprivate
lower_flag_MCMCprivate
MCMC(double(*logposterior)(Array1D< double > &, void *), void *postinfo)MCMC
MCMC()MCMCinline
MCMC(LikelihoodBase &L)MCMC
methodinfo_MCMCprivate
methodInit_MCMCprivate
metricTensor_MCMCprivate
modeState_MCMCprivate
namePrepend_MCMCprivate
namesPrepended()MCMCinline
newMode_MCMCprivate
newModeFound()MCMC
nSubSteps_MCMCprivate
outputinfo_MCMCprivate
outputInit_MCMCprivate
parseBinChain(string filename, Array1D< chainstate > &readchain)MCMC
postInfo_MCMCprivate
printChainSetup()MCMC
probOldNew(Array1D< double > &a, Array1D< double > &b)MCMCprivate
propcovInit_MCMCprivate
propLCov_MCMCprivate
proposalAdaptive(Array1D< double > &m_t, Array1D< double > &m_cand, int t)MCMCprivate
proposalMALA(Array1D< double > &m_t, Array1D< double > &m_cand)MCMCprivate
proposalMMALA(Array1D< double > &m_t, Array1D< double > &m_cand)MCMCprivate
proposalSingleSite(Array1D< double > &m_t, Array1D< double > &m_cand, int dim)MCMCprivate
RandomStateMCMC
resetChainFilename(string filename)MCMCinline
resetChainState()MCMC
runChain(int ncalls, Array1D< double > &chstart)MCMC
runOptim(Array1D< double > &start)MCMC
seed_MCMCprivate
setChainDim(int chdim)MCMC
setDefaultDomain()MCMC
setGradient(void(*gradlogPosterior)(Array1D< double > &, Array1D< double > &, void *))MCMC
setLower(double lower, int i)MCMC
setMetricTensor(void(*metricTensor)(Array1D< double > &, Array2D< double > &, void *))MCMC
setOutputInfo(string outtype, string file, int freq_file, int freq_screen)MCMC
setSeed(int seed)MCMC
setUpper(double upper, int i)MCMC
setWriteFlag(int I)MCMC
tensflag_MCMCprivate
updateMode()MCMCprivate
Upper_MCMCprivate
upper_flag_MCMCprivate
WRITE_FLAGMCMC
writeChainBin(string filename)MCMCprivate
writeChainTxt(string filename)MCMCprivate
writeFullChainTxt(string filename, Array1D< chainstate > fullchain)MCMC
~MCMC()MCMCinline
+ + + + diff --git a/doc/doxygen/html/classMCMC.html b/doc/doxygen/html/classMCMC.html new file mode 100644 index 00000000..af9208cb --- /dev/null +++ b/doc/doxygen/html/classMCMC.html @@ -0,0 +1,2621 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: MCMC Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Markov Chain Monte Carlo class. Implemented single-site and adaptive MCMC algorithms. + More...

+ +

#include <mcmc.h>

+ + + + + + + + + + + +

+Classes

struct  chainstate
 Structure that holds the chain state information. More...
 
struct  methodpar
 A structure to hold method-specific parameters. More...
 
struct  outputpar
 A structure to hold parameters of output specification. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 MCMC (double(*logposterior)(Array1D< double > &, void *), void *postinfo)
 Constructor, given a pointer to logPosterior function, a pointer to additional info, e.g. data and the chain dimaensionality. More...
 
 MCMC ()
 Dummy constructor. More...
 
 MCMC (LikelihoodBase &L)
 
void setWriteFlag (int I)
 
void resetChainState ()
 
 ~MCMC ()
 Destructor. More...
 
void setGradient (void(*gradlogPosterior)(Array1D< double > &, Array1D< double > &, void *))
 Set the gradient function. More...
 
void setMetricTensor (void(*metricTensor)(Array1D< double > &, Array2D< double > &, void *))
 Set the metric tensor function. More...
 
void initDefaults ()
 Set defaults. More...
 
void printChainSetup ()
 Print chain information on the screen. More...
 
void setChainDim (int chdim)
 Set chain dimensionality. More...
 
void initChainPropCov (Array2D< double > &propcov)
 Initialize proposal covariance matrix given as a 2d-array For aMCMC, this matrix is used only before adaptivity starts. More...
 
void initChainPropCovDiag (Array1D< double > &sig)
 Initialize proposal covariance matrix given its 1d-array diagonal For aMCMC, this matrix is used only before adaptivity starts. More...
 
void getChainPropCov (Array2D< double > &propcov)
 Returns proposal covariance matrix. More...
 
void initMethod (string method)
 
void initAdaptSteps (int adaptstart, int adaptstep, int adaptend)
 Initialize adaptivity step parameters for aMCMC. More...
 
void initAMGamma (double gamma)
 Initialize the scaling factor gamma for aMCMC. More...
 
void initEpsCov (double eps_cov)
 Initialize the covariance 'nugget' for aMCMC. More...
 
void initEpsMALA (double eps_mala)
 Initialize epsilon for MALA. More...
 
void setOutputInfo (string outtype, string file, int freq_file, int freq_screen)
 Set output specification, type('txt' or 'bin'), filename, frequency of outputs to the file and to screen. More...
 
void namesPrepended ()
 Set the indicator to confirm that the names of parameters are prepended in the output file. More...
 
string getFilename ()
 Get the name of the chain file. More...
 
void resetChainFilename (string filename)
 Reset to a new chain file. More...
 
void runOptim (Array1D< double > &start)
 The optimization routine. More...
 
void runChain (int ncalls, Array1D< double > &chstart)
 The actual function that generates MCMC. More...
 
void parseBinChain (string filename, Array1D< chainstate > &readchain)
 An auxiliary function to parse the binary file and produce an array of chain-states. More...
 
void writeFullChainTxt (string filename, Array1D< chainstate > fullchain)
 Write an array of chain-states to a file. More...
 
void getFullChain (Array1D< chainstate > &readchain)
 Get full chain as an array of chain-states. More...
 
void appendMAP ()
 Append MAP state to the end. More...
 
double getMode (Array1D< double > &MAPparams)
 Get MAP parameters. More...
 
bool newModeFound ()
 Check to see if a new mode was found during last call to runChain. More...
 
void getAcceptRatio (double *accrat)
 Get the chain's acceptance ratio. More...
 
int GetChainDim () const
 Get the MCMC chain dimensionality. More...
 
double evalLogPosterior (Array1D< double > &m)
 Function to evaluate the log-posterior. More...
 
void evalGradLogPosterior (Array1D< double > &m, Array1D< double > &grads)
 Function to evaluate the gradient of log-posterior. More...
 
void setSeed (int seed)
 Set random generation seed. More...
 
bool inDomain (Array1D< double > &m)
 Check if a point is in the domain. More...
 
void setLower (double lower, int i)
 Set lower bounds. More...
 
void setUpper (double upper, int i)
 Set upper bounds. More...
 
void setDefaultDomain ()
 Set default unbounded domain. More...
 
void getSamples (int burnin, int every, Array2D< double > &samples)
 Get samples of the chain with burnin and thining. More...
 
void getSamples (Array2D< double > &samples)
 Get all samples of the chain. More...
 
+ + + + + +

+Public Attributes

int WRITE_FLAG
 
dsfmt_t RandomState
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Member Functions

void proposalAdaptive (Array1D< double > &m_t, Array1D< double > &m_cand, int t)
 Generating the proposal candidate vector of parameters according to the adaptive MCMC algorithm. More...
 
void proposalSingleSite (Array1D< double > &m_t, Array1D< double > &m_cand, int dim)
 Generating the proposal candidate vector of parameters according to the Single-Site algorithm. More...
 
void proposalMALA (Array1D< double > &m_t, Array1D< double > &m_cand)
 Generating the proposal candidate vector of parameters according to the MALA algorithm. More...
 
void proposalMMALA (Array1D< double > &m_t, Array1D< double > &m_cand)
 Generating the proposal candidate vector of parameters according to the MMALA algorithm. More...
 
double probOldNew (Array1D< double > &a, Array1D< double > &b)
 Evaluate old|new and new|old probabilities. More...
 
double evallogMVN_diag (Array1D< double > &x, Array1D< double > &mu, Array1D< double > &sig2)
 Evaluate MVN. More...
 
void updateMode ()
 Function to update the chain mode, i.e. the MAP location. More...
 
void writeChainTxt (string filename)
 Write the full chain as a text. More...
 
void writeChainBin (string filename)
 Write the full chain as a binary file. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

int FLAG
 
LikelihoodBaseL_
 
int chainDim_
 Void pointer to the posterior info (e.g. data) More...
 
double(* logPosterior_ )(Array1D< double > &, void *)
 Pointer to log-posterior function (of tweaked parameters and a void pointer to any other info) this pointer is set i the constructor to a user-defined function. More...
 
void(* gradlogPosterior_ )(Array1D< double > &, Array1D< double > &, void *)
 
void(* metricTensor_ )(Array1D< double > &, Array2D< double > &, void *)
 
void * postInfo_
 Void pointer to the posterior info (e.g. data) More...
 
Array2D< double > propLCov_
 The Cholesky factor(square-root) of proposal covariance. More...
 
int seed_
 Random seed for MCMC. More...
 
int nSubSteps_
 The number of proposal steps within one MCMC step (=1 for AMCMC, =chaindim for MCMC_SS) More...
 
struct MCMC::methodpar methodinfo_
 
double epsMALA_
 Epsilon for MALA algorithm. More...
 
struct MCMC::outputpar outputinfo_
 
chainstate currState_
 The current chain state. More...
 
chainstate modeState_
 The current MAP state. More...
 
Array1D< chainstatefullChain_
 Array of chain states. More...
 
int lastwrite_
 Indicates up to which state of the chain is already written to files. More...
 
bool namePrepend_
 Indicates up to which state of the chain is already written to files. More...
 
bool newMode_
 Flag to indicate whether a new mode is found during last call to runChain. More...
 
double accRatio_
 Acceptance Ratio of the chain. More...
 
bool gradflag_
 Flag that indicates whether gradient information is given or not. More...
 
bool tensflag_
 Flag that indicates whether tensor information is given or not. More...
 
Array1D< double > Lower_
 Lower bounds. More...
 
Array1D< double > Upper_
 Upper bounds. More...
 
Array1D< int > lower_flag_
 Lower bound existence flags. More...
 
Array1D< int > upper_flag_
 Upper bound existence flags. More...
 
bool chaindimInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool propcovInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool methodInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool outputInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool adaptstepInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool gammaInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool epscovInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
bool epsMalaInit_
 Flag to indicate whether the corresponding parameters are initialized or not. More...
 
string default_method_
 Default. More...
 
double default_gamma_
 Default. More...
 
double default_eps_cov_
 Default. More...
 
double default_eps_mala_
 Default. More...
 
+

Detailed Description

+

Markov Chain Monte Carlo class. Implemented single-site and adaptive MCMC algorithms.

+

Constructor & Destructor Documentation

+ +

◆ MCMC() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
MCMC::MCMC (double(*)(Array1D< double > &, void *) logposterior,
void * postinfo 
)
+
+ +

Constructor, given a pointer to logPosterior function, a pointer to additional info, e.g. data and the chain dimaensionality.

+ +
+
+ +

◆ MCMC() [2/3]

+ +
+
+ + + + + +
+ + + + + + + +
MCMC::MCMC ()
+
+inline
+
+ +

Dummy constructor.

+ +
+
+ +

◆ MCMC() [3/3]

+ +
+
+ + + + + + + + +
MCMC::MCMC (LikelihoodBaseL)
+
+ +
+
+ +

◆ ~MCMC()

+ +
+
+ + + + + +
+ + + + + + + +
MCMC::~MCMC ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ appendMAP()

+ +
+
+ + + + + + + +
void MCMC::appendMAP ()
+
+ +

Append MAP state to the end.

+ +
+
+ +

◆ evalGradLogPosterior()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void MCMC::evalGradLogPosterior (Array1D< double > & m,
Array1D< double > & grads 
)
+
+ +

Function to evaluate the gradient of log-posterior.

+ +
+
+ +

◆ evallogMVN_diag()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
double MCMC::evallogMVN_diag (Array1D< double > & x,
Array1D< double > & mu,
Array1D< double > & sig2 
)
+
+private
+
+ +

Evaluate MVN.

+ +
+
+ +

◆ evalLogPosterior()

+ +
+
+ + + + + + + + +
double MCMC::evalLogPosterior (Array1D< double > & m)
+
+ +

Function to evaluate the log-posterior.

+ +
+
+ +

◆ getAcceptRatio()

+ +
+
+ + + + + + + + +
void MCMC::getAcceptRatio (double * accrat)
+
+ +

Get the chain's acceptance ratio.

+ +
+
+ +

◆ GetChainDim()

+ +
+
+ + + + + +
+ + + + + + + +
int MCMC::GetChainDim () const
+
+inline
+
+ +

Get the MCMC chain dimensionality.

+ +
+
+ +

◆ getChainPropCov()

+ +
+
+ + + + + + + + +
void MCMC::getChainPropCov (Array2D< double > & propcov)
+
+ +

Returns proposal covariance matrix.

+ +
+
+ +

◆ getFilename()

+ +
+
+ + + + + +
+ + + + + + + +
string MCMC::getFilename ()
+
+inline
+
+ +

Get the name of the chain file.

+ +
+
+ +

◆ getFullChain()

+ +
+
+ + + + + +
+ + + + + + + + +
void MCMC::getFullChain (Array1D< chainstate > & readchain)
+
+inline
+
+ +

Get full chain as an array of chain-states.

+ +
+
+ +

◆ getMode()

+ +
+
+ + + + + + + + +
double MCMC::getMode (Array1D< double > & MAPparams)
+
+ +

Get MAP parameters.

+ +
+
+ +

◆ getSamples() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void MCMC::getSamples (int burnin,
int every,
Array2D< double > & samples 
)
+
+ +

Get samples of the chain with burnin and thining.

+ +
+
+ +

◆ getSamples() [2/2]

+ +
+
+ + + + + + + + +
void MCMC::getSamples (Array2D< double > & samples)
+
+ +

Get all samples of the chain.

+ +
+
+ +

◆ inDomain()

+ +
+
+ + + + + + + + +
bool MCMC::inDomain (Array1D< double > & m)
+
+ +

Check if a point is in the domain.

+ +
+
+ +

◆ initAdaptSteps()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void MCMC::initAdaptSteps (int adaptstart,
int adaptstep,
int adaptend 
)
+
+ +

Initialize adaptivity step parameters for aMCMC.

+ +
+
+ +

◆ initAMGamma()

+ +
+
+ + + + + + + + +
void MCMC::initAMGamma (double gamma)
+
+ +

Initialize the scaling factor gamma for aMCMC.

+ +
+
+ +

◆ initChainPropCov()

+ +
+
+ + + + + + + + +
void MCMC::initChainPropCov (Array2D< double > & propcov)
+
+ +

Initialize proposal covariance matrix given as a 2d-array For aMCMC, this matrix is used only before adaptivity starts.

+ +
+
+ +

◆ initChainPropCovDiag()

+ +
+
+ + + + + + + + +
void MCMC::initChainPropCovDiag (Array1D< double > & sig)
+
+ +

Initialize proposal covariance matrix given its 1d-array diagonal For aMCMC, this matrix is used only before adaptivity starts.

+ +
+
+ +

◆ initDefaults()

+ +
+
+ + + + + + + +
void MCMC::initDefaults ()
+
+ +

Set defaults.

+ +
+
+ +

◆ initEpsCov()

+ +
+
+ + + + + + + + +
void MCMC::initEpsCov (double eps_cov)
+
+ +

Initialize the covariance 'nugget' for aMCMC.

+ +
+
+ +

◆ initEpsMALA()

+ +
+
+ + + + + + + + +
void MCMC::initEpsMALA (double eps_mala)
+
+ +

Initialize epsilon for MALA.

+ +
+
+ +

◆ initMethod()

+ +
+
+ + + + + + + + +
void MCMC::initMethod (string method)
+
+ +
+
+ +

◆ namesPrepended()

+ +
+
+ + + + + +
+ + + + + + + +
void MCMC::namesPrepended ()
+
+inline
+
+ +

Set the indicator to confirm that the names of parameters are prepended in the output file.

+ +
+
+ +

◆ newModeFound()

+ +
+
+ + + + + + + +
bool MCMC::newModeFound ()
+
+ +

Check to see if a new mode was found during last call to runChain.

+ +
+
+ +

◆ parseBinChain()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void MCMC::parseBinChain (string filename,
Array1D< chainstate > & readchain 
)
+
+ +

An auxiliary function to parse the binary file and produce an array of chain-states.

+ +
+
+ +

◆ printChainSetup()

+ +
+
+ + + + + + + +
void MCMC::printChainSetup ()
+
+ +

Print chain information on the screen.

+ +
+
+ +

◆ probOldNew()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
double MCMC::probOldNew (Array1D< double > & a,
Array1D< double > & b 
)
+
+private
+
+ +

Evaluate old|new and new|old probabilities.

+ +
+
+ +

◆ proposalAdaptive()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void MCMC::proposalAdaptive (Array1D< double > & m_t,
Array1D< double > & m_cand,
int t 
)
+
+private
+
+ +

Generating the proposal candidate vector of parameters according to the adaptive MCMC algorithm.

+ +
+
+ +

◆ proposalMALA()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void MCMC::proposalMALA (Array1D< double > & m_t,
Array1D< double > & m_cand 
)
+
+private
+
+ +

Generating the proposal candidate vector of parameters according to the MALA algorithm.

+ +
+
+ +

◆ proposalMMALA()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void MCMC::proposalMMALA (Array1D< double > & m_t,
Array1D< double > & m_cand 
)
+
+private
+
+ +

Generating the proposal candidate vector of parameters according to the MMALA algorithm.

+ +
+
+ +

◆ proposalSingleSite()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void MCMC::proposalSingleSite (Array1D< double > & m_t,
Array1D< double > & m_cand,
int dim 
)
+
+private
+
+ +

Generating the proposal candidate vector of parameters according to the Single-Site algorithm.

+ +
+
+ +

◆ resetChainFilename()

+ +
+
+ + + + + +
+ + + + + + + + +
void MCMC::resetChainFilename (string filename)
+
+inline
+
+ +

Reset to a new chain file.

+ +
+
+ +

◆ resetChainState()

+ +
+
+ + + + + + + +
void MCMC::resetChainState ()
+
+ +
+
+ +

◆ runChain()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void MCMC::runChain (int ncalls,
Array1D< double > & chstart 
)
+
+ +

The actual function that generates MCMC.

+ +
+
+ +

◆ runOptim()

+ +
+
+ + + + + + + + +
void MCMC::runOptim (Array1D< double > & start)
+
+ +

The optimization routine.

+ +
+
+ +

◆ setChainDim()

+ +
+
+ + + + + + + + +
void MCMC::setChainDim (int chdim)
+
+ +

Set chain dimensionality.

+ +
+
+ +

◆ setDefaultDomain()

+ +
+
+ + + + + + + +
void MCMC::setDefaultDomain ()
+
+ +

Set default unbounded domain.

+ +
+
+ +

◆ setGradient()

+ +
+
+ + + + + + + + +
void MCMC::setGradient (void(*)(Array1D< double > &, Array1D< double > &, void *) gradlogPosterior)
+
+ +

Set the gradient function.

+ +
+
+ +

◆ setLower()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void MCMC::setLower (double lower,
int i 
)
+
+ +

Set lower bounds.

+ +
+
+ +

◆ setMetricTensor()

+ +
+
+ + + + + + + + +
void MCMC::setMetricTensor (void(*)(Array1D< double > &, Array2D< double > &, void *) metricTensor)
+
+ +

Set the metric tensor function.

+ +
+
+ +

◆ setOutputInfo()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void MCMC::setOutputInfo (string outtype,
string file,
int freq_file,
int freq_screen 
)
+
+ +

Set output specification, type('txt' or 'bin'), filename, frequency of outputs to the file and to screen.

+ +
+
+ +

◆ setSeed()

+ +
+
+ + + + + + + + +
void MCMC::setSeed (int seed)
+
+ +

Set random generation seed.

+ +
+
+ +

◆ setUpper()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void MCMC::setUpper (double upper,
int i 
)
+
+ +

Set upper bounds.

+ +
+
+ +

◆ setWriteFlag()

+ +
+
+ + + + + + + + +
void MCMC::setWriteFlag (int I)
+
+ +
+
+ +

◆ updateMode()

+ +
+
+ + + + + +
+ + + + + + + +
void MCMC::updateMode ()
+
+private
+
+ +

Function to update the chain mode, i.e. the MAP location.

+ +
+
+ +

◆ writeChainBin()

+ +
+
+ + + + + +
+ + + + + + + + +
void MCMC::writeChainBin (string filename)
+
+private
+
+ +

Write the full chain as a binary file.

+ +
+
+ +

◆ writeChainTxt()

+ +
+
+ + + + + +
+ + + + + + + + +
void MCMC::writeChainTxt (string filename)
+
+private
+
+ +

Write the full chain as a text.

+ +
+
+ +

◆ writeFullChainTxt()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void MCMC::writeFullChainTxt (string filename,
Array1D< chainstatefullchain 
)
+
+ +

Write an array of chain-states to a file.

+ +
+
+

Member Data Documentation

+ +

◆ accRatio_

+ +
+
+ + + + + +
+ + + + +
double MCMC::accRatio_
+
+private
+
+ +

Acceptance Ratio of the chain.

+ +
+
+ +

◆ adaptstepInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::adaptstepInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ chainDim_

+ +
+
+ + + + + +
+ + + + +
int MCMC::chainDim_
+
+private
+
+ +

Void pointer to the posterior info (e.g. data)

+

Chain dimensionality

+ +
+
+ +

◆ chaindimInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::chaindimInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ currState_

+ +
+
+ + + + + +
+ + + + +
chainstate MCMC::currState_
+
+private
+
+ +

The current chain state.

+ +
+
+ +

◆ default_eps_cov_

+ +
+
+ + + + + +
+ + + + +
double MCMC::default_eps_cov_
+
+private
+
+ +

Default.

+ +
+
+ +

◆ default_eps_mala_

+ +
+
+ + + + + +
+ + + + +
double MCMC::default_eps_mala_
+
+private
+
+ +

Default.

+ +
+
+ +

◆ default_gamma_

+ +
+
+ + + + + +
+ + + + +
double MCMC::default_gamma_
+
+private
+
+ +

Default.

+ +
+
+ +

◆ default_method_

+ +
+
+ + + + + +
+ + + + +
string MCMC::default_method_
+
+private
+
+ +

Default.

+ +
+
+ +

◆ epscovInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::epscovInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ epsMALA_

+ +
+
+ + + + + +
+ + + + +
double MCMC::epsMALA_
+
+private
+
+ +

Epsilon for MALA algorithm.

+ +
+
+ +

◆ epsMalaInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::epsMalaInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ FLAG

+ +
+
+ + + + + +
+ + + + +
int MCMC::FLAG
+
+private
+
+ +
+
+ +

◆ fullChain_

+ +
+
+ + + + + +
+ + + + +
Array1D<chainstate> MCMC::fullChain_
+
+private
+
+ +

Array of chain states.

+ +
+
+ +

◆ gammaInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::gammaInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ gradflag_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::gradflag_
+
+private
+
+ +

Flag that indicates whether gradient information is given or not.

+ +
+
+ +

◆ gradlogPosterior_

+ +
+
+ + + + + +
+ + + + +
void(* MCMC::gradlogPosterior_) (Array1D< double > &, Array1D< double > &, void *)
+
+private
+
+ +
+
+ +

◆ L_

+ +
+
+ + + + + +
+ + + + +
LikelihoodBase* MCMC::L_
+
+private
+
+ +
+
+ +

◆ lastwrite_

+ +
+
+ + + + + +
+ + + + +
int MCMC::lastwrite_
+
+private
+
+ +

Indicates up to which state of the chain is already written to files.

+ +
+
+ +

◆ logPosterior_

+ +
+
+ + + + + +
+ + + + +
double(* MCMC::logPosterior_) (Array1D< double > &, void *)
+
+private
+
+ +

Pointer to log-posterior function (of tweaked parameters and a void pointer to any other info) this pointer is set i the constructor to a user-defined function.

+ +
+
+ +

◆ Lower_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> MCMC::Lower_
+
+private
+
+ +

Lower bounds.

+ +
+
+ +

◆ lower_flag_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> MCMC::lower_flag_
+
+private
+
+ +

Lower bound existence flags.

+ +
+
+ +

◆ methodinfo_

+ +
+
+ + + + + +
+ + + + +
struct MCMC::methodpar MCMC::methodinfo_
+
+private
+
+ +
+
+ +

◆ methodInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::methodInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ metricTensor_

+ +
+
+ + + + + +
+ + + + +
void(* MCMC::metricTensor_) (Array1D< double > &, Array2D< double > &, void *)
+
+private
+
+ +
+
+ +

◆ modeState_

+ +
+
+ + + + + +
+ + + + +
chainstate MCMC::modeState_
+
+private
+
+ +

The current MAP state.

+ +
+
+ +

◆ namePrepend_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::namePrepend_
+
+private
+
+ +

Indicates up to which state of the chain is already written to files.

+ +
+
+ +

◆ newMode_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::newMode_
+
+private
+
+ +

Flag to indicate whether a new mode is found during last call to runChain.

+ +
+
+ +

◆ nSubSteps_

+ +
+
+ + + + + +
+ + + + +
int MCMC::nSubSteps_
+
+private
+
+ +

The number of proposal steps within one MCMC step (=1 for AMCMC, =chaindim for MCMC_SS)

+ +
+
+ +

◆ outputinfo_

+ +
+
+ + + + + +
+ + + + +
struct MCMC::outputpar MCMC::outputinfo_
+
+private
+
+ +
+
+ +

◆ outputInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::outputInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ postInfo_

+ +
+
+ + + + + +
+ + + + +
void* MCMC::postInfo_
+
+private
+
+ +

Void pointer to the posterior info (e.g. data)

+ +
+
+ +

◆ propcovInit_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::propcovInit_
+
+private
+
+ +

Flag to indicate whether the corresponding parameters are initialized or not.

+ +
+
+ +

◆ propLCov_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> MCMC::propLCov_
+
+private
+
+ +

The Cholesky factor(square-root) of proposal covariance.

+ +
+
+ +

◆ RandomState

+ +
+
+ + + + +
dsfmt_t MCMC::RandomState
+
+ +
+
+ +

◆ seed_

+ +
+
+ + + + + +
+ + + + +
int MCMC::seed_
+
+private
+
+ +

Random seed for MCMC.

+ +
+
+ +

◆ tensflag_

+ +
+
+ + + + + +
+ + + + +
bool MCMC::tensflag_
+
+private
+
+ +

Flag that indicates whether tensor information is given or not.

+ +
+
+ +

◆ Upper_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> MCMC::Upper_
+
+private
+
+ +

Upper bounds.

+ +
+
+ +

◆ upper_flag_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> MCMC::upper_flag_
+
+private
+
+ +

Upper bound existence flags.

+ +
+
+ +

◆ WRITE_FLAG

+ +
+
+ + + + +
int MCMC::WRITE_FLAG
+
+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classMrv-members.html b/doc/doxygen/html/classMrv-members.html new file mode 100644 index 00000000..949938fc --- /dev/null +++ b/doc/doxygen/html/classMrv-members.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Mrv Member List
+
+
+ +

This is the complete list of members for Mrv, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
computeMoments(Array2D< double > &funcCf, Array1D< double > &fcnMean, Array1D< double > &fcnStd, bool covFlag, Array2D< double > &fcnCov)Mrv
evalMultiPC(Array2D< double > &xiSam, Array2D< double > &multiPCcf)Mrv
getBounds(Array1D< double > &lower, Array1D< double > &upper)Mrv
getMultiPCcf(Array1D< double > &rvParams)Mrv
getPCTermId(Array1D< int > &pctermid)Mrvinline
getPDim()Mrvinline
mcParam(Array2D< double > &multiPCcf, int nsam)Mrv
Mrv(int ndim, string pdfType, Array1D< int > rndInd, int order, string pctype)Mrv
nDim_Mrvprivate
nPC_Mrvprivate
order_Mrvprivate
Parametrize()Mrv
paramId_Mrvprivate
pcModel_Mrvprivate
pctermId_Mrvprivate
pcType_Mrvprivate
pdfType_Mrvprivate
pDim_Mrvprivate
propMC(Array2D< double >(*forwardFcn)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array2D< double > &fixindnom, void *funcinfo, Array2D< double > &multiPCcf, Array2D< double > &x, int nsam)Mrv
propNISP(Array2D< double >(*forwardFcn)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array2D< double > &fixindnom, void *funcinfo, Array2D< double > &multiPCcf, Array2D< double > &x)Mrv
quadParam(Array2D< double > &multiPCcf)Mrv
rDim_Mrvprivate
rndInd_Mrvprivate
~Mrv()Mrvinline
+ + + + diff --git a/doc/doxygen/html/classMrv.html b/doc/doxygen/html/classMrv.html new file mode 100644 index 00000000..1963bf7e --- /dev/null +++ b/doc/doxygen/html/classMrv.html @@ -0,0 +1,844 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Mrv Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

multivariate RV parameterized by PC expansions + More...

+ +

#include <mrv.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Mrv (int ndim, string pdfType, Array1D< int > rndInd, int order, string pctype)
 Constructor with dimensionality, pdftype, randomized parameter indices, order, and pctype. More...
 
 ~Mrv ()
 Destructor. More...
 
int Parametrize ()
 Parameterization bookkeeping (i.e. alpha corresponds to certain parameter lambda and certain PC term) More...
 
void getBounds (Array1D< double > &lower, Array1D< double > &upper)
 Get bounds on parameters. More...
 
int getPDim ()
 Get dimensionailty of parameterization. More...
 
Array2D< double > getMultiPCcf (Array1D< double > &rvParams)
 Given parameters of representation, fold them in a 2d-array of PC coefficients for convenience. More...
 
Array2D< double > evalMultiPC (Array2D< double > &xiSam, Array2D< double > &multiPCcf)
 Evaluate at multivariate PC at given germ samples for given coefficient matrix. More...
 
Array2D< double > mcParam (Array2D< double > &multiPCcf, int nsam)
 Random-sample all parameters given coefficient matrix. More...
 
Array2D< double > quadParam (Array2D< double > &multiPCcf)
 Quadrature-sample all parameters given coefficient matrix. More...
 
Array2D< double > propNISP (Array2D< double >(*forwardFcn)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array2D< double > &fixindnom, void *funcinfo, Array2D< double > &multiPCcf, Array2D< double > &x)
 Propagate the multivariate RV with given coefficeints through a given function at given values x. More...
 
Array2D< double > propMC (Array2D< double >(*forwardFcn)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array2D< double > &fixindnom, void *funcinfo, Array2D< double > &multiPCcf, Array2D< double > &x, int nsam)
 Sample values of a given function given input coefficeint matrix. More...
 
void computeMoments (Array2D< double > &funcCf, Array1D< double > &fcnMean, Array1D< double > &fcnStd, bool covFlag, Array2D< double > &fcnCov)
 Compute moments given coefficent matrix. More...
 
void getPCTermId (Array1D< int > &pctermid)
 Get PC term ID. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

Array1D< int > rndInd_
 Randomized parameters indices. More...
 
Array1D< int > paramId_
 For a given parameterization, id the corresponding physical parameter lambda. More...
 
Array1D< int > pctermId_
 For a given parameterization, id the PC term/order for the corresponding parameter representation. More...
 
string pdfType_
 PDF type ('pct', 'pci' or 'full') More...
 
string pcType_
 PC type (see pce library for options) More...
 
int pDim_
 Number of parameters in alpha parameterization. More...
 
int rDim_
 Number of randomized parameters. More...
 
int nDim_
 Number of physical parameters lambda. More...
 
int order_
 Order of function PC representation. More...
 
int nPC_
 Number of PC parameters for each independent component. More...
 
PCSetpcModel_
 Pointer to the corresponding PC object. More...
 
+

Detailed Description

+

multivariate RV parameterized by PC expansions

+

Constructor & Destructor Documentation

+ +

◆ Mrv()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Mrv::Mrv (int ndim,
string pdfType,
Array1D< int > rndInd,
int order,
string pctype 
)
+
+ +

Constructor with dimensionality, pdftype, randomized parameter indices, order, and pctype.

+ +
+
+ +

◆ ~Mrv()

+ +
+
+ + + + + +
+ + + + + + + +
Mrv::~Mrv ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ computeMoments()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Mrv::computeMoments (Array2D< double > & funcCf,
Array1D< double > & fcnMean,
Array1D< double > & fcnStd,
bool covFlag,
Array2D< double > & fcnCov 
)
+
+ +

Compute moments given coefficent matrix.

+ +
+
+ +

◆ evalMultiPC()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D< double > Mrv::evalMultiPC (Array2D< double > & xiSam,
Array2D< double > & multiPCcf 
)
+
+ +

Evaluate at multivariate PC at given germ samples for given coefficient matrix.

+ +
+
+ +

◆ getBounds()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Mrv::getBounds (Array1D< double > & lower,
Array1D< double > & upper 
)
+
+ +

Get bounds on parameters.

+
Note
Useful when some parameters forced to be positive to make use of invariance
+ +
+
+ +

◆ getMultiPCcf()

+ +
+
+ + + + + + + + +
Array2D< double > Mrv::getMultiPCcf (Array1D< double > & rvParams)
+
+ +

Given parameters of representation, fold them in a 2d-array of PC coefficients for convenience.

+ +
+
+ +

◆ getPCTermId()

+ +
+
+ + + + + +
+ + + + + + + + +
void Mrv::getPCTermId (Array1D< int > & pctermid)
+
+inline
+
+ +

Get PC term ID.

+ +
+
+ +

◆ getPDim()

+ +
+
+ + + + + +
+ + + + + + + +
int Mrv::getPDim ()
+
+inline
+
+ +

Get dimensionailty of parameterization.

+ +
+
+ +

◆ mcParam()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D< double > Mrv::mcParam (Array2D< double > & multiPCcf,
int nsam 
)
+
+ +

Random-sample all parameters given coefficient matrix.

+ +
+
+ +

◆ Parametrize()

+ +
+
+ + + + + + + +
int Mrv::Parametrize ()
+
+ +

Parameterization bookkeeping (i.e. alpha corresponds to certain parameter lambda and certain PC term)

+ +
+
+ +

◆ propMC()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D< double > Mrv::propMC (Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) forwardFcn,
Array2D< double > & fixindnom,
void * funcinfo,
Array2D< double > & multiPCcf,
Array2D< double > & x,
int nsam 
)
+
+ +

Sample values of a given function given input coefficeint matrix.

+ +
+
+ +

◆ propNISP()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D< double > Mrv::propNISP (Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) forwardFcn,
Array2D< double > & fixindnom,
void * funcinfo,
Array2D< double > & multiPCcf,
Array2D< double > & x 
)
+
+ +

Propagate the multivariate RV with given coefficeints through a given function at given values x.

+ +
+
+ +

◆ quadParam()

+ +
+
+ + + + + + + + +
Array2D< double > Mrv::quadParam (Array2D< double > & multiPCcf)
+
+ +

Quadrature-sample all parameters given coefficient matrix.

+ +
+
+

Member Data Documentation

+ +

◆ nDim_

+ +
+
+ + + + + +
+ + + + +
int Mrv::nDim_
+
+private
+
+ +

Number of physical parameters lambda.

+ +
+
+ +

◆ nPC_

+ +
+
+ + + + + +
+ + + + +
int Mrv::nPC_
+
+private
+
+ +

Number of PC parameters for each independent component.

+ +
+
+ +

◆ order_

+ +
+
+ + + + + +
+ + + + +
int Mrv::order_
+
+private
+
+ +

Order of function PC representation.

+ +
+
+ +

◆ paramId_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> Mrv::paramId_
+
+private
+
+ +

For a given parameterization, id the corresponding physical parameter lambda.

+ +
+
+ +

◆ pcModel_

+ +
+
+ + + + + +
+ + + + +
PCSet* Mrv::pcModel_
+
+private
+
+ +

Pointer to the corresponding PC object.

+ +
+
+ +

◆ pctermId_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> Mrv::pctermId_
+
+private
+
+ +

For a given parameterization, id the PC term/order for the corresponding parameter representation.

+ +
+
+ +

◆ pcType_

+ +
+
+ + + + + +
+ + + + +
string Mrv::pcType_
+
+private
+
+ +

PC type (see pce library for options)

+ +
+
+ +

◆ pdfType_

+ +
+
+ + + + + +
+ + + + +
string Mrv::pdfType_
+
+private
+
+ +

PDF type ('pct', 'pci' or 'full')

+ +
+
+ +

◆ pDim_

+ +
+
+ + + + + +
+ + + + +
int Mrv::pDim_
+
+private
+
+ +

Number of parameters in alpha parameterization.

+ +
+
+ +

◆ rDim_

+ +
+
+ + + + + +
+ + + + +
int Mrv::rDim_
+
+private
+
+ +

Number of randomized parameters.

+ +
+
+ +

◆ rndInd_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> Mrv::rndInd_
+
+private
+
+ +

Randomized parameters indices.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classMyException-members.html b/doc/doxygen/html/classMyException-members.html new file mode 100644 index 00000000..cfa8cdb5 --- /dev/null +++ b/doc/doxygen/html/classMyException-members.html @@ -0,0 +1,61 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
MyException Member List
+
+
+ +

This is the complete list of members for MyException, including all inherited members.

+ + + + + + +
error_MyExceptionprivate
MyException(const char *errormessage)MyExceptioninline
MyException(const std::string &errormessage)MyExceptioninline
what() constMyExceptioninline
~MyException()MyExceptioninlinevirtual
+ + + + diff --git a/doc/doxygen/html/classMyException.html b/doc/doxygen/html/classMyException.html new file mode 100644 index 00000000..6ec751ee --- /dev/null +++ b/doc/doxygen/html/classMyException.html @@ -0,0 +1,241 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: MyException Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
MyException Class Reference
+
+
+ +

#include <MyException.h>

+
+Inheritance diagram for MyException:
+
+
+ + + +
+ + + + + + + + + + + + + + +

+Public Member Functions

 MyException (const char *errormessage)
 Construct an exception using a C-style character string. More...
 
 MyException (const std::string &errormessage)
 Construct an exception using a C++-style string. More...
 
virtual ~MyException () throw ()
 Destroy. More...
 
const char * what () const throw ()
 What's going on? More...
 
+ + + +

+Private Attributes

std::string error_
 
+

Detailed Description

+

Just an example exception - feel free to override this.

+

Constructor & Destructor Documentation

+ +

◆ MyException() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
MyException::MyException (const char * errormessage)
+
+inline
+
+ +

Construct an exception using a C-style character string.

+ +
+
+ +

◆ MyException() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
MyException::MyException (const std::string & errormessage)
+
+inline
+
+ +

Construct an exception using a C++-style string.

+ +
+
+ +

◆ ~MyException()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + +
virtual MyException::~MyException ()
throw (
)
+
+inlinevirtual
+
+ +

Destroy.

+ +
+
+

Member Function Documentation

+ +

◆ what()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + +
const char* MyException::what () const
throw (
)
+
+inline
+
+ +

What's going on?

+

This function is not permitted to throw exceptions.

+ +
+
+

Member Data Documentation

+ +

◆ error_

+ +
+
+ + + + + +
+ + + + +
std::string MyException::error_
+
+private
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classMyException.png b/doc/doxygen/html/classMyException.png new file mode 100644 index 00000000..b97b6527 Binary files /dev/null and b/doc/doxygen/html/classMyException.png differ diff --git a/doc/doxygen/html/classObject-members.html b/doc/doxygen/html/classObject-members.html new file mode 100644 index 00000000..f2dbd4c6 --- /dev/null +++ b/doc/doxygen/html/classObject-members.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Object Member List
+
+
+ +

This is the complete list of members for Object, including all inherited members.

+ + + + + + + + + +
ConstRefPtr classObjectfriend
Object()Objectinline
reference_count() constObjectinline
reference_grab() constObjectinlineprotected
reference_release() constObjectinlineprotected
RefPtr classObjectfriend
refs_Objectmutableprivate
~Object()Objectinlinevirtual
+ + + + diff --git a/doc/doxygen/html/classObject.html b/doc/doxygen/html/classObject.html new file mode 100644 index 00000000..3a8c159d --- /dev/null +++ b/doc/doxygen/html/classObject.html @@ -0,0 +1,320 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Object Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

#include <Object.h>

+
+Inheritance diagram for Object:
+
+
+ + +XMLAttributeList +XMLElement +XMLParser +XMLExpatParser + +
+ + + + + + + + + + + +

+Public Member Functions

 Object ()
 Construct a new reference counted object with a zero reference count. More...
 
virtual ~Object ()
 Destroy this object. More...
 
long int reference_count () const
 Returns the number of references that are held to this object. More...
 
+ + + + + +

+Protected Member Functions

long int reference_grab () const
 
long int reference_release () const
 
+ + + +

+Private Attributes

long int refs_
 
+ + + + + + + +

+Friends

template<class T >
class RefPtr
 
template<class T >
class ConstRefPtr
 
+

Detailed Description

+

Base class for reference counted objects.

+

Part of the Particle Simulation Toolkit (pst)

+

The "friend" classes "RefPtr" and "ConstRefPtr" take care of the reference counting and garbage collection. This means that it should be safe to create an array of reference counted objects, as long as you do not assign a reference counted pointer to any at the entries in the array at any time.

+

Constructor & Destructor Documentation

+ +

◆ Object()

+ +
+
+ + + + + +
+ + + + + + + +
Object::Object ()
+
+inline
+
+ +

Construct a new reference counted object with a zero reference count.

+ +
+
+ +

◆ ~Object()

+ +
+
+ + + + + +
+ + + + + + + +
virtual Object::~Object ()
+
+inlinevirtual
+
+ +

Destroy this object.

+ +
+
+

Member Function Documentation

+ +

◆ reference_count()

+ +
+
+ + + + + +
+ + + + + + + +
long int Object::reference_count () const
+
+inline
+
+ +

Returns the number of references that are held to this object.

+ +
+
+ +

◆ reference_grab()

+ +
+
+ + + + + +
+ + + + + + + +
long int Object::reference_grab () const
+
+inlineprotected
+
+

Enables the friends of the class to increment and decrement the reference count.

+ +
+
+ +

◆ reference_release()

+ +
+
+ + + + + +
+ + + + + + + +
long int Object::reference_release () const
+
+inlineprotected
+
+ +
+
+

Friends And Related Function Documentation

+ +

◆ ConstRefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class ConstRefPtr
+
+friend
+
+ +
+
+ +

◆ RefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class RefPtr
+
+friend
+
+ +
+
+

Member Data Documentation

+ +

◆ refs_

+ +
+
+ + + + + +
+ + + + +
long int Object::refs_
+
+mutableprivate
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classObject.png b/doc/doxygen/html/classObject.png new file mode 100644 index 00000000..cf6e2cf7 Binary files /dev/null and b/doc/doxygen/html/classObject.png differ diff --git a/doc/doxygen/html/classPCBasis-members.html b/doc/doxygen/html/classPCBasis-members.html new file mode 100644 index 00000000..01cf002e --- /dev/null +++ b/doc/doxygen/html/classPCBasis-members.html @@ -0,0 +1,98 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
PCBasis Member List
+
+
+ +

This is the complete list of members for PCBasis, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
alpha_PCBasisprivate
beta_PCBasisprivate
Eval1dBasisAtCustPoints(Array2D< double > &psi, int kord, const Array1D< double > &custPoints)PCBasis
Eval1dBasisAtQuadPoints()PCBasis
Eval1dDerivBasisAtCustPoints(Array2D< double > &dpsi, int kord, const Array1D< double > &custPoints)PCBasis
Eval1dNormSq(int kord)PCBasisprivate
Eval1dNormSq_Exact(int kord)PCBasis
Eval2ndDerivBasis(const double &xi, Array1D< double > &ddP)PCBasis
Eval2ndDerivCustPoints(Array2D< double > &psi, int kord, Array1D< double > &custPoints)PCBasis
EvalBasis(const double &xi, Array1D< double > &basisEvals) constPCBasis
EvalBasis(const double &xi, const int kord, double *basisEvals) constPCBasis
EvalDerivBasis(const double &xi, Array1D< double > &basisDEvals)PCBasis
Get1dNormsSq(Array1D< double > &psi1dSq) constPCBasisinline
Get1dNormsSqExact(Array1D< double > &psi1dSqExact) constPCBasisinline
GetAlpha() constPCBasisinline
GetBasisAtQuadPoints(Array2D< double > &psi1d) constPCBasisinline
GetBeta() constPCBasisinline
GetPCType() constPCBasisinline
GetQuadIndices(Array2D< int > &quadIndices) constPCBasisinline
GetQuadPoints(Array2D< double > &quadPoints) constPCBasisinline
GetQuadRule(Array2D< double > &qPoints, Array1D< double > &qWeights, Array2D< int > &qIndices)PCBasis
GetQuadWeights(Array1D< double > &quadWeights) constPCBasisinline
GetRandSample(Array1D< double > &randSamples)PCBasis
GetRandSample(double *randSamples, const int &nSamp)PCBasis
GetSeed() constPCBasisinline
Init1dQuadPoints(int qdpts)PCBasis
maxord_PCBasisprivate
narg_PCBasisprivate
NormSq_Exact(int kord)PCBasisprivate
PCBasis(const string type="LU", const double alpha=0.0, const double betta=1.0, const int maxord=10)PCBasis
PCBasis(const PCBasis &obj)PCBasisinlineprivate
psi1d_PCBasisprivate
psi1dSq_PCBasisprivate
psi1dSqExact_PCBasisprivate
quadIndices_PCBasisprivate
quadPoints_PCBasisprivate
quadWeights_PCBasisprivate
rnstate_PCBasisprivate
rSeed_PCBasisprivate
SeedRandNumGen(const int &seed)PCBasis
type_PCBasisprivate
~PCBasis()PCBasisinline
+ + + + diff --git a/doc/doxygen/html/classPCBasis.html b/doc/doxygen/html/classPCBasis.html new file mode 100644 index 00000000..fca3a7bf --- /dev/null +++ b/doc/doxygen/html/classPCBasis.html @@ -0,0 +1,1358 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCBasis Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Contains all basis type specific definitions and operations needed to generate a PCSet. + More...

+ +

#include <PCBasis.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 PCBasis (const string type="LU", const double alpha=0.0, const double betta=1.0, const int maxord=10)
 Constructor: initializes the univariate basis type and order. More...
 
 ~PCBasis ()
 Destructor. More...
 
void Init1dQuadPoints (int qdpts)
 Initialize the quadrature points and weights and store the information in arrays quadPoints_, quadWeights_,quadIndices_. More...
 
void Eval1dBasisAtQuadPoints ()
 Evaluate polynomial 1d basis functions at quadrature points and store in the private variable psi1d_. More...
 
void Eval1dBasisAtCustPoints (Array2D< double > &psi, int kord, const Array1D< double > &custPoints)
 Evaluate polynomial 1d basis functions up to the order kord at custom points given by an array custPoints Returns the evaluations in the first argument psi, where the number of rows are the number of points, and columns correspond to successive orders. More...
 
double EvalBasis (const double &xi, Array1D< double > &basisEvals) const
 Evaluate 1d basis functions for the given value of random variable xi. Return the value of the basis functions for all orders in the passed Array1D array (indexed by their order), also returns the highest-order value. More...
 
double EvalBasis (const double &xi, const int kord, double *basisEvals) const
 Evaluate 1d basis functions for the given value of random variable xi. Return the value of the basis functions for all orders in the passed double * array (indexed by their order), also returns the highest-order value. More...
 
void Eval1dNormSq_Exact (int kord)
 Evaluate the norms (squared) of the basis functions exactly and stores in the private array psi1dSqExact_. More...
 
void EvalDerivBasis (const double &xi, Array1D< double > &basisDEvals)
 Evaluate derivative of 1d non-normalized Legendre basis. More...
 
void Eval1dDerivBasisAtCustPoints (Array2D< double > &dpsi, int kord, const Array1D< double > &custPoints)
 
void Eval2ndDerivBasis (const double &xi, Array1D< double > &ddP)
 
void Eval2ndDerivCustPoints (Array2D< double > &psi, int kord, Array1D< double > &custPoints)
 
void Get1dNormsSq (Array1D< double > &psi1dSq) const
 Get the norms-squared of the basis functions. Returns the values for each basis function in the passed Array1D array. More...
 
void Get1dNormsSqExact (Array1D< double > &psi1dSqExact) const
 Get the analytic norms-squared of the basis functions. Returns the values for each basis function in the passed Array1D array. More...
 
void GetRandSample (Array1D< double > &randSamples)
 Get samples of the random variables associated with the current PC basis functions and return them in the 1D array randSamples. Take as many samples as the length of the array randSamples. More...
 
void GetRandSample (double *randSamples, const int &nSamp)
 Get nSamp samples of the random variables associated with the current PC basis functions and return them in the double* randSamples. More...
 
int GetSeed () const
 Get the random number generator seed. More...
 
void SeedRandNumGen (const int &seed)
 Function to (re)seed the random number generator used to sample the Basis functions. More...
 
void GetQuadRule (Array2D< double > &qPoints, Array1D< double > &qWeights, Array2D< int > &qIndices)
 Get the quadrature integration information. More...
 
void GetQuadPoints (Array2D< double > &quadPoints) const
 Get the quadrature points in the passed Array2D array. More...
 
void GetQuadWeights (Array1D< double > &quadWeights) const
 Get the quadrature weights in the passed Array1D array. More...
 
void GetQuadIndices (Array2D< int > &quadIndices) const
 Get the quadrature points' indices in the passed Array1D array. More...
 
void GetBasisAtQuadPoints (Array2D< double > &psi1d) const
 Get the basis values at quadrature points in the passed Array2D array. More...
 
string GetPCType () const
 Get the PC type. More...
 
double GetAlpha () const
 Get the value of the parameter alpha. More...
 
double GetBeta () const
 Get the value of the parameter beta. More...
 
+ + + + + + + + + + +

+Private Member Functions

 PCBasis (const PCBasis &obj)
 Dummy default constructor, which should not be used as it is not well defined Therefore we make it private so it is not accessible. More...
 
void Eval1dNormSq (int kord)
 Evaluate the norms (squared) of the basis functions and stores in the private array psi1dSq_. More...
 
double NormSq_Exact (int kord)
 Evaluate 1d norm of order kord exactly. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

string type_
 String indicator of type of basis functions used. More...
 
Array2D< double > quadPoints_
 Array to store quadrature points. More...
 
Array1D< double > quadWeights_
 Array to store quadrature weights. More...
 
Array2D< int > quadIndices_
 Array to store quadrature point indexing; useful only for nested rules. More...
 
Array2D< double > psi1d_
 Array to store basis functions evaluated at quadrature points for each order: psi1d_(iqp,iord) contains the value of the polynomial chaos basis of order iord at the location of quadrature point iqp. More...
 
Array1D< double > psi1dSq_
 Array with the norms squared of the 1D basis functions for each order. More...
 
Array1D< double > psi1dSqExact_
 Array with the exact norms squared of the 1D basis functions for each order. More...
 
int maxord_
 Maximal order of any dimension. More...
 
int narg_
 Number of parameters to specify the basis. More...
 
double alpha_
 Parameter alpha for PCs that require a parameter (GLG,SW,JB) More...
 
double beta_
 Parameter beta for PCs that require two parameters (SW,JB) More...
 
dsfmt_t rnstate_
 Random sequence state for dsfmt. More...
 
int rSeed_
 The seed used for the random number generators that sample the xi's in the basis functions. More...
 
+

Detailed Description

+

Contains all basis type specific definitions and operations needed to generate a PCSet.

+

Constructor & Destructor Documentation

+ +

◆ PCBasis() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PCBasis::PCBasis (const string type = "LU",
const double alpha = 0.0,
const double betta = 1.0,
const int maxord = 10 
)
+
+ +

Constructor: initializes the univariate basis type and order.

+

Currently, the only valid types are Hermite-Gaussian, denoted with "HG", Legendre-Uniform, denoted with "LU", or Laguerre-Gamma, denoted with "LG". (Where the shape parameter for the Gamma distribution is alpha + 1 = 2)

Todo:
At some point, the basis selection should probably be implemented in a more elegant way using base and inherited classes. For the time being, Hermite-Gaussian or Legendre-Uniform will probably be the most commonly used cases. The parameters alpha and betta are relevant only for GLG, SW and JB chaoses
+
Note
Maxord specifies the maximal order up to which the computations are performed
+ +
+
+ +

◆ ~PCBasis()

+ +
+
+ + + + + +
+ + + + + + + +
PCBasis::~PCBasis ()
+
+inline
+
+ +

Destructor.

+ +
+
+ +

◆ PCBasis() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
PCBasis::PCBasis (const PCBasisobj)
+
+inlineprivate
+
+ +

Dummy default constructor, which should not be used as it is not well defined Therefore we make it private so it is not accessible.

+
Note
All parameters are intialized to dummy values. Dummy copy constructor, which should not be used as it is currently not well defined. Therefore we make it private so it is not accessible.
+
+I am not sure actually whether the initialization performed below is legal as it requires access to private data members of the class that is passed in.
+ +
+
+

Member Function Documentation

+ +

◆ Eval1dBasisAtCustPoints()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCBasis::Eval1dBasisAtCustPoints (Array2D< double > & psi,
int kord,
const Array1D< double > & custPoints 
)
+
+ +

Evaluate polynomial 1d basis functions up to the order kord at custom points given by an array custPoints Returns the evaluations in the first argument psi, where the number of rows are the number of points, and columns correspond to successive orders.

+ +
+
+ +

◆ Eval1dBasisAtQuadPoints()

+ +
+
+ + + + + + + +
void PCBasis::Eval1dBasisAtQuadPoints ()
+
+ +

Evaluate polynomial 1d basis functions at quadrature points and store in the private variable psi1d_.

+ +
+
+ +

◆ Eval1dDerivBasisAtCustPoints()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCBasis::Eval1dDerivBasisAtCustPoints (Array2D< double > & dpsi,
int kord,
const Array1D< double > & custPoints 
)
+
+ +
+
+ +

◆ Eval1dNormSq()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::Eval1dNormSq (int kord)
+
+private
+
+ +

Evaluate the norms (squared) of the basis functions and stores in the private array psi1dSq_.

+ +
+
+ +

◆ Eval1dNormSq_Exact()

+ +
+
+ + + + + + + + +
void PCBasis::Eval1dNormSq_Exact (int kord)
+
+ +

Evaluate the norms (squared) of the basis functions exactly and stores in the private array psi1dSqExact_.

+ +
+
+ +

◆ Eval2ndDerivBasis()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCBasis::Eval2ndDerivBasis (const double & xi,
Array1D< double > & ddP 
)
+
+ +
+
+ +

◆ Eval2ndDerivCustPoints()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCBasis::Eval2ndDerivCustPoints (Array2D< double > & psi,
int kord,
Array1D< double > & custPoints 
)
+
+ +
+
+ +

◆ EvalBasis() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double PCBasis::EvalBasis (const double & xi,
Array1D< double > & basisEvals 
) const
+
+ +

Evaluate 1d basis functions for the given value of random variable xi. Return the value of the basis functions for all orders in the passed Array1D array (indexed by their order), also returns the highest-order value.

+
Note
For custom 'pdf' option, a file containing the polynomial recursion coefficients, called 'ab.dat', is required.
+
Todo:
Import the recursion coefficients in a more friendly fashion.
+ +
+
+ +

◆ EvalBasis() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double PCBasis::EvalBasis (const double & xi,
const int kord,
double * basisEvals 
) const
+
+ +

Evaluate 1d basis functions for the given value of random variable xi. Return the value of the basis functions for all orders in the passed double * array (indexed by their order), also returns the highest-order value.

+ +
+
+ +

◆ EvalDerivBasis()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCBasis::EvalDerivBasis (const double & xi,
Array1D< double > & basisDEvals 
)
+
+ +

Evaluate derivative of 1d non-normalized Legendre basis.

+ +
+
+ +

◆ Get1dNormsSq()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::Get1dNormsSq (Array1D< double > & psi1dSq) const
+
+inline
+
+ +

Get the norms-squared of the basis functions. Returns the values for each basis function in the passed Array1D array.

+ +
+
+ +

◆ Get1dNormsSqExact()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::Get1dNormsSqExact (Array1D< double > & psi1dSqExact) const
+
+inline
+
+ +

Get the analytic norms-squared of the basis functions. Returns the values for each basis function in the passed Array1D array.

+ +
+
+ +

◆ GetAlpha()

+ +
+
+ + + + + +
+ + + + + + + +
double PCBasis::GetAlpha () const
+
+inline
+
+ +

Get the value of the parameter alpha.

+ +
+
+ +

◆ GetBasisAtQuadPoints()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::GetBasisAtQuadPoints (Array2D< double > & psi1d) const
+
+inline
+
+ +

Get the basis values at quadrature points in the passed Array2D array.

+ +
+
+ +

◆ GetBeta()

+ +
+
+ + + + + +
+ + + + + + + +
double PCBasis::GetBeta () const
+
+inline
+
+ +

Get the value of the parameter beta.

+ +
+
+ +

◆ GetPCType()

+ +
+
+ + + + + +
+ + + + + + + +
string PCBasis::GetPCType () const
+
+inline
+
+ +

Get the PC type.

+ +
+
+ +

◆ GetQuadIndices()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::GetQuadIndices (Array2D< int > & quadIndices) const
+
+inline
+
+ +

Get the quadrature points' indices in the passed Array1D array.

+ +
+
+ +

◆ GetQuadPoints()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::GetQuadPoints (Array2D< double > & quadPoints) const
+
+inline
+
+ +

Get the quadrature points in the passed Array2D array.

+
Note
Although quadPoints is a 2D array, its second dimension is equal to 1
+ +
+
+ +

◆ GetQuadRule()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCBasis::GetQuadRule (Array2D< double > & qPoints,
Array1D< double > & qWeights,
Array2D< int > & qIndices 
)
+
+ +

Get the quadrature integration information.

+ +
+
+ +

◆ GetQuadWeights()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCBasis::GetQuadWeights (Array1D< double > & quadWeights) const
+
+inline
+
+ +

Get the quadrature weights in the passed Array1D array.

+ +
+
+ +

◆ GetRandSample() [1/2]

+ +
+
+ + + + + + + + +
void PCBasis::GetRandSample (Array1D< double > & randSamples)
+
+ +

Get samples of the random variables associated with the current PC basis functions and return them in the 1D array randSamples. Take as many samples as the length of the array randSamples.

+
Note
This function does NOT reset the random number seed before sampling
+ +
+
+ +

◆ GetRandSample() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCBasis::GetRandSample (double * randSamples,
const int & nSamp 
)
+
+ +

Get nSamp samples of the random variables associated with the current PC basis functions and return them in the double* randSamples.

+
Note
This function does NOT reset the random number seed before sampling
+ +
+
+ +

◆ GetSeed()

+ +
+
+ + + + + +
+ + + + + + + +
int PCBasis::GetSeed () const
+
+inline
+
+ +

Get the random number generator seed.

+ +
+
+ +

◆ Init1dQuadPoints()

+ +
+
+ + + + + + + + +
void PCBasis::Init1dQuadPoints (int qdpts)
+
+ +

Initialize the quadrature points and weights and store the information in arrays quadPoints_, quadWeights_,quadIndices_.

+
Note
Uses an arbitrary number of quad. points.
+
+The default implementation relies on N_q=2*p+1 quadrature points, where p is the maximal order and N_q is the number of quadrature points
+
Todo:
Come up with a smarter way to pick the number of quadrature points
+
Note
Quadrature points are set according to the basis function type
+
+quadPoints is a 2D array but its second dimension is equal to 1.
+ +
+
+ +

◆ NormSq_Exact()

+ +
+
+ + + + + +
+ + + + + + + + +
double PCBasis::NormSq_Exact (int kord)
+
+private
+
+ +

Evaluate 1d norm of order kord exactly.

+ +
+
+ +

◆ SeedRandNumGen()

+ +
+
+ + + + + + + + +
void PCBasis::SeedRandNumGen (const int & seed)
+
+ +

Function to (re)seed the random number generator used to sample the Basis functions.

+ +
+
+

Member Data Documentation

+ +

◆ alpha_

+ +
+
+ + + + + +
+ + + + +
double PCBasis::alpha_
+
+private
+
+ +

Parameter alpha for PCs that require a parameter (GLG,SW,JB)

+ +
+
+ +

◆ beta_

+ +
+
+ + + + + +
+ + + + +
double PCBasis::beta_
+
+private
+
+ +

Parameter beta for PCs that require two parameters (SW,JB)

+ +
+
+ +

◆ maxord_

+ +
+
+ + + + + +
+ + + + +
int PCBasis::maxord_
+
+private
+
+ +

Maximal order of any dimension.

+ +
+
+ +

◆ narg_

+ +
+
+ + + + + +
+ + + + +
int PCBasis::narg_
+
+private
+
+ +

Number of parameters to specify the basis.

+ +
+
+ +

◆ psi1d_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> PCBasis::psi1d_
+
+private
+
+ +

Array to store basis functions evaluated at quadrature points for each order: psi1d_(iqp,iord) contains the value of the polynomial chaos basis of order iord at the location of quadrature point iqp.

+ +
+
+ +

◆ psi1dSq_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> PCBasis::psi1dSq_
+
+private
+
+ +

Array with the norms squared of the 1D basis functions for each order.

+ +
+
+ +

◆ psi1dSqExact_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> PCBasis::psi1dSqExact_
+
+private
+
+ +

Array with the exact norms squared of the 1D basis functions for each order.

+ +
+
+ +

◆ quadIndices_

+ +
+
+ + + + + +
+ + + + +
Array2D<int> PCBasis::quadIndices_
+
+private
+
+ +

Array to store quadrature point indexing; useful only for nested rules.

+ +
+
+ +

◆ quadPoints_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> PCBasis::quadPoints_
+
+private
+
+ +

Array to store quadrature points.

+ +
+
+ +

◆ quadWeights_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> PCBasis::quadWeights_
+
+private
+
+ +

Array to store quadrature weights.

+ +
+
+ +

◆ rnstate_

+ +
+
+ + + + + +
+ + + + +
dsfmt_t PCBasis::rnstate_
+
+private
+
+ +

Random sequence state for dsfmt.

+
Todo:
need more functionalities to get/set this variable from user
+ +
+
+ +

◆ rSeed_

+ +
+
+ + + + + +
+ + + + +
int PCBasis::rSeed_
+
+private
+
+ +

The seed used for the random number generators that sample the xi's in the basis functions.

+

This seed is set to 1 during the class construction and can be reset with the SeedRandNumGen function

See also
SeedRandNumGen
+ +
+
+ +

◆ type_

+ +
+
+ + + + + +
+ + + + +
string PCBasis::type_
+
+private
+
+ +

String indicator of type of basis functions used.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classPCSet-members.html b/doc/doxygen/html/classPCSet-members.html new file mode 100644 index 00000000..f0e0b855 --- /dev/null +++ b/doc/doxygen/html/classPCSet-members.html @@ -0,0 +1,233 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
PCSet Member List
+
+
+ +

This is the complete list of members for PCSet, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Add(const double *p1, const double *p2, double *p3) constPCSet
Add(const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) constPCSet
AddInPlace(double *p1, const double *p2) constPCSet
AddInPlace(Array1D< double > &p1, const Array1D< double > &p2) constPCSet
alpha_PCSetprivate
beta_PCSetprivate
Check_CVflag(void *flagvalue, const char *funcname, int opt) constPCSetprivate
ComputeEffDims(int *effdim)PCSet
ComputeEffDims(Array1D< int > &effdim)PCSet
ComputeJointSens(Array1D< double > &coef, Array2D< double > &jointsens)PCSet
ComputeMainSens(Array1D< double > &coef, Array1D< double > &mainsens)PCSet
ComputeMaxOrdPerDim()PCSetprivate
ComputeMean(const double *coef)PCSet
ComputeMean(Array1D< double > &coef)PCSet
ComputeOrders(Array1D< int > &orders)PCSet
ComputeTotSens(Array1D< double > &coef, Array1D< double > &totsens)PCSet
ComputeVarFrac(const double *coef, double *varfrac)PCSet
ComputeVarFrac(Array1D< double > &coef, Array1D< double > &varfrac)PCSet
Copy(double *p1, const double *p2) constPCSet
Copy(Array1D< double > &p1, const Array1D< double > &p2) constPCSet
CVabst_PCSetprivate
CVinitstep_PCSetprivate
CVmaxnumsteps_PCSetprivate
CVmaxord_PCSetprivate
CVmaxstep_PCSetprivate
CVrelt_PCSetprivate
ddPhi(Array1D< double > &x, Array2D< int > &mindex, Array2D< double > &grad, Array1D< double > &ck)PCSet
ddPhi_alpha(Array1D< double > &x, Array1D< int > &alpha, Array2D< double > &grad)PCSet
Derivative(const double *p1, double *p2) constPCSet
Derivative(const Array1D< double > &p1, Array1D< double > &p2) constPCSet
Div(const double *p1, const double *p2, double *p3) constPCSet
Div(const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) constPCSet
dPhi(Array1D< double > &x, Array2D< int > &mindex, Array1D< double > &grad, Array1D< double > &ck)PCSet
dPhi(Array2D< double > &x, Array2D< int > &mindex, Array2D< double > &grad, Array1D< double > &ck)PCSet
dPhi_alpha(Array1D< double > &x, Array1D< int > &alpha, Array1D< double > &grad)PCSet
DrawSampleSet(const Array1D< double > &p, Array1D< double > &samples)PCSet
DrawSampleSet(const double *p, double *samples, const int &nSamples)PCSet
DrawSampleVar(Array2D< double > &samples) constPCSet
DrawSampleVar(double *samples, const int &nS, const int &nD) constPCSet
EncodeMindex(Array1D< Array2D< int > > &sp_mindex)PCSet
EvalBasisAtCustPts(const Array2D< double > &custPoints, Array2D< double > &psi)PCSet
EvalBasisAtCustPts(const double *custPoints, const int npts, double *psi)PCSet
EvalBasisProd3()PCSetprivate
EvalBasisProd4()PCSetprivate
EvalNormSq(Array1D< double > &normsq)PCSet
EvalNormSq(double *normsq, const int npc)PCSet
EvalNormSqExact(Array1D< double > &normsq)PCSet
EvalPC(const Array1D< double > &p, Array1D< double > &randVarSamples)PCSet
EvalPC(const double *p, const double *randVarSamples)PCSet
EvalPCAtCustPoints(Array1D< double > &xch, Array2D< double > &custPoints, Array1D< double > &p)PCSet
Exp(const double *p1, double *p2) constPCSet
Exp(const Array1D< double > &p1, Array1D< double > &p2) constPCSet
GalerkProjection(const Array1D< double > &fcn, Array1D< double > &ck)PCSet
GalerkProjectionMC(const Array2D< double > &x, const Array1D< double > &fcn, Array1D< double > &ck)PCSet
GetAlpha() constPCSetinline
GetBeta() constPCSetinline
GetGMRESDivTolerance() constPCSetinline
GetModesRMS(const double *p) constPCSet
GetModesRMS(const Array1D< double > &p) constPCSet
GetMultiIndex(Array2D< int > &mindex) constPCSetinline
GetMultiIndex(int *mindex) constPCSet
GetNDim() constPCSetinline
GetNormSq(Array1D< double > &normsq) constPCSetinline
GetNQuadPoints() constPCSetinline
GetNumberPCTerms() constPCSetinline
GetNumQuadProd() constPCSet
GetNumTripleProd() constPCSet
GetOrder() constPCSetinline
GetPCType() constPCSetinline
GetPsi(Array2D< double > &psi) constPCSetinline
GetPsi(double *psi) constPCSetinline
GetPsiSq(Array1D< double > &psisq) constPCSetinline
GetPsiSq(double *psisq) constPCSetinline
GetQuadPoints(Array2D< double > &quad) constPCSetinline
GetQuadPoints(double *quad) constPCSetinline
GetQuadPointsWeights(Array2D< double > &quad, Array1D< double > &wghts) constPCSetinline
GetQuadProd(int *nQuad, int *iProd, int *jProd, int *kProd, double *Cijkl) constPCSet
GetQuadProd(Array1D< int > &nQuad, Array1D< int > &iProd, Array1D< int > &jProd, Array1D< int > &kProd, Array1D< double > &Cijkl) constPCSet
GetQuadWeights(Array1D< double > &wghts) constPCSetinline
GetQuadWeights(double *wghts) constPCSetinline
GetTaylorTermsMax() constPCSetinline
GetTaylorTolerance() constPCSetinline
GetTripleProd(int *nTriple, int *iProd, int *jProd, double *Cijk) constPCSet
GetTripleProd(Array1D< int > &nTriple, Array1D< int > &iProd, Array1D< int > &jProd, Array1D< double > &Cijk) constPCSet
GMRESMatrixVectorProd(const double *x, const double *a, double *y) constPCSetprivate
GMRESMatrixVectorProdWrapper(int *n, double *x, double *y, int *nelt, int *ia, int *ja, double *a, int *obj)PCSetinlineprivatestatic
GMRESPreCondWrapper(int *n, double *r, double *z, int *nelt, int *ia, int *ja, double *a, int *obj, double *rwork, int *iwork)PCSetinlineprivatestatic
Initialize(const string ordertype)PCSetprivate
InitISP()PCSetprivate
InitMeanStDv(const double &m, const double &s, double *p) constPCSet
InitMeanStDv(const double &m, const double &s, Array1D< double > &p) constPCSet
InitNISP()PCSetprivate
Inv(const double *p1, double *p2) constPCSet
Inv(const Array1D< double > &p1, Array1D< double > &p2) constPCSet
IPow(const double *p1, double *p2, const int &ia) constPCSet
IPow(const Array1D< double > &p1, Array1D< double > &p2, const int &ia) constPCSet
iProd2_PCSetprivate
iProd3_PCSetprivate
IsInDomain(double x)PCSet
jProd2_PCSetprivate
jProd3_PCSetprivate
kProd3_PCSetprivate
Log(const double *p1, double *p2) constPCSet
Log(const Array1D< double > &p1, Array1D< double > &p2) constPCSet
Log10(const double *p1, double *p2) constPCSet
Log10(const Array1D< double > &p1, Array1D< double > &p2) constPCSet
LogInt(const double *p1, double *p2) constPCSetprivate
LogIntRhs(realtype t, N_Vector y, N_Vector ydot, void *f_data) constPCSetprivate
LogIntRhsWrapper(realtype t, N_Vector y, N_Vector ydot, void *f_data)PCSetinlineprivatestatic
logMethod_PCSetprivate
LogTaylor(const double *p1, double *p2) constPCSetprivate
maxorddim_PCSetprivate
maxOrders_PCSetprivate
maxOrdPerDim_PCSetprivate
maxTermTaylor_PCSetprivate
multiIndex_PCSetprivate
Multiply(const double *p1, const double &a, double *p2) constPCSet
Multiply(const Array1D< double > &p1, const double &a, Array1D< double > &p2) constPCSet
MultiplyInPlace(double *p1, const double &a) constPCSet
MultiplyInPlace(Array1D< double > &p1, const double &a) constPCSet
my_index_PCSetprivate
narg_PCSetprivate
nDim_PCSetprivate
next_index_PCSetprivatestatic
nPCTerms_PCSetprivate
nQuadPoints_PCSetprivate
omap_PCSetprivatestatic
OMap_t typedefPCSetprivate
order_PCSetprivate
p_basis_PCSetprivate
pcSeq_PCSetprivate
PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, const double alpha=0.0, const double betta=1.0)PCSet
PCSet(const string sp_type, const int order, const int n_dim, const string pc_type, const string pc_seq, const double alpha=0.0, const double betta=1.0)PCSet
PCSet(const string sp_type, const Array1D< int > &maxOrders, const int n_dim, const string pc_type, const double alpha=0.0, const double betta=1.0)PCSet
PCSet(const string sp_type, const Array2D< int > &customMultiIndex, const string pc_type, const double alpha=0.0, const double betta=1.0)PCSet
PCSet()PCSetinlineprivate
PCSet(const PCSet &obj)PCSetinlineprivate
pcType_PCSetprivate
Polyn(const double *polycf, int npoly, const double *p1, double *p2) constPCSet
Polyn(const Array1D< double > &polycf, const Array1D< double > &p1, Array1D< double > &p2) constPCSet
PolynMulti(const Array1D< double > &polycf, const Array2D< int > &mindex, const Array2D< double > &p1, Array1D< double > &p2) constPCSet
PrintMultiIndex() constPCSet
PrintMultiIndexNormSquared() constPCSet
Prod(const double *p1, const double *p2, double *p3) constPCSet
Prod(const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) constPCSet
Prod3(const double *p1, const double *p2, const double *p3, double *p4) constPCSet
Prod3(const Array1D< double > &p1, const Array1D< double > &p2, const Array1D< double > &p3, Array1D< double > &p4) constPCSet
psi_PCSetprivate
psiIJKLProd3_PCSetprivate
psiIJKProd2_PCSetprivate
psiSq_PCSetprivate
quadIndices_PCSetprivate
quadPoints_PCSetprivate
quadWeights_PCSetprivate
RPow(const double *p1, double *p2, const double &a) constPCSet
RPow(const Array1D< double > &p1, Array1D< double > &p2, const double &a) constPCSet
rTolGMRESDiv_PCSetprivate
rTolTaylor_PCSetprivate
SeedBasisRandNumGen(const int &seed) constPCSet
SetGMRESDivTolerance(const double &rTol)PCSetinline
SetLogCompMethod(const LogCompMethod &logMethod)PCSetinline
SetQd1d(Array1D< double > &qdpts1d, Array1D< double > &wghts1d, int nqd)PCSet
SetQuadRule(const string grid_type, const string fs_type, int param)PCSet
SetQuadRule(Quad &quadRule)PCSet
SetTaylorTermsMax(const int &maxTerm)PCSetinline
SetTaylorTolerance(const double &rTol)PCSetinline
SetVerbosity(int verbosity)PCSetinline
SMALL_PCSetprivate
spType_PCSetprivate
StDv(const double *p) constPCSet
StDv(const Array1D< double > &p) constPCSet
Subtract(const double *p1, const double *p2, double *p3) constPCSet
Subtract(const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) constPCSet
SubtractInPlace(double *p1, const double *p2) constPCSet
SubtractInPlace(Array1D< double > &p1, const Array1D< double > &p2) constPCSet
uqtkverbose_PCSetprivate
~PCSet()PCSet
+ + + + diff --git a/doc/doxygen/html/classPCSet.html b/doc/doxygen/html/classPCSet.html new file mode 100644 index 00000000..6775a2db --- /dev/null +++ b/doc/doxygen/html/classPCSet.html @@ -0,0 +1,6081 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCSet Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Defines and initializes PC basis function set and provides functions to manipulate PC expansions defined on this basis set. + More...

+ +

#include <PCSet.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 PCSet (const string sp_type, const int order, const int n_dim, const string pc_type, const double alpha=0.0, const double betta=1.0)
 Constructor: initializes the PC basis set for the order, number of dimensions and type that are passed in. More...
 
 PCSet (const string sp_type, const int order, const int n_dim, const string pc_type, const string pc_seq, const double alpha=0.0, const double betta=1.0)
 Constructor: initializes the PC basis set for the order, number of dimensions and type that are passed in. It also customizes the multiindex sequence ( lexicographical-lex, colexicographical-colex, reverse lexicographical-revlex, and reverse clexicographical-revcolex). More...
 
 PCSet (const string sp_type, const Array1D< int > &maxOrders, const int n_dim, const string pc_type, const double alpha=0.0, const double betta=1.0)
 Constructor: initializes the PC basis set ordered in an HDMR fashion given order per each HDMR rank (univariate, bivariate, etc...) More...
 
 PCSet (const string sp_type, const Array2D< int > &customMultiIndex, const string pc_type, const double alpha=0.0, const double betta=1.0)
 Constructor: initializes the PC basis set for a given custom multiIndex. More...
 
 ~PCSet ()
 Destructor: cleans up all memory and destroys object. More...
 
void dPhi_alpha (Array1D< double > &x, Array1D< int > &alpha, Array1D< double > &grad)
 Set Gradient and Hessian operators. More...
 
void dPhi (Array1D< double > &x, Array2D< int > &mindex, Array1D< double > &grad, Array1D< double > &ck)
 Evaluate Gradient at a single d-dim point. More...
 
void dPhi (Array2D< double > &x, Array2D< int > &mindex, Array2D< double > &grad, Array1D< double > &ck)
 Evaluate Gradient at a multiple d-dim x points. More...
 
void ddPhi_alpha (Array1D< double > &x, Array1D< int > &alpha, Array2D< double > &grad)
 Evaluate Hessian at a single d-dim point and d-dim basis polynomial. More...
 
void ddPhi (Array1D< double > &x, Array2D< int > &mindex, Array2D< double > &grad, Array1D< double > &ck)
 Evaluate Gradient at a single d-dim point. More...
 
void SetQd1d (Array1D< double > &qdpts1d, Array1D< double > &wghts1d, int nqd)
 Set the quadrature rule. More...
 
void SetQuadRule (const string grid_type, const string fs_type, int param)
 Set the quadrature points by specifying a grid type, a full/sparse indicator, and an integer parameter. More...
 
void SetQuadRule (Quad &quadRule)
 Set a custom quadrature rule by pointing to the corresponding object. More...
 
void PrintMultiIndex () const
 Print information on the screen. More...
 
void PrintMultiIndexNormSquared () const
 For all terms, print their multi-index and norm^2 on the screen. More...
 
string GetPCType () const
 Get and set variables/arrays inline. More...
 
double GetAlpha () const
 Get the value of the parameter alpha. More...
 
double GetBeta () const
 Get the value of the parameter beta. More...
 
void GetMultiIndex (Array2D< int > &mindex) const
 Get the multiindex (return Array2D) More...
 
void GetMultiIndex (int *mindex) const
 Get the multiindex (return double *) More...
 
void GetNormSq (Array1D< double > &normsq) const
 Get the norm-squared. More...
 
int GetNumberPCTerms () const
 Get the number of terms in a PC expansion of this order and dimension. More...
 
int GetNDim () const
 Get the PC dimensionality. More...
 
int GetOrder () const
 Get the PC order. More...
 
int GetNQuadPoints () const
 Get the number of quadrature points. More...
 
void GetQuadPoints (Array2D< double > &quad) const
 Get the quadrature points. More...
 
void GetQuadPointsWeights (Array2D< double > &quad, Array1D< double > &wghts) const
 Get the quadrature points and weights. More...
 
void GetQuadPoints (double *quad) const
 Get the quadrature points folded into a one-dimensional array quad. More...
 
void GetQuadWeights (Array1D< double > &wghts) const
 Get the quadrature weights. More...
 
void GetQuadWeights (double *wghts) const
 Get the quadrature weights folded into a one-dimensional array wghts. More...
 
void GetPsi (Array2D< double > &psi) const
 Get the values of the basis polynomials evaluated at the quadrature points. More...
 
void GetPsi (double *psi) const
 Get the polynomials evaluated at the quadrature points folded into a one-dimensional array psi. More...
 
void GetPsiSq (Array1D< double > &psisq) const
 Get the basis polynomial norms-squared in an array class object psisq. More...
 
void GetPsiSq (double *psisq) const
 Get the basis polynomial norms-squared in a double* array psisq. More...
 
double GetTaylorTolerance () const
 Get relative tolerance for Taylor series approximations. More...
 
void SetTaylorTolerance (const double &rTol)
 Set relative tolerance for Taylor series approximations. More...
 
int GetTaylorTermsMax () const
 Get maximum number of terms in Taylor series approximations. More...
 
void SetTaylorTermsMax (const int &maxTerm)
 Set maximum number of terms in Taylor series approximations. More...
 
void SetLogCompMethod (const LogCompMethod &logMethod)
 Set method of computing the log function. More...
 
double GetGMRESDivTolerance () const
 Get relative tolerance for GMRES in Div routine. More...
 
void SetGMRESDivTolerance (const double &rTol)
 Set the relative tolerance for GMRES in Div routine. More...
 
void InitMeanStDv (const double &m, const double &s, double *p) const
 Intrusive arithmetics. More...
 
void InitMeanStDv (const double &m, const double &s, Array1D< double > &p) const
 Initializes a PC expansion p in Array1D<double> format to have the same distribution as the underlying PC germ, but with a specified mean m and standard deviation s. More...
 
void Copy (double *p1, const double *p2) const
 Copy PC expansion p2 into p1 (i.e. p1 = p2). More...
 
void Copy (Array1D< double > &p1, const Array1D< double > &p2) const
 Copy PC expansion p2 into p1 (i.e. p1 = p2). More...
 
void Add (const double *p1, const double *p2, double *p3) const
 Add two PC expansions given by double* arguments p1 and p2, and return the result in p3. More...
 
void Add (const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) const
 Add two PC expansions given by Array1D arguments p1 and p2, and return the result in p3. More...
 
void AddInPlace (double *p1, const double *p2) const
 Add PC expansions given by double* argument p2 to p1 and return the result in p1. More...
 
void AddInPlace (Array1D< double > &p1, const Array1D< double > &p2) const
 Add PC expansions given by Array1D argument p2 to p1 and return the result in p1. More...
 
void Multiply (const double *p1, const double &a, double *p2) const
 Multiply PC expansion p1 with scalar a and return the result in p2. All PCEs are in double* format. More...
 
void Multiply (const Array1D< double > &p1, const double &a, Array1D< double > &p2) const
 Multiply PC expansion p1 with scalar a and return the result in p2. All PCEs are in Array1D format. More...
 
void MultiplyInPlace (double *p1, const double &a) const
 Multiply PC expansions given by double* argument p1 with scalar a and return the result in p1. More...
 
void MultiplyInPlace (Array1D< double > &p1, const double &a) const
 Multiply PC expansions given by Array1D argument p1 with scalar a and return the result in p1. More...
 
void Subtract (const double *p1, const double *p2, double *p3) const
 Subtract PC expansion p2 from p1, and return the result in p3, with all arguments given as double*. More...
 
void Subtract (const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) const
 Subtract PC expansion p2 from p1, and return the result in p3, with all arguments given as Array1D structures. More...
 
void SubtractInPlace (double *p1, const double *p2) const
 Subtract PC expansion p2 from p1, and return the result in p1, with all arguments given as double*. More...
 
void SubtractInPlace (Array1D< double > &p1, const Array1D< double > &p2) const
 Subtract PC expansion p2 from p1, and return the result in p1, with all arguments given as Array1D structures. More...
 
void Prod (const double *p1, const double *p2, double *p3) const
 Multiply two PC expansions given by double* arguments p1 and p2, and return the result in p3. More...
 
void Prod (const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) const
 Multipy two PC expansions given by Array1D arguments p1 and p2, and return the result in p3. More...
 
void Prod3 (const double *p1, const double *p2, const double *p3, double *p4) const
 Multiply three PC expansions given by double* arguments p1, p2, and p3, and return the result in p4. More...
 
void Prod3 (const Array1D< double > &p1, const Array1D< double > &p2, const Array1D< double > &p3, Array1D< double > &p4) const
 Multipy three PC expansions given by Array1D arguments p1, p2, and p3, and return the result in p4. More...
 
void Polyn (const double *polycf, int npoly, const double *p1, double *p2) const
 Evaluates a polynomial of PC that is given in double* argument p1. Polynomial coefficients are given in double* argument polycf of size npoly. The output PC is contained in double* argument p2. More...
 
void Polyn (const Array1D< double > &polycf, const Array1D< double > &p1, Array1D< double > &p2) const
 Evaluates a polynomial of PC that is given by Array1D argument p1. Polynomial coefficients are given in the Array1D argument polycf. The output PC is contained in Array1D argument p2. More...
 
void PolynMulti (const Array1D< double > &polycf, const Array2D< int > &mindex, const Array2D< double > &p1, Array1D< double > &p2) const
 Evaluates a multivariate polynomial of a set of PC inputs given by Array2D argument p1 (each column of p1 is a PC input). Polynomial coefficients are given in Array1D argument polycf. Multiindex set for the multivariate polynomial is given in Array2D argument mindex. The output PC is contained in Array1D argument p2. More...
 
void Exp (const double *p1, double *p2) const
 Take the exp() of the PC expansion given by double* argument p1, and return the result in p2. More...
 
void Exp (const Array1D< double > &p1, Array1D< double > &p2) const
 Take the exp() of the PC expansion given by Array1D argument p1, and return the result in p2. More...
 
void Log (const double *p1, double *p2) const
 Take the natural logarithm log() of the PC expansion given by double* argument p1, and return the result in p2. The logarithm is evaluated either via Taylor series or via integration depending on the value of parameter logMethod_. More...
 
void Log (const Array1D< double > &p1, Array1D< double > &p2) const
 Take the natural logarithm, log(), of the PC expansion given by Array1D argument p1, and return the result in Array1D argument p2. More...
 
void Log10 (const double *p1, double *p2) const
 Take the logarithm to base 10 of the PC expansion given by double* argument p1, and return the result in p2. More...
 
void Log10 (const Array1D< double > &p1, Array1D< double > &p2) const
 Take the logarithm to base 10 of the PC expansion given by Array1D argument p1, and return the result in Array1D argument p2. More...
 
void RPow (const double *p1, double *p2, const double &a) const
 Evaluate power a (a real number) of PC expansion given by double* argument p1, and return the result in p2. The power is computed as p1^a = exp(a*log(p1)), where log(p1) is evaluated either via Taylor series or via integration depending on the value of parameter logMethod_. More...
 
void RPow (const Array1D< double > &p1, Array1D< double > &p2, const double &a) const
 Evaluate power a (a real number) of PC expansion given by Array1D argument p1, and return the result in Array1D argument p2. More...
 
void IPow (const double *p1, double *p2, const int &ia) const
 Evaluate power ia (an integer number) of PC expansion given by double* argument p1, and return the result in p2. More...
 
void IPow (const Array1D< double > &p1, Array1D< double > &p2, const int &ia) const
 Evaluate power ia (an integer number) of PC expansion given by Array1D argument p1, and return the result in Array1D argument p2. More...
 
void Inv (const double *p1, double *p2) const
 Evaluate the inverse of PC expansion given by double* argument p1, and return the result in p2. The inverse is computed using the division function. More...
 
void Inv (const Array1D< double > &p1, Array1D< double > &p2) const
 Evaluate the inverse of PC expansion given by Array1D argument p1, and return the result in Array1D argument p2. More...
 
void Div (const double *p1, const double *p2, double *p3) const
 Divide the PC expansion p1 by p2, and return the result in p3 (All arguments in double* format) More...
 
void Div (const Array1D< double > &p1, const Array1D< double > &p2, Array1D< double > &p3) const
 Divide the PC expansion p1 by p2, and return the result in p3 (All arguments in Array1D<double> format) More...
 
double StDv (const double *p) const
 Returns the standard deviation of PC expansion p in a double* format. More...
 
double StDv (const Array1D< double > &p) const
 Returns the standard deviation of PC expansion p (Argument in Array1D<double> format) More...
 
double GetModesRMS (const double *p) const
 Compute the rms average of the PC coefficients (i.e. the square root of the average of the square of the PC coefficients, not taking into account any basis functions). (Arguments in double* format) More...
 
double GetModesRMS (const Array1D< double > &p) const
 Compute the rms average of the PC coefficients (i.e. the square root of the average of the square of the PC coefficients, not taking into account any basis functions). (Arguments in Array1D<double> format) More...
 
void Derivative (const double *p1, double *p2) const
 Computes derivatives of univariate PC given by coefficients p1 returns coefficient vector of the derivative in p2. More...
 
void Derivative (const Array1D< double > &p1, Array1D< double > &p2) const
 Computes derivatives of univariate PC given by coefficients p1 returns coefficient vector of the derivative in p2. More...
 
int GetNumTripleProd () const
 Returns number of triple products. More...
 
void GetTripleProd (int *nTriple, int *iProd, int *jProd, double *Cijk) const
 Returns triple products indices (int*/double* version) More...
 
void GetTripleProd (Array1D< int > &nTriple, Array1D< int > &iProd, Array1D< int > &jProd, Array1D< double > &Cijk) const
 Returns triple products indices (Array version) More...
 
int GetNumQuadProd () const
 Returns number of quad products. More...
 
void GetQuadProd (int *nQuad, int *iProd, int *jProd, int *kProd, double *Cijkl) const
 Returns quad products indices (int*/double* version) More...
 
void GetQuadProd (Array1D< int > &nQuad, Array1D< int > &iProd, Array1D< int > &jProd, Array1D< int > &kProd, Array1D< double > &Cijkl) const
 Returns quad products indices (Array version) More...
 
void SeedBasisRandNumGen (const int &seed) const
 Random sample generator functions. More...
 
void DrawSampleSet (const Array1D< double > &p, Array1D< double > &samples)
 Draw a set of samples from the PC expansion p, and return the result in the array samples. All arguments are in Array1D<double> format The number of samples requested is assumed to be the size of the samples array. More...
 
void DrawSampleSet (const double *p, double *samples, const int &nSamples)
 Draw a set of samples from the PC expansion given in double* argument p, and return the result in double* array samples. The number of samples requested is the argument nSamples. More...
 
void DrawSampleVar (Array2D< double > &samples) const
 Draw a set of samples of the underlying germ random variable. More...
 
void DrawSampleVar (double *samples, const int &nS, const int &nD) const
 
double EvalPC (const Array1D< double > &p, Array1D< double > &randVarSamples)
 PC evaluation functionalities. More...
 
double EvalPC (const double *p, const double *randVarSamples)
 Evaluate the given PC expansion p, at the specified values of the random variables, randVarSamples. All arguments in const double* format. More...
 
void EvalPCAtCustPoints (Array1D< double > &xch, Array2D< double > &custPoints, Array1D< double > &p)
 Evaluate the given PC expansion at given set of points with given coefficient vector and return the values in an 1D Array in the first argument. More...
 
void EvalBasisAtCustPts (const Array2D< double > &custPoints, Array2D< double > &psi)
 Evaluate Basis Functions at given points custPoints and return in the array psi. More...
 
void EvalBasisAtCustPts (const double *custPoints, const int npts, double *psi)
 
void GalerkProjection (const Array1D< double > &fcn, Array1D< double > &ck)
 Galerkin projection functionalities. More...
 
void GalerkProjectionMC (const Array2D< double > &x, const Array1D< double > &fcn, Array1D< double > &ck)
 Galerkin Projection via Monte-Carlo integration. More...
 
int ComputeOrders (Array1D< int > &orders)
 Multiindex parsing functionalities. More...
 
int ComputeEffDims (int *effdim)
 Computes the effective dimensionality of each basis term, i.e., the number of dimensions that enter with a non-zero degree. also returns the maximal dimensionality among all basis terms. More...
 
int ComputeEffDims (Array1D< int > &effdim)
 Computes the effective dimensionality of each basis term, i.e., the number of dimensions that enter with a non-zero degree. also returns the maximal dimensionality among all basis terms. More...
 
void EncodeMindex (Array1D< Array2D< int > > &sp_mindex)
 Encode multiIndex into a 'sparse' format where the bases are ordered by their effective dimensionality. The i-th element in sp_mindex stores all the bases that have effective dimensionality equal to i. Also, only non-zero components are stored. More...
 
double ComputeMean (const double *coef)
 Moment/sensitivity extraction given coefficients. More...
 
double ComputeMean (Array1D< double > &coef)
 Compute the mean of the PC given coefficient array coef(seeking the zero-th order multiindex) More...
 
double ComputeVarFrac (const double *coef, double *varfrac)
 Compute the variance fractions of each basis term given coefficients in double *coef; returns the variance fractions in the double *varfrac. More...
 
double ComputeVarFrac (Array1D< double > &coef, Array1D< double > &varfrac)
 Compute the variance fractions of each basis term given coefficient array coef; returns the variance fractions in the array varfrac. More...
 
void ComputeMainSens (Array1D< double > &coef, Array1D< double > &mainsens)
 Compute main effect sensitivity (Sobol) indices given coefficient array coef; returns the indices in the array mainsens. More...
 
void ComputeTotSens (Array1D< double > &coef, Array1D< double > &totsens)
 Compute total effect sensitivity (Sobol) indices given coefficient array coeff; returns the indices in the array totsens. More...
 
void ComputeJointSens (Array1D< double > &coef, Array2D< double > &jointsens)
 Compute joint effect sensitivity (Sobol) indices given coefficient array coeff; returns the indices in the array jointsens. More...
 
void SetVerbosity (int verbosity)
 Other. More...
 
void EvalNormSq (Array1D< double > &normsq)
 Evaluate norms-squared of all bases and return in the array normsq. More...
 
void EvalNormSq (double *normsq, const int npc)
 
void EvalNormSqExact (Array1D< double > &normsq)
 Evaluate norms-squared analytically of all bases and return in the array normsq. More...
 
bool IsInDomain (double x)
 Check if the point x is in the PC domain. More...
 
+ + + + +

+Private Types

typedef std::map< int, PCSet * > OMap_t
 Definition of a map to connect integer indexes with pointers to this class. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Member Functions

 PCSet ()
 Dummy default constructor, which should not be used as it is not well defined Therefore we make it private so it is not accessible. More...
 
 PCSet (const PCSet &obj)
 Dummy copy constructor, which should not be used as it is currently not well defined. Therefore we make it private so it is not accessible. More...
 
void ComputeMaxOrdPerDim ()
 Compute maximal order per dimension and fill in the array maxOrdPerDim_. More...
 
void Initialize (const string ordertype)
 Initialization of the appropriate variables. More...
 
void InitISP ()
 Initialize quadrature for computing triple products(ISP) and orthogonal projection(NISP) More...
 
void InitNISP ()
 Initialize variables that are needed only in non-intrusive computations. More...
 
void EvalBasisProd3 ()
 Evaluate the expectation of product of three basis functions. More...
 
void EvalBasisProd4 ()
 Evaluate the expectation of product of four basis functions. More...
 
void GMRESMatrixVectorProd (const double *x, const double *a, double *y) const
 Actual C++ implementation of the matric vector multiplication for GMRES for the division operation. More...
 
void LogTaylor (const double *p1, double *p2) const
 Computes natural logarithm using Taylor expansion: N p2 = ln(p1) = ln(p1Mean) + sum d n=1 n. More...
 
void LogInt (const double *p1, double *p2) const
 Computes natural logarithm by numerical integration: calculate p2=ln(p1) by integrating du=dx/x to get ln(x) More...
 
int LogIntRhs (realtype t, N_Vector y, N_Vector ydot, void *f_data) const
 Evaluates rhs necessary to compute natural logarithm via integration. More...
 
int Check_CVflag (void *flagvalue, const char *funcname, int opt) const
 Check cvode return for errors. More...
 
+ + + + + + + + + + +

+Static Private Member Functions

static void GMRESMatrixVectorProdWrapper (int *n, double *x, double *y, int *nelt, int *ia, int *ja, double *a, int *obj)
 Wrapper for Matrix-vector multiplication routine to be called by GMRES. More...
 
static void GMRESPreCondWrapper (int *n, double *r, double *z, int *nelt, int *ia, int *ja, double *a, int *obj, double *rwork, int *iwork)
 Wrapper for preconditioner routine to be called by GMRES. More...
 
static int LogIntRhsWrapper (realtype t, N_Vector y, N_Vector ydot, void *f_data)
 Wrapper for LogIntRhs. The first component of f_data pointer carries an integer handle identifying the appropriate PC object. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

int uqtkverbose_
 Verbosity level. More...
 
string spType_
 String indicator of ISP or NISP implementation type. More...
 
string pcType_
 String indicator of PC type. More...
 
string pcSeq_
 String indicator of multiindex ordering. More...
 
PCBasisp_basis_
 Pointer to the class that defines the basis type and functions. More...
 
int order_
 Order of the PC representation. More...
 
int maxorddim_
 Maximal order within all dimensions. More...
 
Array1D< int > maxOrders_
 Array of maximum orders requested if custom(HDMR) ordering is requested. More...
 
Array1D< int > maxOrdPerDim_
 Array of maximum orders per dimension. More...
 
const int nDim_
 Number of stochastic dimensions (degrees of freedom) in the PC representation. More...
 
int nQuadPoints_
 Number of quadrature points used. More...
 
int nPCTerms_
 Total number of terms in the PC expansions. More...
 
double rTolTaylor_
 Relative tolerance for Taylor series approximations. More...
 
int maxTermTaylor_
 Max number of terms in Taylor series approximations. More...
 
double SMALL_
 Tolerance to avoid floating-point errors. More...
 
double rTolGMRESDiv_
 GMRES tolerance in Div() More...
 
Array2D< double > psi_
 Array to store basis functions evaluated at quadrature points for each order: psi_(iqp,ipc) contains the value of the polynomial chaos ipc-th basis at the location of quadrature point iqp. More...
 
Array1D< double > psiSq_
 Array with the norms squared of the basis functions, corresponding to each term in the PC expansion. More...
 
Array2D< double > quadPoints_
 Array to store quadrature points. More...
 
Array1D< double > quadWeights_
 Array to store quadrature weights. More...
 
Array2D< int > quadIndices_
 Array to store quadrature point indexing; useful for nested rules. More...
 
Array2D< int > multiIndex_
 Array to store multi-index: multiIndex_(ipc,idim) contains the order of the basis function associated with dimension idim, for the ipc-th term in the PC expansion. More...
 
Array1D< Array1D< int > > iProd2_
 i-indices of <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k More...
 
Array1D< Array1D< int > > jProd2_
 j-indices of <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k More...
 
Array1D< Array1D< double > > psiIJKProd2_
 <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k More...
 
Array1D< Array1D< int > > iProd3_
 i-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l More...
 
Array1D< Array1D< int > > jProd3_
 j-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l More...
 
Array1D< Array1D< int > > kProd3_
 k-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l More...
 
Array1D< Array1D< double > > psiIJKLProd3_
 <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l More...
 
LogCompMethod logMethod_
 Flag for method to compute log: TaylorSeries or Integration. More...
 
int CVmaxord_
 CVODE parameter: maximal order. More...
 
int CVmaxnumsteps_
 CVODE parameter: maximal number of steps. More...
 
double CVinitstep_
 CVODE parameter: initial step size. More...
 
double CVmaxstep_
 CVODE parameter: maximal step size. More...
 
double CVrelt_
 CVODE parameter: relative tolerance. More...
 
double CVabst_
 CVODE parameter: absolute tolerance. More...
 
int my_index_
 Index of this class. More...
 
int narg_
 Number of free parameters to specify the basis. More...
 
double alpha_
 Parameter alpha for PCs that require a parameter (GLG,SW,JB) More...
 
double beta_
 Parameter beta for PCs that require two parameters (SW,JB) More...
 
+ + + + + + + +

+Static Private Attributes

static int next_index_ = 0
 index of next object in map More...
 
static OMap_tomap_ = NULL
 Map to connect integer indexes with pointers to this class. More...
 
+

Detailed Description

+

Defines and initializes PC basis function set and provides functions to manipulate PC expansions defined on this basis set.

+

Member Typedef Documentation

+ +

◆ OMap_t

+ +
+
+ + + + + +
+ + + + +
typedef std::map<int, PCSet*> PCSet::OMap_t
+
+private
+
+ +

Definition of a map to connect integer indexes with pointers to this class.

+ +
+
+

Constructor & Destructor Documentation

+ +

◆ PCSet() [1/6]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PCSet::PCSet (const string sp_type,
const int order,
const int n_dim,
const string pc_type,
const double alpha = 0.0,
const double betta = 1.0 
)
+
+ +

Constructor: initializes the PC basis set for the order, number of dimensions and type that are passed in.

+

Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), or "NISPnoq" (non-intrusive without quadrature initialization)

Note
alpha and betta are parameters only relevant for GLG, JB or SW chaoses
+ +
+
+ +

◆ PCSet() [2/6]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PCSet::PCSet (const string sp_type,
const int order,
const int n_dim,
const string pc_type,
const string pc_seq,
const double alpha = 0.0,
const double betta = 1.0 
)
+
+ +

Constructor: initializes the PC basis set for the order, number of dimensions and type that are passed in. It also customizes the multiindex sequence ( lexicographical-lex, colexicographical-colex, reverse lexicographical-revlex, and reverse clexicographical-revcolex).

+

Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), or "NISPnoq" (non-intrusive without quadrature initialization)

Note
alpha and betta are parameters only relevant for GLG, JB or SW chaoses
+ +
+
+ +

◆ PCSet() [3/6]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PCSet::PCSet (const string sp_type,
const Array1D< int > & maxOrders,
const int n_dim,
const string pc_type,
const double alpha = 0.0,
const double betta = 1.0 
)
+
+ +

Constructor: initializes the PC basis set ordered in an HDMR fashion given order per each HDMR rank (univariate, bivariate, etc...)

+

Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), or "NISPnoq" (non-intrusive without quadrature initialization)

Note
alpha and betta are parameters only relevant for GLG, JB or SW chaoses
+ +
+
+ +

◆ PCSet() [4/6]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PCSet::PCSet (const string sp_type,
const Array2D< int > & customMultiIndex,
const string pc_type,
const double alpha = 0.0,
const double betta = 1.0 
)
+
+ +

Constructor: initializes the PC basis set for a given custom multiIndex.

+

Implementation type sp_type has three options "ISP" (intrusive methods), "NISP" (non-intrusive), or "NISPnoq" (non-intrusive without quadrature initialization)

Note
alpha and betta are parameters only relevant for GLG, JB or SW chaoses
+ +
+
+ +

◆ ~PCSet()

+ +
+
+ + + + + + + +
PCSet::~PCSet ()
+
+ +

Destructor: cleans up all memory and destroys object.

+ +
+
+ +

◆ PCSet() [5/6]

+ +
+
+ + + + + +
+ + + + + + + +
PCSet::PCSet ()
+
+inlineprivate
+
+ +

Dummy default constructor, which should not be used as it is not well defined Therefore we make it private so it is not accessible.

+
Note
All parameters are intialized to dummy values.
+ +
+
+ +

◆ PCSet() [6/6]

+ +
+
+ + + + + +
+ + + + + + + + +
PCSet::PCSet (const PCSetobj)
+
+inlineprivate
+
+ +

Dummy copy constructor, which should not be used as it is currently not well defined. Therefore we make it private so it is not accessible.

+
Note
I am not sure actually whether the initialization performed below is legal as it requires access to private data members of the class that is passed in.
+ +
+
+

Member Function Documentation

+ +

◆ Add() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Add (const double * p1,
const double * p2,
double * p3 
) const
+
+ +

Add two PC expansions given by double* arguments p1 and p2, and return the result in p3.

+ +
+
+ +

◆ Add() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Add (const Array1D< double > & p1,
const Array1D< double > & p2,
Array1D< double > & p3 
) const
+
+ +

Add two PC expansions given by Array1D arguments p1 and p2, and return the result in p3.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ AddInPlace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::AddInPlace (double * p1,
const double * p2 
) const
+
+ +

Add PC expansions given by double* argument p2 to p1 and return the result in p1.

+ +
+
+ +

◆ AddInPlace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::AddInPlace (Array1D< double > & p1,
const Array1D< double > & p2 
) const
+
+ +

Add PC expansions given by Array1D argument p2 to p1 and return the result in p1.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ Check_CVflag()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
int PCSet::Check_CVflag (void * flagvalue,
const char * funcname,
int opt 
) const
+
+private
+
+ +

Check cvode return for errors.

+ +
+
+ +

◆ ComputeEffDims() [1/2]

+ +
+
+ + + + + + + + +
int PCSet::ComputeEffDims (int * effdim)
+
+ +

Computes the effective dimensionality of each basis term, i.e., the number of dimensions that enter with a non-zero degree. also returns the maximal dimensionality among all basis terms.

+
Note
This is not the classical effective dimensionality, since all dimensions can still be involved.
+ +
+
+ +

◆ ComputeEffDims() [2/2]

+ +
+
+ + + + + + + + +
int PCSet::ComputeEffDims (Array1D< int > & effdim)
+
+ +

Computes the effective dimensionality of each basis term, i.e., the number of dimensions that enter with a non-zero degree. also returns the maximal dimensionality among all basis terms.

+
Note
This is not the classical effective dimensionality, since all dimensions can still be involved.
+ +
+
+ +

◆ ComputeJointSens()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::ComputeJointSens (Array1D< double > & coef,
Array2D< double > & jointsens 
)
+
+ +

Compute joint effect sensitivity (Sobol) indices given coefficient array coeff; returns the indices in the array jointsens.

+
Note
jointsens will be populated as a strictly upper-diagonal matrix
+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ ComputeMainSens()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::ComputeMainSens (Array1D< double > & coef,
Array1D< double > & mainsens 
)
+
+ +

Compute main effect sensitivity (Sobol) indices given coefficient array coef; returns the indices in the array mainsens.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ ComputeMaxOrdPerDim()

+ +
+
+ + + + + +
+ + + + + + + +
void PCSet::ComputeMaxOrdPerDim ()
+
+private
+
+ +

Compute maximal order per dimension and fill in the array maxOrdPerDim_.

+ +
+
+ +

◆ ComputeMean() [1/2]

+ +
+
+ + + + + + + + +
double PCSet::ComputeMean (const double * coef)
+
+ +

Moment/sensitivity extraction given coefficients.

+

Compute the mean of the PC given coefficients in double *coef (seeking the zero-th order multiindex)

+ +
+
+ +

◆ ComputeMean() [2/2]

+ +
+
+ + + + + + + + +
double PCSet::ComputeMean (Array1D< double > & coef)
+
+ +

Compute the mean of the PC given coefficient array coef(seeking the zero-th order multiindex)

+ +
+
+ +

◆ ComputeOrders()

+ +
+
+ + + + + + + + +
int PCSet::ComputeOrders (Array1D< int > & orders)
+
+ +

Multiindex parsing functionalities.

+

Computes the order of each basis term and return it in the array orders, also returns the maximal order

Todo:
There is no double* version of this function
+ +
+
+ +

◆ ComputeTotSens()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::ComputeTotSens (Array1D< double > & coef,
Array1D< double > & totsens 
)
+
+ +

Compute total effect sensitivity (Sobol) indices given coefficient array coeff; returns the indices in the array totsens.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ ComputeVarFrac() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double PCSet::ComputeVarFrac (const double * coef,
double * varfrac 
)
+
+ +

Compute the variance fractions of each basis term given coefficients in double *coef; returns the variance fractions in the double *varfrac.

+
Note
Also returns the variance
+
+The value for the zeroth order term has a special meaning: it is equal to mean^2/variance or (mean/std)^2.
+ +
+
+ +

◆ ComputeVarFrac() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double PCSet::ComputeVarFrac (Array1D< double > & coef,
Array1D< double > & varfrac 
)
+
+ +

Compute the variance fractions of each basis term given coefficient array coef; returns the variance fractions in the array varfrac.

+
Note
Also returns the variance
+
+The value for the zeroth order term has a special meaning: it is equal to mean^2/variance or (mean/std)^2.
+ +
+
+ +

◆ Copy() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Copy (double * p1,
const double * p2 
) const
+
+ +

Copy PC expansion p2 into p1 (i.e. p1 = p2).

+

All arguments in double* format.

+ +
+
+ +

◆ Copy() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Copy (Array1D< double > & p1,
const Array1D< double > & p2 
) const
+
+ +

Copy PC expansion p2 into p1 (i.e. p1 = p2).

+

All arguments in Array format

Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ ddPhi()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::ddPhi (Array1D< double > & x,
Array2D< int > & mindex,
Array2D< double > & grad,
Array1D< double > & ck 
)
+
+ +

Evaluate Gradient at a single d-dim point.

+

for a PCSet object

+ +
+
+ +

◆ ddPhi_alpha()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::ddPhi_alpha (Array1D< double > & x,
Array1D< int > & alpha,
Array2D< double > & grad 
)
+
+ +

Evaluate Hessian at a single d-dim point and d-dim basis polynomial.

+ +
+
+ +

◆ Derivative() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Derivative (const double * p1,
double * p2 
) const
+
+ +

Computes derivatives of univariate PC given by coefficients p1 returns coefficient vector of the derivative in p2.

+
Note
Makes use of intrusive computations on recursive formulae for derivatives
+
Todo:

Supports LU and HG bases only

+

Supports only for 1d PCs

+
+ +
+
+ +

◆ Derivative() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Derivative (const Array1D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Computes derivatives of univariate PC given by coefficients p1 returns coefficient vector of the derivative in p2.

+
Note
Makes use of intrusive computations on recursive formulae for derivatives
+
Todo:

Supports LU and HG bases only

+

Supports only for 1d PCs

+
+ +
+
+ +

◆ Div() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Div (const double * p1,
const double * p2,
double * p3 
) const
+
+ +

Divide the PC expansion p1 by p2, and return the result in p3 (All arguments in double* format)

+

The "division" p3 = p1/p2 is performed by solving the system of equations p2*p3 = p1 for the unknown p3.

Note
When GMRES is used to solve this system of equations (based on a preprocessor flag in the source code for this routine), a relative tolerance criterium is used that is set by default to 1.e-8, and can be changed with SetGMRESDivTolerance().
+
Todo:
Remove duplication of data and parameters that was required for enforcing imposed "const" constraints on some of the arguments and the class data members when they are being passed to fortran.
+ +
+
+ +

◆ Div() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Div (const Array1D< double > & p1,
const Array1D< double > & p2,
Array1D< double > & p3 
) const
+
+ +

Divide the PC expansion p1 by p2, and return the result in p3 (All arguments in Array1D<double> format)

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ dPhi() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::dPhi (Array1D< double > & x,
Array2D< int > & mindex,
Array1D< double > & grad,
Array1D< double > & ck 
)
+
+ +

Evaluate Gradient at a single d-dim point.

+

for a PCSet object

+ +
+
+ +

◆ dPhi() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::dPhi (Array2D< double > & x,
Array2D< int > & mindex,
Array2D< double > & grad,
Array1D< double > & ck 
)
+
+ +

Evaluate Gradient at a multiple d-dim x points.

+

for a PCSet object

+ +
+
+ +

◆ dPhi_alpha()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::dPhi_alpha (Array1D< double > & x,
Array1D< int > & alpha,
Array1D< double > & grad 
)
+
+ +

Set Gradient and Hessian operators.

+

Evaluate Gradient at a single d-dim point and d-dim basis polynomial

+ +
+
+ +

◆ DrawSampleSet() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::DrawSampleSet (const Array1D< double > & p,
Array1D< double > & samples 
)
+
+ +

Draw a set of samples from the PC expansion p, and return the result in the array samples. All arguments are in Array1D<double> format The number of samples requested is assumed to be the size of the samples array.

+
Note
The size of the array p that is passed in needs to equal the number of PC terms
+ +
+
+ +

◆ DrawSampleSet() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::DrawSampleSet (const double * p,
double * samples,
const int & nSamples 
)
+
+ +

Draw a set of samples from the PC expansion given in double* argument p, and return the result in double* array samples. The number of samples requested is the argument nSamples.

+ +
+
+ +

◆ DrawSampleVar() [1/2]

+ +
+
+ + + + + + + + +
void PCSet::DrawSampleVar (Array2D< double > & samples) const
+
+ +

Draw a set of samples of the underlying germ random variable.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ DrawSampleVar() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::DrawSampleVar (double * samples,
const int & nS,
const int & nD 
) const
+
+ +
+
+ +

◆ EncodeMindex()

+ +
+
+ + + + + + + + +
void PCSet::EncodeMindex (Array1D< Array2D< int > > & sp_mindex)
+
+ +

Encode multiIndex into a 'sparse' format where the bases are ordered by their effective dimensionality. The i-th element in sp_mindex stores all the bases that have effective dimensionality equal to i. Also, only non-zero components are stored.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ EvalBasisAtCustPts() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::EvalBasisAtCustPts (const Array2D< double > & custPoints,
Array2D< double > & psi 
)
+
+ +

Evaluate Basis Functions at given points custPoints and return in the array psi.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ EvalBasisAtCustPts() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::EvalBasisAtCustPts (const double * custPoints,
const int npts,
double * psi 
)
+
+ +
+
+ +

◆ EvalBasisProd3()

+ +
+
+ + + + + +
+ + + + + + + +
void PCSet::EvalBasisProd3 ()
+
+private
+
+ +

Evaluate the expectation of product of three basis functions.

+ +
+
+ +

◆ EvalBasisProd4()

+ +
+
+ + + + + +
+ + + + + + + +
void PCSet::EvalBasisProd4 ()
+
+private
+
+ +

Evaluate the expectation of product of four basis functions.

+ +
+
+ +

◆ EvalNormSq() [1/2]

+ +
+
+ + + + + + + + +
void PCSet::EvalNormSq (Array1D< double > & normsq)
+
+ +

Evaluate norms-squared of all bases and return in the array normsq.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ EvalNormSq() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::EvalNormSq (double * normsq,
const int npc 
)
+
+ +
+
+ +

◆ EvalNormSqExact()

+ +
+
+ + + + + + + + +
void PCSet::EvalNormSqExact (Array1D< double > & normsq)
+
+ +

Evaluate norms-squared analytically of all bases and return in the array normsq.

+
Todo:
There is no double* version of this function
+
Note
Custom PCs do not have this capability
+ +
+
+ +

◆ EvalPC() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double PCSet::EvalPC (const Array1D< double > & p,
Array1D< double > & randVarSamples 
)
+
+ +

PC evaluation functionalities.

+

Evaluate the given PC expansion p, at the specified values of the random variables, randVarSamples. All arguments in const Array1D<double> format

Note
The number of elements in p needs to match the number of terms in the PC expansions in this PCSet.
+
+The number of elements in randVarSamples needs to match the number of dimensions in the PC expansion.
+ +
+
+ +

◆ EvalPC() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double PCSet::EvalPC (const double * p,
const double * randVarSamples 
)
+
+ +

Evaluate the given PC expansion p, at the specified values of the random variables, randVarSamples. All arguments in const double* format.

+
Note
The number of elements in p is assumed to match the number of terms in the PC expansions in this PCSet.
+
+The number of elements in randVarSamples is assumed to match the number of dimensions in the PC expansion.
+ +
+
+ +

◆ EvalPCAtCustPoints()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::EvalPCAtCustPoints (Array1D< double > & xch,
Array2D< double > & custPoints,
Array1D< double > & p 
)
+
+ +

Evaluate the given PC expansion at given set of points with given coefficient vector and return the values in an 1D Array in the first argument.

+
Todo:
There is no double* version of this function
+ +
+
+ +

◆ Exp() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Exp (const double * p1,
double * p2 
) const
+
+ +

Take the exp() of the PC expansion given by double* argument p1, and return the result in p2.

+

Relies on Taylor series expansion: exp(x) = 1 + x + x^2/2! + x^3/3! + ... However, for efficiency and to avoid overflow, the terms are computed as d_i = d_{i-1}*x/i. Also, to reduce the number of terms needed in the series, we subtract the mean out of a random variable u as u = u_0 + (u-u_0) and exp(u) = exp(u_0)*exp(u-u_0), where exp(u_0) can be computed with the regular exp(double& ) function

Note
The Taylor series is truncated after a tolerance criterium is achieved on the relative error defined as the max absolute value of the PC coefficients in the last added term, divided by the mean of exp(p1). The tolerance is set to 1.e-6 by default and can be changed with SetTaylorTolerance().
+
+The maximum number of terms in the Taylor series is set by default to 500 and can be changed with SetTaylorTermsMax()
+ +
+
+ +

◆ Exp() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Exp (const Array1D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Take the exp() of the PC expansion given by Array1D argument p1, and return the result in p2.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ GalerkProjection()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::GalerkProjection (const Array1D< double > & fcn,
Array1D< double > & ck 
)
+
+ +

Galerkin projection functionalities.

+

Performs (NISP) Galerkin projection, given function evaluations at quadrature points Returns in the coefficient vector in the second argument

Note
User should make sure that the function HAS BEEN evaluated at the correct quadrature points by first extracting the quadrature points and evaluating the function externally
+
Todo:

Overload this with forward function pointers

+

There is no double* version of this function

+
+ +
+
+ +

◆ GalerkProjectionMC()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::GalerkProjectionMC (const Array2D< double > & x,
const Array1D< double > & fcn,
Array1D< double > & ck 
)
+
+ +

Galerkin Projection via Monte-Carlo integration.

+
Note
User should make sure that the function HAS BEEN evaluated at the correct sampling points by first sampling the proper PC germ distribution and evaluating the function externally
+
Todo:

Overload this with forward function pointers

+

There is no double* version of this function

+
+ +
+
+ +

◆ GetAlpha()

+ +
+
+ + + + + +
+ + + + + + + +
double PCSet::GetAlpha () const
+
+inline
+
+ +

Get the value of the parameter alpha.

+ +
+
+ +

◆ GetBeta()

+ +
+
+ + + + + +
+ + + + + + + +
double PCSet::GetBeta () const
+
+inline
+
+ +

Get the value of the parameter beta.

+ +
+
+ +

◆ GetGMRESDivTolerance()

+ +
+
+ + + + + +
+ + + + + + + +
double PCSet::GetGMRESDivTolerance () const
+
+inline
+
+ +

Get relative tolerance for GMRES in Div routine.

+ +
+
+ +

◆ GetModesRMS() [1/2]

+ +
+
+ + + + + + + + +
double PCSet::GetModesRMS (const double * p) const
+
+ +

Compute the rms average of the PC coefficients (i.e. the square root of the average of the square of the PC coefficients, not taking into account any basis functions). (Arguments in double* format)

+ +
+
+ +

◆ GetModesRMS() [2/2]

+ +
+
+ + + + + + + + +
double PCSet::GetModesRMS (const Array1D< double > & p) const
+
+ +

Compute the rms average of the PC coefficients (i.e. the square root of the average of the square of the PC coefficients, not taking into account any basis functions). (Arguments in Array1D<double> format)

+
Note
Requires the size of the array that is passed in to equal the number of PC terms
+ +
+
+ +

◆ GetMultiIndex() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetMultiIndex (Array2D< int > & mindex) const
+
+inline
+
+ +

Get the multiindex (return Array2D)

+ +
+
+ +

◆ GetMultiIndex() [2/2]

+ +
+
+ + + + + + + + +
void PCSet::GetMultiIndex (int * mindex) const
+
+ +

Get the multiindex (return double *)

+ +
+
+ +

◆ GetNDim()

+ +
+
+ + + + + +
+ + + + + + + +
int PCSet::GetNDim () const
+
+inline
+
+ +

Get the PC dimensionality.

+ +
+
+ +

◆ GetNormSq()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetNormSq (Array1D< double > & normsq) const
+
+inline
+
+ +

Get the norm-squared.

+
Todo:
this seems like a duplication, see below GetPsiSq()
+ +
+
+ +

◆ GetNQuadPoints()

+ +
+
+ + + + + +
+ + + + + + + +
int PCSet::GetNQuadPoints () const
+
+inline
+
+ +

Get the number of quadrature points.

+ +
+
+ +

◆ GetNumberPCTerms()

+ +
+
+ + + + + +
+ + + + + + + +
int PCSet::GetNumberPCTerms () const
+
+inline
+
+ +

Get the number of terms in a PC expansion of this order and dimension.

+ +
+
+ +

◆ GetNumQuadProd()

+ +
+
+ + + + + + + +
int PCSet::GetNumQuadProd () const
+
+ +

Returns number of quad products.

+ +
+
+ +

◆ GetNumTripleProd()

+ +
+
+ + + + + + + +
int PCSet::GetNumTripleProd () const
+
+ +

Returns number of triple products.

+ +
+
+ +

◆ GetOrder()

+ +
+
+ + + + + +
+ + + + + + + +
int PCSet::GetOrder () const
+
+inline
+
+ +

Get the PC order.

+ +
+
+ +

◆ GetPCType()

+ +
+
+ + + + + +
+ + + + + + + +
string PCSet::GetPCType () const
+
+inline
+
+ +

Get and set variables/arrays inline.

+

Get the PC type

+ +
+
+ +

◆ GetPsi() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetPsi (Array2D< double > & psi) const
+
+inline
+
+ +

Get the values of the basis polynomials evaluated at the quadrature points.

+ +
+
+ +

◆ GetPsi() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetPsi (double * psi) const
+
+inline
+
+ +

Get the polynomials evaluated at the quadrature points folded into a one-dimensional array psi.

+ +
+
+ +

◆ GetPsiSq() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetPsiSq (Array1D< double > & psisq) const
+
+inline
+
+ +

Get the basis polynomial norms-squared in an array class object psisq.

+ +
+
+ +

◆ GetPsiSq() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetPsiSq (double * psisq) const
+
+inline
+
+ +

Get the basis polynomial norms-squared in a double* array psisq.

+ +
+
+ +

◆ GetQuadPoints() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetQuadPoints (Array2D< double > & quad) const
+
+inline
+
+ +

Get the quadrature points.

+ +
+
+ +

◆ GetQuadPoints() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetQuadPoints (double * quad) const
+
+inline
+
+ +

Get the quadrature points folded into a one-dimensional array quad.

+ +
+
+ +

◆ GetQuadPointsWeights()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PCSet::GetQuadPointsWeights (Array2D< double > & quad,
Array1D< double > & wghts 
) const
+
+inline
+
+ +

Get the quadrature points and weights.

+ +
+
+ +

◆ GetQuadProd() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::GetQuadProd (int * nQuad,
int * iProd,
int * jProd,
int * kProd,
double * Cijkl 
) const
+
+ +

Returns quad products indices (int*/double* version)

+ +
+
+ +

◆ GetQuadProd() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::GetQuadProd (Array1D< int > & nQuad,
Array1D< int > & iProd,
Array1D< int > & jProd,
Array1D< int > & kProd,
Array1D< double > & Cijkl 
) const
+
+ +

Returns quad products indices (Array version)

+ +
+
+ +

◆ GetQuadWeights() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetQuadWeights (Array1D< double > & wghts) const
+
+inline
+
+ +

Get the quadrature weights.

+ +
+
+ +

◆ GetQuadWeights() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::GetQuadWeights (double * wghts) const
+
+inline
+
+ +

Get the quadrature weights folded into a one-dimensional array wghts.

+ +
+
+ +

◆ GetTaylorTermsMax()

+ +
+
+ + + + + +
+ + + + + + + +
int PCSet::GetTaylorTermsMax () const
+
+inline
+
+ +

Get maximum number of terms in Taylor series approximations.

+ +
+
+ +

◆ GetTaylorTolerance()

+ +
+
+ + + + + +
+ + + + + + + +
double PCSet::GetTaylorTolerance () const
+
+inline
+
+ +

Get relative tolerance for Taylor series approximations.

+ +
+
+ +

◆ GetTripleProd() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::GetTripleProd (int * nTriple,
int * iProd,
int * jProd,
double * Cijk 
) const
+
+ +

Returns triple products indices (int*/double* version)

+ +
+
+ +

◆ GetTripleProd() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::GetTripleProd (Array1D< int > & nTriple,
Array1D< int > & iProd,
Array1D< int > & jProd,
Array1D< double > & Cijk 
) const
+
+ +

Returns triple products indices (Array version)

+ +
+
+ +

◆ GMRESMatrixVectorProd()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::GMRESMatrixVectorProd (const double * x,
const double * a,
double * y 
) const
+
+private
+
+ +

Actual C++ implementation of the matric vector multiplication for GMRES for the division operation.

+

Given the structure of the problem, this boils down to the product between two PC variables.

+ +
+
+ +

◆ GMRESMatrixVectorProdWrapper()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
static void PCSet::GMRESMatrixVectorProdWrapper (int * n,
double * x,
double * y,
int * nelt,
int * ia,
int * ja,
double * a,
int * obj 
)
+
+inlinestaticprivate
+
+ +

Wrapper for Matrix-vector multiplication routine to be called by GMRES.

+

As GMRES is a Fortran77 routine, this routine is defined as a static function. One of the function arguments (obj) was originally isym, a flag for matrix symmetry, but has been repurposed to carry an integer handle to identify this object.

Note
The matrix vector product here comes down to a product between two PC expansions.
+ +
+
+ +

◆ GMRESPreCondWrapper()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
static void PCSet::GMRESPreCondWrapper (int * n,
double * r,
double * z,
int * nelt,
int * ia,
int * ja,
double * a,
int * obj,
double * rwork,
int * iwork 
)
+
+inlinestaticprivate
+
+ +

Wrapper for preconditioner routine to be called by GMRES.

+

As GMRES is a Fortran77 routine, this routine is defined as a static function. One of the function arguments (obj) was originally isym, a flag for matrix symmetry, but has been repurposed to carry an integer handle to identify this object.

Note
Since we currently do not use preconditioning, this routine does nothing. It is a place holder for future use.
+ +
+
+ +

◆ Initialize()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::Initialize (const string ordertype)
+
+private
+
+ +

Initialization of the appropriate variables.

+
Note
Intrusive implementation only works with TotalOrder multiindes
+
Todo:
Test and allow intrusive implementation with customized multiindices
+ +
+
+ +

◆ InitISP()

+ +
+
+ + + + + +
+ + + + + + + +
void PCSet::InitISP ()
+
+private
+
+ +

Initialize quadrature for computing triple products(ISP) and orthogonal projection(NISP)

+

Initialize variables that are needed only in intrusive computations

+ +
+
+ +

◆ InitMeanStDv() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::InitMeanStDv (const double & m,
const double & s,
double * p 
) const
+
+ +

Intrusive arithmetics.

+

Initializes a PC expansion p in a double* format to have the same distribution as the underlying PC germ, but with a specified mean m and standard deviation s

Note
This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general
+
+This function only holds for expansions with one stochastic dimension
+
+All existing coefficient values in p will be overwritten
+
Todo:
Make this function work for general multi-indices, and for any number of stochastic dimensions
+ +
+
+ +

◆ InitMeanStDv() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::InitMeanStDv (const double & m,
const double & s,
Array1D< double > & p 
) const
+
+ +

Initializes a PC expansion p in Array1D<double> format to have the same distribution as the underlying PC germ, but with a specified mean m and standard deviation s.

+
Note
This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general
+
+This function only holds for expansions with one stochastic dimension
+
+All existing coefficient values in p will be overwritten
+
Todo:
Make this function work for general multi-indices, and for any number of stochastic dimensions
+ +
+
+ +

◆ InitNISP()

+ +
+
+ + + + + +
+ + + + + + + +
void PCSet::InitNISP ()
+
+private
+
+ +

Initialize variables that are needed only in non-intrusive computations.

+ +
+
+ +

◆ Inv() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Inv (const double * p1,
double * p2 
) const
+
+ +

Evaluate the inverse of PC expansion given by double* argument p1, and return the result in p2. The inverse is computed using the division function.

+ +
+
+ +

◆ Inv() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Inv (const Array1D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Evaluate the inverse of PC expansion given by Array1D argument p1, and return the result in Array1D argument p2.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ IPow() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::IPow (const double * p1,
double * p2,
const int & ia 
) const
+
+ +

Evaluate power ia (an integer number) of PC expansion given by double* argument p1, and return the result in p2.

+ +
+
+ +

◆ IPow() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::IPow (const Array1D< double > & p1,
Array1D< double > & p2,
const int & ia 
) const
+
+ +

Evaluate power ia (an integer number) of PC expansion given by Array1D argument p1, and return the result in Array1D argument p2.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ IsInDomain()

+ +
+
+ + + + + + + + +
bool PCSet::IsInDomain (double x)
+
+ +

Check if the point x is in the PC domain.

+ +
+
+ +

◆ Log() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Log (const double * p1,
double * p2 
) const
+
+ +

Take the natural logarithm log() of the PC expansion given by double* argument p1, and return the result in p2. The logarithm is evaluated either via Taylor series or via integration depending on the value of parameter logMethod_.

+ +
+
+ +

◆ Log() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Log (const Array1D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Take the natural logarithm, log(), of the PC expansion given by Array1D argument p1, and return the result in Array1D argument p2.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ Log10() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Log10 (const double * p1,
double * p2 
) const
+
+ +

Take the logarithm to base 10 of the PC expansion given by double* argument p1, and return the result in p2.

+

First use Log() to compute the natural logarithm and then divide it by log(10)

+ +
+
+ +

◆ Log10() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::Log10 (const Array1D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Take the logarithm to base 10 of the PC expansion given by Array1D argument p1, and return the result in Array1D argument p2.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ LogInt()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PCSet::LogInt (const double * p1,
double * p2 
) const
+
+private
+
+ +

Computes natural logarithm by numerical integration: calculate p2=ln(p1) by integrating du=dx/x to get ln(x)

+ +
+
+ +

◆ LogIntRhs()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
int PCSet::LogIntRhs (realtype t,
N_Vector y,
N_Vector ydot,
void * f_data 
) const
+
+private
+
+ +

Evaluates rhs necessary to compute natural logarithm via integration.

+ +
+
+ +

◆ LogIntRhsWrapper()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
static int PCSet::LogIntRhsWrapper (realtype t,
N_Vector y,
N_Vector ydot,
void * f_data 
)
+
+inlinestaticprivate
+
+ +

Wrapper for LogIntRhs. The first component of f_data pointer carries an integer handle identifying the appropriate PC object.

+
Todo:
Why is this function a static int instead of static void? Should there be a return statement at the end?
+ +
+
+ +

◆ LogTaylor()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PCSet::LogTaylor (const double * p1,
double * p2 
) const
+
+private
+
+ +

Computes natural logarithm using Taylor expansion: N p2 = ln(p1) = ln(p1Mean) + sum d n=1 n.

+

(n+1) (-1) n p1 where d = -— *x , and x = ---— - 1 n n p1Mean

+
Note
See Exp notes for info related to tolerance and maximum number of terms criteria for truncating the Taylor series
+ +
+
+ +

◆ Multiply() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Multiply (const double * p1,
const double & a,
double * p2 
) const
+
+ +

Multiply PC expansion p1 with scalar a and return the result in p2. All PCEs are in double* format.

+ +
+
+ +

◆ Multiply() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Multiply (const Array1D< double > & p1,
const double & a,
Array1D< double > & p2 
) const
+
+ +

Multiply PC expansion p1 with scalar a and return the result in p2. All PCEs are in Array1D format.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ MultiplyInPlace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::MultiplyInPlace (double * p1,
const double & a 
) const
+
+ +

Multiply PC expansions given by double* argument p1 with scalar a and return the result in p1.

+ +
+
+ +

◆ MultiplyInPlace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::MultiplyInPlace (Array1D< double > & p1,
const double & a 
) const
+
+ +

Multiply PC expansions given by Array1D argument p1 with scalar a and return the result in p1.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ Polyn() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Polyn (const double * polycf,
int npoly,
const double * p1,
double * p2 
) const
+
+ +

Evaluates a polynomial of PC that is given in double* argument p1. Polynomial coefficients are given in double* argument polycf of size npoly. The output PC is contained in double* argument p2.

+
Note
Recursive algorithm is implemented.
+ +
+
+ +

◆ Polyn() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Polyn (const Array1D< double > & polycf,
const Array1D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Evaluates a polynomial of PC that is given by Array1D argument p1. Polynomial coefficients are given in the Array1D argument polycf. The output PC is contained in Array1D argument p2.

+
Note
Requires the size of array p1 to equal the number of PC terms
+ +
+
+ +

◆ PolynMulti()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::PolynMulti (const Array1D< double > & polycf,
const Array2D< int > & mindex,
const Array2D< double > & p1,
Array1D< double > & p2 
) const
+
+ +

Evaluates a multivariate polynomial of a set of PC inputs given by Array2D argument p1 (each column of p1 is a PC input). Polynomial coefficients are given in Array1D argument polycf. Multiindex set for the multivariate polynomial is given in Array2D argument mindex. The output PC is contained in Array1D argument p2.

+
Note
Requires the size of the array polycf to equal the first dimension of argument mindex
+
+Requires the size of the array p1 to equal (the number of PC terms) X (second dimension of argument mindex)
+
+Uses a recursive algorithm
+
+Out of convenience, this function so far is implemented for Array classes, not double* arrays.
+
Todo:
A double* version should be added.
+ +
+
+ +

◆ PrintMultiIndex()

+ +
+
+ + + + + + + +
void PCSet::PrintMultiIndex () const
+
+ +

Print information on the screen.

+

Print the multi-indices for all terms on the screen

+ +
+
+ +

◆ PrintMultiIndexNormSquared()

+ +
+
+ + + + + + + +
void PCSet::PrintMultiIndexNormSquared () const
+
+ +

For all terms, print their multi-index and norm^2 on the screen.

+ +
+
+ +

◆ Prod() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Prod (const double * p1,
const double * p2,
double * p3 
) const
+
+ +

Multiply two PC expansions given by double* arguments p1 and p2, and return the result in p3.

+ +
+
+ +

◆ Prod() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Prod (const Array1D< double > & p1,
const Array1D< double > & p2,
Array1D< double > & p3 
) const
+
+ +

Multipy two PC expansions given by Array1D arguments p1 and p2, and return the result in p3.

+
Note
Requires the size of the input arrays to equal the number of PC terms
+ +
+
+ +

◆ Prod3() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Prod3 (const double * p1,
const double * p2,
const double * p3,
double * p4 
) const
+
+ +

Multiply three PC expansions given by double* arguments p1, p2, and p3, and return the result in p4.

+ +
+
+ +

◆ Prod3() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Prod3 (const Array1D< double > & p1,
const Array1D< double > & p2,
const Array1D< double > & p3,
Array1D< double > & p4 
) const
+
+ +

Multipy three PC expansions given by Array1D arguments p1, p2, and p3, and return the result in p4.

+
Note
Requires the size of the input arrays to equal the number of PC terms
+ +
+
+ +

◆ RPow() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::RPow (const double * p1,
double * p2,
const double & a 
) const
+
+ +

Evaluate power a (a real number) of PC expansion given by double* argument p1, and return the result in p2. The power is computed as p1^a = exp(a*log(p1)), where log(p1) is evaluated either via Taylor series or via integration depending on the value of parameter logMethod_.

+ +
+
+ +

◆ RPow() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::RPow (const Array1D< double > & p1,
Array1D< double > & p2,
const double & a 
) const
+
+ +

Evaluate power a (a real number) of PC expansion given by Array1D argument p1, and return the result in Array1D argument p2.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ SeedBasisRandNumGen()

+ +
+
+ + + + + + + + +
void PCSet::SeedBasisRandNumGen (const int & seed) const
+
+ +

Random sample generator functions.

+

Reseed the random number generator used for the sampling of the PC variables and expansions

+ +
+
+ +

◆ SetGMRESDivTolerance()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::SetGMRESDivTolerance (const double & rTol)
+
+inline
+
+ +

Set the relative tolerance for GMRES in Div routine.

+ +
+
+ +

◆ SetLogCompMethod()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::SetLogCompMethod (const LogCompMethodlogMethod)
+
+inline
+
+ +

Set method of computing the log function.

+

Use the argument TaylorSeries to select the Taylor series approach or Integration to select the integration method.

+ +
+
+ +

◆ SetQd1d()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::SetQd1d (Array1D< double > & qdpts1d,
Array1D< double > & wghts1d,
int nqd 
)
+
+ +

Set the quadrature rule.

+

Obtain 1d quadrature points and weights

Note
This is used in triple or quadruple product computation for which the default quadrature is not enough
+ +
+
+ +

◆ SetQuadRule() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::SetQuadRule (const string grid_type,
const string fs_type,
int param 
)
+
+ +

Set the quadrature points by specifying a grid type, a full/sparse indicator, and an integer parameter.

+

Full/sparse switch fs_type can be either 'full' or 'sparse' The parameter param is the number of points per dimension for full quadrature, and the level for sparse quadrature Options for grid_type are, besides the standard PC types, 'CC' (Clenshaw-Curtis), 'CCO' (Clenshaw-Curtis open), 'NC' (Newton-Cotes), 'NCO' (Newton-Cotes open), where open means that endpoints are expluded

Note
'NC', 'NCO' quadratures are the same as uniformly spaced grids
+
Todo:
Need to improve it
+ +
+
+ +

◆ SetQuadRule() [2/2]

+ +
+
+ + + + + + + + +
void PCSet::SetQuadRule (QuadquadRule)
+
+ +

Set a custom quadrature rule by pointing to the corresponding object.

+ +
+
+ +

◆ SetTaylorTermsMax()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::SetTaylorTermsMax (const int & maxTerm)
+
+inline
+
+ +

Set maximum number of terms in Taylor series approximations.

+ +
+
+ +

◆ SetTaylorTolerance()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::SetTaylorTolerance (const double & rTol)
+
+inline
+
+ +

Set relative tolerance for Taylor series approximations.

+ +
+
+ +

◆ SetVerbosity()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCSet::SetVerbosity (int verbosity)
+
+inline
+
+ +

Other.

+

Set the verbosity level

Note
Currently, the values of 0, 1 and 2 are implemented
+ +
+
+ +

◆ StDv() [1/2]

+ +
+
+ + + + + + + + +
double PCSet::StDv (const double * p) const
+
+ +

Returns the standard deviation of PC expansion p in a double* format.

+
Note
This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general
+
Todo:
Lift the assumption by looking for the constant term in the multiindex
+ +
+
+ +

◆ StDv() [2/2]

+ +
+
+ + + + + + + + +
double PCSet::StDv (const Array1D< double > & p) const
+
+ +

Returns the standard deviation of PC expansion p (Argument in Array1D<double> format)

+
Note
This assumes that the zeroth order term is the first one in the multi-index - this assumption does not hold in general
+
Todo:
Lift the assumption by looking for the constant term in the multiindex
+
Note
For a more general implementation, see ComputeVarFrac()
+ +
+
+ +

◆ Subtract() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Subtract (const double * p1,
const double * p2,
double * p3 
) const
+
+ +

Subtract PC expansion p2 from p1, and return the result in p3, with all arguments given as double*.

+ +
+
+ +

◆ Subtract() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void PCSet::Subtract (const Array1D< double > & p1,
const Array1D< double > & p2,
Array1D< double > & p3 
) const
+
+ +

Subtract PC expansion p2 from p1, and return the result in p3, with all arguments given as Array1D structures.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+ +

◆ SubtractInPlace() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::SubtractInPlace (double * p1,
const double * p2 
) const
+
+ +

Subtract PC expansion p2 from p1, and return the result in p1, with all arguments given as double*.

+ +
+
+ +

◆ SubtractInPlace() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void PCSet::SubtractInPlace (Array1D< double > & p1,
const Array1D< double > & p2 
) const
+
+ +

Subtract PC expansion p2 from p1, and return the result in p1, with all arguments given as Array1D structures.

+
Note
Requires the size of the arrays that are passed in to equal the number of PC terms
+ +
+
+

Member Data Documentation

+ +

◆ alpha_

+ +
+
+ + + + + +
+ + + + +
double PCSet::alpha_
+
+private
+
+ +

Parameter alpha for PCs that require a parameter (GLG,SW,JB)

+ +
+
+ +

◆ beta_

+ +
+
+ + + + + +
+ + + + +
double PCSet::beta_
+
+private
+
+ +

Parameter beta for PCs that require two parameters (SW,JB)

+ +
+
+ +

◆ CVabst_

+ +
+
+ + + + + +
+ + + + +
double PCSet::CVabst_
+
+private
+
+ +

CVODE parameter: absolute tolerance.

+ +
+
+ +

◆ CVinitstep_

+ +
+
+ + + + + +
+ + + + +
double PCSet::CVinitstep_
+
+private
+
+ +

CVODE parameter: initial step size.

+ +
+
+ +

◆ CVmaxnumsteps_

+ +
+
+ + + + + +
+ + + + +
int PCSet::CVmaxnumsteps_
+
+private
+
+ +

CVODE parameter: maximal number of steps.

+ +
+
+ +

◆ CVmaxord_

+ +
+
+ + + + + +
+ + + + +
int PCSet::CVmaxord_
+
+private
+
+ +

CVODE parameter: maximal order.

+ +
+
+ +

◆ CVmaxstep_

+ +
+
+ + + + + +
+ + + + +
double PCSet::CVmaxstep_
+
+private
+
+ +

CVODE parameter: maximal step size.

+ +
+
+ +

◆ CVrelt_

+ +
+
+ + + + + +
+ + + + +
double PCSet::CVrelt_
+
+private
+
+ +

CVODE parameter: relative tolerance.

+ +
+
+ +

◆ iProd2_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<int> > PCSet::iProd2_
+
+private
+
+ +

i-indices of <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k

+
Note
Stored as a vector over k, with each element being a vector of i-indices itself
+ +
+
+ +

◆ iProd3_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<int> > PCSet::iProd3_
+
+private
+
+ +

i-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l

+
Note
Stored as a vector over l, with each element being a vector of i-indices itself
+ +
+
+ +

◆ jProd2_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<int> > PCSet::jProd2_
+
+private
+
+ +

j-indices of <\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k

+
Note
Stored as a vector over k, with each element being a vector of j-indices itself
+ +
+
+ +

◆ jProd3_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<int> > PCSet::jProd3_
+
+private
+
+ +

j-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l

+
Note
Stored as a vector over l, with each element being a vector of j-indices itself
+ +
+
+ +

◆ kProd3_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<int> > PCSet::kProd3_
+
+private
+
+ +

k-indices of <\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l

+
Note
Stored as a vector over l, with each element being a vector of k-indices itself
+ +
+
+ +

◆ logMethod_

+ +
+
+ + + + + +
+ + + + +
LogCompMethod PCSet::logMethod_
+
+private
+
+ +

Flag for method to compute log: TaylorSeries or Integration.

+ +
+
+ +

◆ maxorddim_

+ +
+
+ + + + + +
+ + + + +
int PCSet::maxorddim_
+
+private
+
+ +

Maximal order within all dimensions.

+ +
+
+ +

◆ maxOrders_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> PCSet::maxOrders_
+
+private
+
+ +

Array of maximum orders requested if custom(HDMR) ordering is requested.

+ +
+
+ +

◆ maxOrdPerDim_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> PCSet::maxOrdPerDim_
+
+private
+
+ +

Array of maximum orders per dimension.

+ +
+
+ +

◆ maxTermTaylor_

+ +
+
+ + + + + +
+ + + + +
int PCSet::maxTermTaylor_
+
+private
+
+ +

Max number of terms in Taylor series approximations.

+ +
+
+ +

◆ multiIndex_

+ +
+
+ + + + + +
+ + + + +
Array2D<int> PCSet::multiIndex_
+
+private
+
+ +

Array to store multi-index: multiIndex_(ipc,idim) contains the order of the basis function associated with dimension idim, for the ipc-th term in the PC expansion.

+ +
+
+ +

◆ my_index_

+ +
+
+ + + + + +
+ + + + +
int PCSet::my_index_
+
+private
+
+ +

Index of this class.

+ +
+
+ +

◆ narg_

+ +
+
+ + + + + +
+ + + + +
int PCSet::narg_
+
+private
+
+ +

Number of free parameters to specify the basis.

+ +
+
+ +

◆ nDim_

+ +
+
+ + + + + +
+ + + + +
const int PCSet::nDim_
+
+private
+
+ +

Number of stochastic dimensions (degrees of freedom) in the PC representation.

+ +
+
+ +

◆ next_index_

+ +
+
+ + + + + +
+ + + + +
int PCSet::next_index_ = 0
+
+staticprivate
+
+ +

index of next object in map

+ +
+
+ +

◆ nPCTerms_

+ +
+
+ + + + + +
+ + + + +
int PCSet::nPCTerms_
+
+private
+
+ +

Total number of terms in the PC expansions.

+ +
+
+ +

◆ nQuadPoints_

+ +
+
+ + + + + +
+ + + + +
int PCSet::nQuadPoints_
+
+private
+
+ +

Number of quadrature points used.

+ +
+
+ +

◆ omap_

+ +
+
+ + + + + +
+ + + + +
PCSet::OMap_t * PCSet::omap_ = NULL
+
+staticprivate
+
+ +

Map to connect integer indexes with pointers to this class.

+ +
+
+ +

◆ order_

+ +
+
+ + + + + +
+ + + + +
int PCSet::order_
+
+private
+
+ +

Order of the PC representation.

+ +
+
+ +

◆ p_basis_

+ +
+
+ + + + + +
+ + + + +
PCBasis* PCSet::p_basis_
+
+private
+
+ +

Pointer to the class that defines the basis type and functions.

+ +
+
+ +

◆ pcSeq_

+ +
+
+ + + + + +
+ + + + +
string PCSet::pcSeq_
+
+private
+
+ +

String indicator of multiindex ordering.

+ +
+
+ +

◆ pcType_

+ +
+
+ + + + + +
+ + + + +
string PCSet::pcType_
+
+private
+
+ +

String indicator of PC type.

+ +
+
+ +

◆ psi_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> PCSet::psi_
+
+private
+
+ +

Array to store basis functions evaluated at quadrature points for each order: psi_(iqp,ipc) contains the value of the polynomial chaos ipc-th basis at the location of quadrature point iqp.

+ +
+
+ +

◆ psiIJKLProd3_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<double> > PCSet::psiIJKLProd3_
+
+private
+
+ +

<\Psi_i \Psi_j \Psi_k \Psi_l> terms that are not zero, for all l

+
Note
Stored as a vector over l, with each element being a vector of <\Psi_i \Psi_j \Psi_k \Psi_l> values
+ +
+
+ +

◆ psiIJKProd2_

+ +
+
+ + + + + +
+ + + + +
Array1D<Array1D<double> > PCSet::psiIJKProd2_
+
+private
+
+ +

<\Psi_i \Psi_j \Psi_k> terms that are not zero, for all k

+
Note
Stored as a vector over k, with each element being a vector of <\Psi_i \Psi_j \Psi_k> values
+ +
+
+ +

◆ psiSq_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> PCSet::psiSq_
+
+private
+
+ +

Array with the norms squared of the basis functions, corresponding to each term in the PC expansion.

+ +
+
+ +

◆ quadIndices_

+ +
+
+ + + + + +
+ + + + +
Array2D<int> PCSet::quadIndices_
+
+private
+
+ +

Array to store quadrature point indexing; useful for nested rules.

+ +
+
+ +

◆ quadPoints_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> PCSet::quadPoints_
+
+private
+
+ +

Array to store quadrature points.

+ +
+
+ +

◆ quadWeights_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> PCSet::quadWeights_
+
+private
+
+ +

Array to store quadrature weights.

+ +
+
+ +

◆ rTolGMRESDiv_

+ +
+
+ + + + + +
+ + + + +
double PCSet::rTolGMRESDiv_
+
+private
+
+ +

GMRES tolerance in Div()

+ +
+
+ +

◆ rTolTaylor_

+ +
+
+ + + + + +
+ + + + +
double PCSet::rTolTaylor_
+
+private
+
+ +

Relative tolerance for Taylor series approximations.

+ +
+
+ +

◆ SMALL_

+ +
+
+ + + + + +
+ + + + +
double PCSet::SMALL_
+
+private
+
+ +

Tolerance to avoid floating-point errors.

+ +
+
+ +

◆ spType_

+ +
+
+ + + + + +
+ + + + +
string PCSet::spType_
+
+private
+
+ +

String indicator of ISP or NISP implementation type.

+ +
+
+ +

◆ uqtkverbose_

+ +
+
+ + + + + +
+ + + + +
int PCSet::uqtkverbose_
+
+private
+
+ +

Verbosity level.

+
Note
Currently the values of 0, 1 or 2 are implemented.
+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classPCreg-members.html b/doc/doxygen/html/classPCreg-members.html new file mode 100644 index 00000000..e80b660f --- /dev/null +++ b/doc/doxygen/html/classPCreg-members.html @@ -0,0 +1,109 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
PCreg Member List
+
+
+ +

This is the complete list of members for PCreg, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A_Lregprotected
A_inv_Lregprotected
BCS_BuildRegr(Array1D< int > &selected, double eta)Lreg
bdata_Lregprotected
coef_Lregprotected
coef_cov_Lregprotected
coef_erb_Lregprotected
computeErrorMetrics(string method)Lreg
computeRVE(Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)Lreg
diagP_Lregprotected
diagPFlag_Lregprotected
EvalBases(Array2D< double > &xx, Array2D< double > &bb)PCregvirtual
EvalRegr(Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)Lreg
GetCoef(Array1D< double > &coef)Lreginline
GetCoefCov(Array2D< double > &coef_cov)Lreginline
getDiagP()Lreg
GetMindex(Array2D< int > &mindex)PCreginlinevirtual
GetNbas() constLreginline
GetNdim() constLreginline
GetNpt() constLreginline
getResid()Lreg
GetSigma2() constLreginline
Hty_Lregprotected
InitRegr()Lreg
Lreg()Lreginline
LSQ_BuildRegr()Lreg
LSQ_computeBestLambda()Lreg
LSQ_computeBestLambdas()Lreg
mindex_PCregprivate
nbas_Lregprotected
ndim_Lregprotected
npt_Lregprotected
PCreg(string strpar, int order, int dim)PCreg
PCreg(string strpar, Array2D< int > &mindex)PCreg
pctype_PCregprivate
Proj(Array1D< double > &array, Array1D< double > &proj_array)Lreg
resid_Lregprotected
residFlag_Lregprotected
SetCenters(Array2D< double > &centers)Lreginlinevirtual
SetMindex(Array2D< int > &mindex)PCreginlinevirtual
SetParamsRBF()Lreginlinevirtual
SetRegMode(string regmode)Lreginline
SetRegWeights(Array1D< double > &weights)Lreg
SetupData(Array2D< double > &xdata, Array1D< double > &ydata)Lreg
SetupData(Array2D< double > &xdata, Array2D< double > &ydata)Lreg
SetWidths(Array1D< double > &widths)Lreginlinevirtual
sigma2_Lregprotected
StripBases(Array1D< int > &used)PCregvirtual
weights_Lregprotected
xdata_Lregprotected
ydata_Lregprotected
~Lreg()Lreginline
~PCreg()PCreginline
+ + + + diff --git a/doc/doxygen/html/classPCreg.html b/doc/doxygen/html/classPCreg.html new file mode 100644 index 00000000..8f860ee2 --- /dev/null +++ b/doc/doxygen/html/classPCreg.html @@ -0,0 +1,519 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PCreg Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Derived class for PC regression. + More...

+ +

#include <lreg.h>

+
+Inheritance diagram for PCreg:
+
+
+ + +Lreg + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 PCreg (string strpar, int order, int dim)
 Constructors: More...
 
 PCreg (string strpar, Array2D< int > &mindex)
 
 ~PCreg ()
 Destructor. More...
 
void EvalBases (Array2D< double > &xx, Array2D< double > &bb)
 Evaluate the bases. More...
 
void StripBases (Array1D< int > &used)
 Strip the bases. More...
 
void SetMindex (Array2D< int > &mindex)
 Set multiindex. More...
 
void GetMindex (Array2D< int > &mindex)
 Get multiindex. More...
 
- Public Member Functions inherited from Lreg
 Lreg ()
 Constructor. More...
 
 ~Lreg ()
 Destrcutor. More...
 
virtual void SetCenters (Array2D< double > &centers)
 Set centers (for RBF) More...
 
virtual void SetWidths (Array1D< double > &widths)
 Set widths (for RBF) More...
 
virtual void SetParamsRBF ()
 Set parameters (for RBF) More...
 
void InitRegr ()
 Initialize. More...
 
void SetupData (Array2D< double > &xdata, Array1D< double > &ydata)
 Setup data (1d ydata) More...
 
void SetupData (Array2D< double > &xdata, Array2D< double > &ydata)
 Setup data (2d ydata) More...
 
void SetRegMode (string regmode)
 Set the regression mode. More...
 
void SetRegWeights (Array1D< double > &weights)
 Set weights. More...
 
void BCS_BuildRegr (Array1D< int > &selected, double eta)
 Build BCS regression. More...
 
void LSQ_BuildRegr ()
 Build LSQ regression. More...
 
void EvalRegr (Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)
 Evaluate the regression expansion. More...
 
int GetNpt () const
 Get the number of points. More...
 
int GetNdim () const
 Get dimensionality. More...
 
int GetNbas () const
 Get the number of bases. More...
 
double GetSigma2 () const
 Get the variance. More...
 
void GetCoefCov (Array2D< double > &coef_cov)
 Get coefficient covariance. More...
 
void GetCoef (Array1D< double > &coef)
 Get coefficients. More...
 
void Proj (Array1D< double > &array, Array1D< double > &proj_array)
 Project. More...
 
Array1D< double > LSQ_computeBestLambdas ()
 Compute the best values for regulariation parameter vector lambda, for LSQ. More...
 
double LSQ_computeBestLambda ()
 Compute the best value for regulariation parameter lambda, for LSQ. More...
 
void getResid ()
 Compute the residual vector, if not already computed. More...
 
void getDiagP ()
 Compute the diagonal of projection matrix, if not already computed. More...
 
Array1D< double > computeErrorMetrics (string method)
 Compote error according to a selected metrics. More...
 
double computeRVE (Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)
 Compute validation error. More...
 
+ + + + + + + +

+Private Attributes

Array2D< int > mindex_
 Multiindex. More...
 
string pctype_
 PC type. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Lreg
Array2D< double > xdata_
 xdata array More...
 
Array1D< double > ydata_
 ydata array More...
 
int npt_
 Number of samples. More...
 
int nbas_
 Number of bases. More...
 
int ndim_
 Dimensionality. More...
 
double sigma2_
 Variance. More...
 
Array1D< double > weights_
 Weights. More...
 
Array1D< double > resid_
 Residuals. More...
 
bool residFlag_
 Flag to indicate whether residual is computed. More...
 
Array1D< double > diagP_
 Diagonal of projection matrix. More...
 
bool diagPFlag_
 Flag to indicate whether diagonal of projetion matrix is computed. More...
 
Array2D< double > bdata_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_inv_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > coef_cov_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > Hty_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_erb_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
+

Detailed Description

+

Derived class for PC regression.

+

Constructor & Destructor Documentation

+ +

◆ PCreg() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
PCreg::PCreg (string strpar,
int order,
int dim 
)
+
+ +

Constructors:

+ +
+
+ +

◆ PCreg() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
PCreg::PCreg (string strpar,
Array2D< int > & mindex 
)
+
+ +
+
+ +

◆ ~PCreg()

+ +
+
+ + + + + +
+ + + + + + + +
PCreg::~PCreg ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ EvalBases()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PCreg::EvalBases (Array2D< double > & xx,
Array2D< double > & bb 
)
+
+virtual
+
+ +

Evaluate the bases.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ GetMindex()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCreg::GetMindex (Array2D< int > & mindex)
+
+inlinevirtual
+
+ +

Get multiindex.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ SetMindex()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCreg::SetMindex (Array2D< int > & mindex)
+
+inlinevirtual
+
+ +

Set multiindex.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ StripBases()

+ +
+
+ + + + + +
+ + + + + + + + +
void PCreg::StripBases (Array1D< int > & used)
+
+virtual
+
+ +

Strip the bases.

+ +

Reimplemented from Lreg.

+ +
+
+

Member Data Documentation

+ +

◆ mindex_

+ +
+
+ + + + + +
+ + + + +
Array2D<int> PCreg::mindex_
+
+private
+
+ +

Multiindex.

+ +
+
+ +

◆ pctype_

+ +
+
+ + + + + +
+ + + + +
string PCreg::pctype_
+
+private
+
+ +

PC type.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classPCreg.png b/doc/doxygen/html/classPCreg.png new file mode 100644 index 00000000..fa9d4bba Binary files /dev/null and b/doc/doxygen/html/classPCreg.png differ diff --git a/doc/doxygen/html/classPLreg-members.html b/doc/doxygen/html/classPLreg-members.html new file mode 100644 index 00000000..8d49a388 --- /dev/null +++ b/doc/doxygen/html/classPLreg-members.html @@ -0,0 +1,108 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
PLreg Member List
+
+
+ +

This is the complete list of members for PLreg, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A_Lregprotected
A_inv_Lregprotected
BCS_BuildRegr(Array1D< int > &selected, double eta)Lreg
bdata_Lregprotected
coef_Lregprotected
coef_cov_Lregprotected
coef_erb_Lregprotected
computeErrorMetrics(string method)Lreg
computeRVE(Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)Lreg
diagP_Lregprotected
diagPFlag_Lregprotected
EvalBases(Array2D< double > &xx, Array2D< double > &bb)PLregvirtual
EvalRegr(Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)Lreg
GetCoef(Array1D< double > &coef)Lreginline
GetCoefCov(Array2D< double > &coef_cov)Lreginline
getDiagP()Lreg
GetMindex(Array2D< int > &mindex)PLreginlinevirtual
GetNbas() constLreginline
GetNdim() constLreginline
GetNpt() constLreginline
getResid()Lreg
GetSigma2() constLreginline
Hty_Lregprotected
InitRegr()Lreg
Lreg()Lreginline
LSQ_BuildRegr()Lreg
LSQ_computeBestLambda()Lreg
LSQ_computeBestLambdas()Lreg
mindex_PLregprivate
nbas_Lregprotected
ndim_Lregprotected
npt_Lregprotected
PLreg(int order, int dim)PLreg
PLreg(Array2D< int > &mindex)PLreg
Proj(Array1D< double > &array, Array1D< double > &proj_array)Lreg
resid_Lregprotected
residFlag_Lregprotected
SetCenters(Array2D< double > &centers)Lreginlinevirtual
SetMindex(Array2D< int > &mindex)PLreginlinevirtual
SetParamsRBF()Lreginlinevirtual
SetRegMode(string regmode)Lreginline
SetRegWeights(Array1D< double > &weights)Lreg
SetupData(Array2D< double > &xdata, Array1D< double > &ydata)Lreg
SetupData(Array2D< double > &xdata, Array2D< double > &ydata)Lreg
SetWidths(Array1D< double > &widths)Lreginlinevirtual
sigma2_Lregprotected
StripBases(Array1D< int > &used)PLregvirtual
weights_Lregprotected
xdata_Lregprotected
ydata_Lregprotected
~Lreg()Lreginline
~PLreg()PLreginline
+ + + + diff --git a/doc/doxygen/html/classPLreg.html b/doc/doxygen/html/classPLreg.html new file mode 100644 index 00000000..dcb05b70 --- /dev/null +++ b/doc/doxygen/html/classPLreg.html @@ -0,0 +1,476 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: PLreg Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Derived class for polynomial regression. + More...

+ +

#include <lreg.h>

+
+Inheritance diagram for PLreg:
+
+
+ + +Lreg + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 PLreg (int order, int dim)
 Constructors: More...
 
 PLreg (Array2D< int > &mindex)
 
 ~PLreg ()
 Destructor. More...
 
void EvalBases (Array2D< double > &xx, Array2D< double > &bb)
 Evaluate the bases. More...
 
void StripBases (Array1D< int > &used)
 Strip the bases. More...
 
void SetMindex (Array2D< int > &mindex)
 Set multiindex. More...
 
void GetMindex (Array2D< int > &mindex)
 Get multiindex. More...
 
- Public Member Functions inherited from Lreg
 Lreg ()
 Constructor. More...
 
 ~Lreg ()
 Destrcutor. More...
 
virtual void SetCenters (Array2D< double > &centers)
 Set centers (for RBF) More...
 
virtual void SetWidths (Array1D< double > &widths)
 Set widths (for RBF) More...
 
virtual void SetParamsRBF ()
 Set parameters (for RBF) More...
 
void InitRegr ()
 Initialize. More...
 
void SetupData (Array2D< double > &xdata, Array1D< double > &ydata)
 Setup data (1d ydata) More...
 
void SetupData (Array2D< double > &xdata, Array2D< double > &ydata)
 Setup data (2d ydata) More...
 
void SetRegMode (string regmode)
 Set the regression mode. More...
 
void SetRegWeights (Array1D< double > &weights)
 Set weights. More...
 
void BCS_BuildRegr (Array1D< int > &selected, double eta)
 Build BCS regression. More...
 
void LSQ_BuildRegr ()
 Build LSQ regression. More...
 
void EvalRegr (Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)
 Evaluate the regression expansion. More...
 
int GetNpt () const
 Get the number of points. More...
 
int GetNdim () const
 Get dimensionality. More...
 
int GetNbas () const
 Get the number of bases. More...
 
double GetSigma2 () const
 Get the variance. More...
 
void GetCoefCov (Array2D< double > &coef_cov)
 Get coefficient covariance. More...
 
void GetCoef (Array1D< double > &coef)
 Get coefficients. More...
 
void Proj (Array1D< double > &array, Array1D< double > &proj_array)
 Project. More...
 
Array1D< double > LSQ_computeBestLambdas ()
 Compute the best values for regulariation parameter vector lambda, for LSQ. More...
 
double LSQ_computeBestLambda ()
 Compute the best value for regulariation parameter lambda, for LSQ. More...
 
void getResid ()
 Compute the residual vector, if not already computed. More...
 
void getDiagP ()
 Compute the diagonal of projection matrix, if not already computed. More...
 
Array1D< double > computeErrorMetrics (string method)
 Compote error according to a selected metrics. More...
 
double computeRVE (Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)
 Compute validation error. More...
 
+ + + + +

+Private Attributes

Array2D< int > mindex_
 Multiindex. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Lreg
Array2D< double > xdata_
 xdata array More...
 
Array1D< double > ydata_
 ydata array More...
 
int npt_
 Number of samples. More...
 
int nbas_
 Number of bases. More...
 
int ndim_
 Dimensionality. More...
 
double sigma2_
 Variance. More...
 
Array1D< double > weights_
 Weights. More...
 
Array1D< double > resid_
 Residuals. More...
 
bool residFlag_
 Flag to indicate whether residual is computed. More...
 
Array1D< double > diagP_
 Diagonal of projection matrix. More...
 
bool diagPFlag_
 Flag to indicate whether diagonal of projetion matrix is computed. More...
 
Array2D< double > bdata_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_inv_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > coef_cov_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > Hty_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_erb_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
+

Detailed Description

+

Derived class for polynomial regression.

+

Constructor & Destructor Documentation

+ +

◆ PLreg() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
PLreg::PLreg (int order,
int dim 
)
+
+ +

Constructors:

+ +
+
+ +

◆ PLreg() [2/2]

+ +
+
+ + + + + + + + +
PLreg::PLreg (Array2D< int > & mindex)
+
+ +
+
+ +

◆ ~PLreg()

+ +
+
+ + + + + +
+ + + + + + + +
PLreg::~PLreg ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ EvalBases()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void PLreg::EvalBases (Array2D< double > & xx,
Array2D< double > & bb 
)
+
+virtual
+
+ +

Evaluate the bases.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ GetMindex()

+ +
+
+ + + + + +
+ + + + + + + + +
void PLreg::GetMindex (Array2D< int > & mindex)
+
+inlinevirtual
+
+ +

Get multiindex.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ SetMindex()

+ +
+
+ + + + + +
+ + + + + + + + +
void PLreg::SetMindex (Array2D< int > & mindex)
+
+inlinevirtual
+
+ +

Set multiindex.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ StripBases()

+ +
+
+ + + + + +
+ + + + + + + + +
void PLreg::StripBases (Array1D< int > & used)
+
+virtual
+
+ +

Strip the bases.

+ +

Reimplemented from Lreg.

+ +
+
+

Member Data Documentation

+ +

◆ mindex_

+ +
+
+ + + + + +
+ + + + +
Array2D<int> PLreg::mindex_
+
+private
+
+ +

Multiindex.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classPLreg.png b/doc/doxygen/html/classPLreg.png new file mode 100644 index 00000000..2cb8ec36 Binary files /dev/null and b/doc/doxygen/html/classPLreg.png differ diff --git a/doc/doxygen/html/classPost-members.html b/doc/doxygen/html/classPost-members.html new file mode 100644 index 00000000..fa48db9b --- /dev/null +++ b/doc/doxygen/html/classPost-members.html @@ -0,0 +1,101 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Post Member List
+
+
+ +

This is the complete list of members for Post, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
chDim_Postprotected
dataNoiseLogFlag_Postprotected
dataNoiseSig_Postprotected
dataSigma(double m_last)Post
evalLogLik(Array1D< double > &m)Postinlinevirtual
evalLogPrior(Array1D< double > &m)Post
extraInferredParams_Postprotected
fixIndNom_Postprotected
forwardFcns_Postprotected
funcinfo_Postprotected
getChainDim()Post
getParamPCcf(Array1D< double > &m)Post
inferDataNoise()Post
inferDataNoise_Postprotected
inferLogDataNoise()Post
lower_Postprotected
momForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momForwardFcn(Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)Post
momParam(Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)Post
Mrv_Postprotected
ncat_Postprotected
nData_Postprotected
nEach_Postprotected
pdfType_Postprotected
pDim_Postprotected
Post()Post
priora_Postprotected
priorb_Postprotected
priorType_Postprotected
rndInd_Postprotected
rvpcType_Postprotected
samForwardFcn(Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)Post
samParam(Array1D< double > &m, int ns)Post
setData(Array2D< double > &xdata, Array2D< double > &ydata)Post
setDataNoise(Array1D< double > &sigma)Post
setModel(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)Post
setModelRVinput(int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)Post
setPrior(string priorType, double priora, double priorb)Post
upper_Postprotected
verbosity_Postprivate
xData_Postprotected
xDim_Postprotected
yData_Postprotected
yDatam_Postprotected
~Post()Postinline
+ + + + diff --git a/doc/doxygen/html/classPost.html b/doc/doxygen/html/classPost.html new file mode 100644 index 00000000..3ed37d5f --- /dev/null +++ b/doc/doxygen/html/classPost.html @@ -0,0 +1,1449 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Post Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

posterior evaluation with various likelihood and prior options + More...

+ +

#include <post.h>

+
+Inheritance diagram for Post:
+
+
+ + +Lik_ABC +Lik_ABCm +Lik_Classical +Lik_Full +Lik_GausMarg +Lik_GausMargD +Lik_Koh +Lik_Marg +Lik_MVN + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Post ()
 Constructor. More...
 
 ~Post ()
 Destructor. More...
 
void setData (Array2D< double > &xdata, Array2D< double > &ydata)
 Set the x- and y-data. More...
 
void setDataNoise (Array1D< double > &sigma)
 Set the magnitude of data noise. More...
 
void inferDataNoise ()
 Indicate inference of data noise stdev. More...
 
void inferLogDataNoise ()
 Indicate inference of log of data noise stdev. More...
 
Array1D< double > dataSigma (double m_last)
 Get data noise, whether inferred or fixed. More...
 
void setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, Array2D< double > &fixindnom, void *funcInfo)
 Set a pointer to the forward model f(p,x) More...
 
void setModelRVinput (int pdim, int order, Array1D< int > &rndInd, string pdfType, string pcType)
 Set model input parameters' randomization scheme. More...
 
int getChainDim ()
 Get the dimensionailty of the posterior function. More...
 
void setPrior (string priorType, double priora, double priorb)
 Set the prior type and its parameters. More...
 
double evalLogPrior (Array1D< double > &m)
 Evaluate log-prior. More...
 
Array2D< double > getParamPCcf (Array1D< double > &m)
 Extract parameter PC coefficients from a posterior input. More...
 
Array2D< double > samParam (Array1D< double > &m, int ns)
 Sample model parameters given posterior input. More...
 
void momParam (Array1D< double > &m, Array1D< double > &parMean, Array1D< double > &parVar, bool covFlag, Array2D< double > &parCov)
 Get moments of parameters given posterior input. More...
 
Array2D< double > samForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, int ns)
 Sample forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array2D< double >(*forwardFunc)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *), Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 Get moments of forward function at a given grid for given posterior input. More...
 
void momForwardFcn (Array1D< double > &m, Array2D< double > &xgrid, Array1D< double > &fcnMean, Array1D< double > &fcnVar, bool covflag, Array2D< double > &fcnCov)
 
virtual double evalLogLik (Array1D< double > &m)
 Dummy evaluation of log-likelihood. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Protected Attributes

Array2D< double > xData_
 xdata More...
 
Array2D< double > yData_
 ydata More...
 
Array1D< double > yDatam_
 ydata averaged per measurement (in case more than one y is given for each x) More...
 
int nData_
 Number of data points. More...
 
int nEach_
 Number of samples at each input. More...
 
int xDim_
 Dimensionality of x-space. More...
 
int pDim_
 Dimensionality of parameter space (p-space) More...
 
int chDim_
 Dimensionality of posterior input. More...
 
bool inferDataNoise_
 Flag for data noise inference. More...
 
bool dataNoiseLogFlag_
 Flag to check if data noise logarithm is used. More...
 
Array1D< double > dataNoiseSig_
 Data noise stdev. More...
 
Array1D< Array2D< double > Array2D forwardFcns_
 Pointer to the forward function f(p,x) More...
 
void * funcinfo_
 Auxiliary information for function evaluation. More...
 
int extraInferredParams_
 Number of extra inferred parameters, such as data noise or Koh variance. More...
 
int ncat_
 Number of categories. More...
 
MrvMrv_
 Pointer to a multivariate PC RV object. More...
 
Array1D< int > rndInd_
 Indices of randomized inputs. More...
 
Array2D< double > fixIndNom_
 Indices and nominal values for fixed inputs. More...
 
Array1D< double > lower_
 Lower and upper bounds on parameters. More...
 
Array1D< double > upper_
 
string pdfType_
 Input parameter PDF type. More...
 
string rvpcType_
 PC type parameter for the r.v. More...
 
string priorType_
 Prior type. More...
 
double priora_
 Prior parameter #1. More...
 
double priorb_
 Prior parameter #2. More...
 
+ + + + +

+Private Attributes

int verbosity_
 Verbosity level. More...
 
+

Detailed Description

+

posterior evaluation with various likelihood and prior options

+

Constructor & Destructor Documentation

+ +

◆ Post()

+ +
+
+ + + + + + + +
Post::Post ()
+
+ +

Constructor.

+ +
+
+ +

◆ ~Post()

+ +
+
+ + + + + +
+ + + + + + + +
Post::~Post ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ dataSigma()

+ +
+
+ + + + + + + + +
Array1D< double > Post::dataSigma (double m_last)
+
+ +

Get data noise, whether inferred or fixed.

+ +
+
+ +

◆ evalLogLik()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual double Post::evalLogLik (Array1D< double > & m)
+
+inlinevirtual
+
+ +

Dummy evaluation of log-likelihood.

+ +

Reimplemented in Lik_Classical, Lik_Koh, Lik_ABCm, Lik_ABC, Lik_GausMargD, Lik_GausMarg, Lik_MVN, Lik_Marg, and Lik_Full.

+ +
+
+ +

◆ evalLogPrior()

+ +
+
+ + + + + + + + +
double Post::evalLogPrior (Array1D< double > & m)
+
+ +

Evaluate log-prior.

+ +
+
+ +

◆ getChainDim()

+ +
+
+ + + + + + + +
int Post::getChainDim ()
+
+ +

Get the dimensionailty of the posterior function.

+ +
+
+ +

◆ getParamPCcf()

+ +
+
+ + + + + + + + +
Array2D< double > Post::getParamPCcf (Array1D< double > & m)
+
+ +

Extract parameter PC coefficients from a posterior input.

+ +
+
+ +

◆ inferDataNoise()

+ +
+
+ + + + + + + +
void Post::inferDataNoise ()
+
+ +

Indicate inference of data noise stdev.

+ +
+
+ +

◆ inferLogDataNoise()

+ +
+
+ + + + + + + +
void Post::inferLogDataNoise ()
+
+ +

Indicate inference of log of data noise stdev.

+ +
+
+ +

◆ momForwardFcn() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Post::momForwardFcn (Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) forwardFunc,
Array1D< double > & m,
Array2D< double > & xgrid,
Array1D< double > & fcnMean,
Array1D< double > & fcnVar,
bool covflag,
Array2D< double > & fcnCov 
)
+
+ +

Get moments of forward function at a given grid for given posterior input.

+ +
+
+ +

◆ momForwardFcn() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Post::momForwardFcn (Array1D< double > & m,
Array2D< double > & xgrid,
Array1D< double > & fcnMean,
Array1D< double > & fcnVar,
bool covflag,
Array2D< double > & fcnCov 
)
+
+ +
+
+ +

◆ momParam()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Post::momParam (Array1D< double > & m,
Array1D< double > & parMean,
Array1D< double > & parVar,
bool covFlag,
Array2D< double > & parCov 
)
+
+ +

Get moments of parameters given posterior input.

+ +
+
+ +

◆ samForwardFcn()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D< double > Post::samForwardFcn (Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) forwardFunc,
Array1D< double > & m,
Array2D< double > & xgrid,
int ns 
)
+
+ +

Sample forward function at a given grid for given posterior input.

+ +
+
+ +

◆ samParam()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D< double > Post::samParam (Array1D< double > & m,
int ns 
)
+
+ +

Sample model parameters given posterior input.

+ +
+
+ +

◆ setData()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Post::setData (Array2D< double > & xdata,
Array2D< double > & ydata 
)
+
+ +

Set the x- and y-data.

+ +
+
+ +

◆ setDataNoise()

+ +
+
+ + + + + + + + +
void Post::setDataNoise (Array1D< double > & sigma)
+
+ +

Set the magnitude of data noise.

+ +
+
+ +

◆ setModel()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Post::setModel (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs,
Array2D< double > & fixindnom,
void * funcInfo 
)
+
+ +

Set a pointer to the forward model f(p,x)

+ +
+
+ +

◆ setModelRVinput()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Post::setModelRVinput (int pdim,
int order,
Array1D< int > & rndInd,
string pdfType,
string pcType 
)
+
+ +

Set model input parameters' randomization scheme.

+ +
+
+ +

◆ setPrior()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Post::setPrior (string priorType,
double priora,
double priorb 
)
+
+ +

Set the prior type and its parameters.

+ +
+
+

Member Data Documentation

+ +

◆ chDim_

+ +
+
+ + + + + +
+ + + + +
int Post::chDim_
+
+protected
+
+ +

Dimensionality of posterior input.

+ +
+
+ +

◆ dataNoiseLogFlag_

+ +
+
+ + + + + +
+ + + + +
bool Post::dataNoiseLogFlag_
+
+protected
+
+ +

Flag to check if data noise logarithm is used.

+ +
+
+ +

◆ dataNoiseSig_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Post::dataNoiseSig_
+
+protected
+
+ +

Data noise stdev.

+ +
+
+ +

◆ extraInferredParams_

+ +
+
+ + + + + +
+ + + + +
int Post::extraInferredParams_
+
+protected
+
+ +

Number of extra inferred parameters, such as data noise or Koh variance.

+ +
+
+ +

◆ fixIndNom_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Post::fixIndNom_
+
+protected
+
+ +

Indices and nominal values for fixed inputs.

+ +
+
+ +

◆ forwardFcns_

+ +
+
+ + + + + +
+ + + + +
Array1D< Array2D<double> Array2D Post::forwardFcns_
+
+protected
+
+ +

Pointer to the forward function f(p,x)

+ +
+
+ +

◆ funcinfo_

+ +
+
+ + + + + +
+ + + + +
void* Post::funcinfo_
+
+protected
+
+ +

Auxiliary information for function evaluation.

+ +
+
+ +

◆ inferDataNoise_

+ +
+
+ + + + + +
+ + + + +
bool Post::inferDataNoise_
+
+protected
+
+ +

Flag for data noise inference.

+ +
+
+ +

◆ lower_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Post::lower_
+
+protected
+
+ +

Lower and upper bounds on parameters.

+ +
+
+ +

◆ Mrv_

+ +
+
+ + + + + +
+ + + + +
Mrv* Post::Mrv_
+
+protected
+
+ +

Pointer to a multivariate PC RV object.

+ +
+
+ +

◆ ncat_

+ +
+
+ + + + + +
+ + + + +
int Post::ncat_
+
+protected
+
+ +

Number of categories.

+ +
+
+ +

◆ nData_

+ +
+
+ + + + + +
+ + + + +
int Post::nData_
+
+protected
+
+ +

Number of data points.

+ +
+
+ +

◆ nEach_

+ +
+
+ + + + + +
+ + + + +
int Post::nEach_
+
+protected
+
+ +

Number of samples at each input.

+ +
+
+ +

◆ pdfType_

+ +
+
+ + + + + +
+ + + + +
string Post::pdfType_
+
+protected
+
+ +

Input parameter PDF type.

+ +
+
+ +

◆ pDim_

+ +
+
+ + + + + +
+ + + + +
int Post::pDim_
+
+protected
+
+ +

Dimensionality of parameter space (p-space)

+ +
+
+ +

◆ priora_

+ +
+
+ + + + + +
+ + + + +
double Post::priora_
+
+protected
+
+ +

Prior parameter #1.

+ +
+
+ +

◆ priorb_

+ +
+
+ + + + + +
+ + + + +
double Post::priorb_
+
+protected
+
+ +

Prior parameter #2.

+ +
+
+ +

◆ priorType_

+ +
+
+ + + + + +
+ + + + +
string Post::priorType_
+
+protected
+
+ +

Prior type.

+ +
+
+ +

◆ rndInd_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> Post::rndInd_
+
+protected
+
+ +

Indices of randomized inputs.

+ +
+
+ +

◆ rvpcType_

+ +
+
+ + + + + +
+ + + + +
string Post::rvpcType_
+
+protected
+
+ +

PC type parameter for the r.v.

+ +
+
+ +

◆ upper_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Post::upper_
+
+protected
+
+ +
+
+ +

◆ verbosity_

+ +
+
+ + + + + +
+ + + + +
int Post::verbosity_
+
+private
+
+ +

Verbosity level.

+ +
+
+ +

◆ xData_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Post::xData_
+
+protected
+
+ +

xdata

+ +
+
+ +

◆ xDim_

+ +
+
+ + + + + +
+ + + + +
int Post::xDim_
+
+protected
+
+ +

Dimensionality of x-space.

+ +
+
+ +

◆ yData_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> Post::yData_
+
+protected
+
+ +

ydata

+ +
+
+ +

◆ yDatam_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Post::yDatam_
+
+protected
+
+ +

ydata averaged per measurement (in case more than one y is given for each x)

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classPost.png b/doc/doxygen/html/classPost.png new file mode 100644 index 00000000..c4b3ae0f Binary files /dev/null and b/doc/doxygen/html/classPost.png differ diff --git a/doc/doxygen/html/classQuad-members.html b/doc/doxygen/html/classQuad-members.html new file mode 100644 index 00000000..e17e60c5 --- /dev/null +++ b/doc/doxygen/html/classQuad-members.html @@ -0,0 +1,116 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Quad Member List
+
+
+ +

This is the complete list of members for Quad, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aa_Quadprivate
AddTwoRules(QuadRule *rule1, QuadRule *rule2, QuadRule *rule_sum)Quadprivate
alpha_Quadprivate
alphas_Quadprivate
bb_Quadprivate
beta_Quadprivate
betas_Quadprivate
compressRule(QuadRule *rule)Quadprivate
create1DRule(string gridtype, Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_CC(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_CCO(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_GLG(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr)Quadprivate
create1DRule_GP3(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_HG(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr)Quadprivate
create1DRule_JB(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_LU(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_NC(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_NCO(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_pdf(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)Quadprivate
create1DRule_SW(Array1D< double > &qdpts, Array1D< double > &wghts, int ngr)Quadprivate
fs_type_Quadprivate
GetDomain(Array1D< double > &aa, Array1D< double > &bb) constQuadinline
GetDomain(Array1D< double > &aa) constQuadinline
getMultiIndexLevel(Array2D< int > &multiIndexLevel, int level, int ndim)Quadprivate
GetNQ()Quadinline
GetQdpts(Array2D< double > &q)Quadinline
GetRule(Array2D< double > &q, Array1D< double > &w)Quad
GetRule(Array2D< double > &q, Array1D< double > &w, Array2D< int > &ind)Quadinline
GetWghts(Array1D< double > &w)Quadinline
grid_type_Quadprivate
grid_types_Quadprivate
growth_rule_Quadprivate
growth_rules_Quadprivate
init()Quad
maxlevel_Quadprivate
MultiplyManyRules(int nrules, QuadRule *rules, QuadRule *rule_prod)Quadprivate
MultiplyTwoRules(QuadRule *rule1, QuadRule *rule2, QuadRule *rule_prod)Quadprivate
ndim_Quadprivate
nextLevel()Quad
nlevel_Quadprivate
param_Quadprivate
Quad(char *grid_type, char *fs_type, int ndim, int param, double alpha=0.0, double betta=1.0)Quad
Quad(Array1D< string > &grid_types, char *fs_type, Array1D< int > &param, Array1D< double > &alphas, Array1D< double > &bettas)Quad
Quad()Quadinline
Quad(const Quad &)Quadinlineprivate
quadverbose_Quadprivate
rule_Quadprivate
SetAlpha(double alpha)Quadinline
SetBeta(double betta)Quadinline
SetDomain(Array1D< double > &aa, Array1D< double > &bb)Quad
SetDomain(Array1D< double > &aa)Quad
SetLevel(int param)Quadinline
SetQdpts(Array2D< double > &q)Quadinline
SetRule(Array2D< double > &q, Array1D< double > &w)Quad
SetRule(Array2D< double > &q, Array1D< double > &w, Array2D< int > &ind)Quadinline
SetRule()Quad
SetVerbosity(int verbosity)Quadinline
SetWghts(Array1D< double > &w)Quadinline
SubtractTwoRules(QuadRule *rule1, QuadRule *rule2, QuadRule *rule_sum)Quadprivate
~Quad()Quadinline
+ + + + diff --git a/doc/doxygen/html/classQuad.html b/doc/doxygen/html/classQuad.html new file mode 100644 index 00000000..06397d85 --- /dev/null +++ b/doc/doxygen/html/classQuad.html @@ -0,0 +1,2332 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Quad Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

Generates quadrature rules. + More...

+ +

#include <quad.h>

+ + + + + +

+Classes

struct  QuadRule
 Rule structure that stores quadrature points, weights and indices. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Quad (char *grid_type, char *fs_type, int ndim, int param, double alpha=0.0, double betta=1.0)
 Constructor: initializes the rule type, sparseness type, dimensionality, level or ppd parameter, and two optional parameters for quadrature rule. More...
 
 Quad (Array1D< string > &grid_types, char *fs_type, Array1D< int > &param, Array1D< double > &alphas, Array1D< double > &bettas)
 Constructor, overloaded for dimension-unisotropy: initializes the dimension-specific rule types, sparseness type, dimension-specific ppd or level, and two optional parameters for quadrature rule per each dimension. More...
 
 Quad ()
 Constructor: empty. More...
 
 ~Quad ()
 Destructor. More...
 
void init ()
 Initialization function. More...
 
void SetAlpha (double alpha)
 Set the parameter alpha. More...
 
void SetBeta (double betta)
 Set the parameter beta. More...
 
void SetDomain (Array1D< double > &aa, Array1D< double > &bb)
 Set the domain endpoints (for compact support domains) More...
 
void SetDomain (Array1D< double > &aa)
 Set the domain endpoint (for semi-infinite domains) More...
 
void GetDomain (Array1D< double > &aa, Array1D< double > &bb) const
 Get the domain endpoints (for compact support domains) More...
 
void GetDomain (Array1D< double > &aa) const
 Get the domain endpoint (for semi-infinite domains) More...
 
void SetRule (Array2D< double > &q, Array1D< double > &w)
 Set the rule externally (only quadrature points and weights) More...
 
void SetRule (Array2D< double > &q, Array1D< double > &w, Array2D< int > &ind)
 Set the rule externally (quadrature points, weights and indices) Dummy function for backward compatibility. More...
 
void SetRule ()
 Set the rule externally (quadrature points, weights, indices, and the level) More...
 
void GetRule (Array2D< double > &q, Array1D< double > &w)
 Get the quadrature rule. More...
 
void GetRule (Array2D< double > &q, Array1D< double > &w, Array2D< int > &ind)
 Get the quadrature rule with indexing Dummy function for backward compatibility. More...
 
void SetQdpts (Array2D< double > &q)
 Externally set quadrature points. More...
 
void SetWghts (Array1D< double > &w)
 Externally set the weights. More...
 
void GetQdpts (Array2D< double > &q)
 Externally set the indices. More...
 
void GetWghts (Array1D< double > &w)
 Get the weights. More...
 
void SetLevel (int param)
 Get the indices. More...
 
void nextLevel ()
 Compute the indices of the next-level points. More...
 
int GetNQ ()
 Get the number of quadrature points. More...
 
void SetVerbosity (int verbosity)
 Set the verbosity level. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Member Functions

 Quad (const Quad &)
 Dummy copy constructor, which should not be used as it is currently not well defined. More...
 
void MultiplyTwoRules (QuadRule *rule1, QuadRule *rule2, QuadRule *rule_prod)
 Multiply two rules (full tensor product) More...
 
void MultiplyManyRules (int nrules, QuadRule *rules, QuadRule *rule_prod)
 Multiply many rules (full tensor product) More...
 
void AddTwoRules (QuadRule *rule1, QuadRule *rule2, QuadRule *rule_sum)
 Add two rules. More...
 
void SubtractTwoRules (QuadRule *rule1, QuadRule *rule2, QuadRule *rule_sum)
 Subtract two rules. More...
 
void create1DRule (string gridtype, Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Compute 1D rules. More...
 
void create1DRule_CC (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Clenshaw-Curtis (includes the endpoints) More...
 
void create1DRule_LU (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Legendre-Uniform. More...
 
void create1DRule_HG (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr)
 Gauss-Hermite. More...
 
void create1DRule_NC (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Newton-Cotes (i.e. equispaced, includes the endpoints) More...
 
void create1DRule_NCO (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Newton-Cotes open (i.e. excludes the endpoints) More...
 
void create1DRule_CCO (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Clenshaw-Curtis open (i.e. excludes the endpoints) More...
 
void create1DRule_JB (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Jacobi-Beta. More...
 
void create1DRule_GLG (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr)
 Gamma-Laguerre. More...
 
void create1DRule_SW (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr)
 Stieltjes-Wigert. More...
 
void create1DRule_pdf (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Custom rule given the recursive coefficients of the corresponding orthogonal polynomials. More...
 
void create1DRule_GP3 (Array1D< double > &qdpts, Array1D< double > &wghts, int ngr, double a, double b)
 Gauss-Patterson starting with Legendre-Uniform 3. More...
 
void getMultiIndexLevel (Array2D< int > &multiIndexLevel, int level, int ndim)
 Auxilliary function: get the level of the multi-index. More...
 
void compressRule (QuadRule *rule)
 Compress the rule, i.e. merge repeating points. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

Array1D< double > aa_
 The left endpoints of the domain. More...
 
Array1D< double > bb_
 the right endpoints of the domain More...
 
int quadverbose_
 Verbosity level. More...
 
double alpha_
 The first parameter of the rule, if any. More...
 
double beta_
 The second parameter of the rule, if any. More...
 
Array1D< double > alphas_
 The first parameter of the rule, if any. More...
 
Array1D< double > betas_
 The second parameter of the rule, if any. More...
 
QuadRule rule_
 The quadrature rule structure. More...
 
int ndim_
 The dimensionality. More...
 
int nlevel_
 The current level, working variable for hierarchical construction. More...
 
int maxlevel_
 The level for sparse rules, or the number of grid points per dim for full product rules. More...
 
Array1D< int > param_
 
int growth_rule_
 Growth rule: exponential(0) or linear(1) More...
 
Array1D< int > growth_rules_
 Growth rules: exponential(0) or linear(1) More...
 
string grid_type_
 Grid type: 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf', or 'GP3'. More...
 
Array1D< string > grid_types_
 Vector of grid types: 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf', or 'GP3'. More...
 
string fs_type_
 Sparseness type (full or sparse) More...
 
+

Detailed Description

+

Generates quadrature rules.

+
Note
Besides quadrature rules corresponding to PC bases (i.e. LU, HG, LG, SW, JB), Clenshaw-Curtis(CC) and Newton-Cotes(NC) as well as their Open (with no endpoints) versions (CCO, NCO) are implemented. Also, Gauss-Patterson (GP3) and custom (pdf) rules are added.
+

Constructor & Destructor Documentation

+ +

◆ Quad() [1/4]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Quad::Quad (char * grid_type,
char * fs_type,
int ndim,
int param,
double alpha = 0.0,
double betta = 1.0 
)
+
+ +

Constructor: initializes the rule type, sparseness type, dimensionality, level or ppd parameter, and two optional parameters for quadrature rule.

+
Note
Options for the arguments are: grid_type : LU, HG, LG, SW, JB, CC, CCO, NC, NCO, GP3, pdf fs_type : full, sparse ndim : integer dimensionality param : integer points-per-dimension (if full), or level (if sparse) alpha : parameter #1 for the corresponding PC type (e.g. LG requires one parameter) betta : parameter #2 for the corresponding PC type (e.g. JB requires two parameters)
+ +
+
+ +

◆ Quad() [2/4]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Quad::Quad (Array1D< string > & grid_types,
char * fs_type,
Array1D< int > & param,
Array1D< double > & alphas,
Array1D< double > & bettas 
)
+
+ +

Constructor, overloaded for dimension-unisotropy: initializes the dimension-specific rule types, sparseness type, dimension-specific ppd or level, and two optional parameters for quadrature rule per each dimension.

+
Note
Options for the arguments are: grid_types : array with entry options LU, HG, LG, SW, JB, CC, CCO, NC, NCO, GP3, pdf fs_type : full, sparse param : integer array for points-per-dimension (if full), or an array with first element indicating the level (if sparse) alpha : array of parameters #1 for the corresponding PC type (e.g. LG requires one parameter) bettas : array of parameters #2 for the corresponding PC type (e.g. JB requires two parameters)
+ +
+
+ +

◆ Quad() [3/4]

+ +
+
+ + + + + +
+ + + + + + + +
Quad::Quad ()
+
+inline
+
+ +

Constructor: empty.

+ +
+
+ +

◆ ~Quad()

+ +
+
+ + + + + +
+ + + + + + + +
Quad::~Quad ()
+
+inline
+
+ +

Destructor.

+ +
+
+ +

◆ Quad() [4/4]

+ +
+
+ + + + + +
+ + + + + + + + +
Quad::Quad (const Quad)
+
+inlineprivate
+
+ +

Dummy copy constructor, which should not be used as it is currently not well defined.

+ +
+
+

Member Function Documentation

+ +

◆ AddTwoRules()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::AddTwoRules (QuadRulerule1,
QuadRulerule2,
QuadRulerule_sum 
)
+
+private
+
+ +

Add two rules.

+ +
+
+ +

◆ compressRule()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::compressRule (QuadRulerule)
+
+private
+
+ +

Compress the rule, i.e. merge repeating points.

+ +
+
+ +

◆ create1DRule()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule (string gridtype,
Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Compute 1D rules.

+ +
+
+ +

◆ create1DRule_CC()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_CC (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Clenshaw-Curtis (includes the endpoints)

+
Note
Heavily adopted from http://people.sc.fsu.edu/~jburkardt/cpp_src/sparse_grid_cc/sparse_grid_cc.html (distributed under LGPL)
+ +
+
+ +

◆ create1DRule_CCO()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_CCO (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Clenshaw-Curtis open (i.e. excludes the endpoints)

+
Note
Heavily adopted from http://people.sc.fsu.edu/~jburkardt/cpp_src/sparse_grid_cc/sparse_grid_cc.html (distributed under LGPL)
+ +
+
+ +

◆ create1DRule_GLG()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_GLG (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr 
)
+
+private
+
+ +

Gamma-Laguerre.

+ +
+
+ +

◆ create1DRule_GP3()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_GP3 (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Gauss-Patterson starting with Legendre-Uniform 3.

+
Note
Hardwired reading of quadrature points and weights
+ +
+
+ +

◆ create1DRule_HG()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_HG (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr 
)
+
+private
+
+ +

Gauss-Hermite.

+ +
+
+ +

◆ create1DRule_JB()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_JB (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Jacobi-Beta.

+ +
+
+ +

◆ create1DRule_LU()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_LU (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Legendre-Uniform.

+ +
+
+ +

◆ create1DRule_NC()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_NC (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Newton-Cotes (i.e. equispaced, includes the endpoints)

+ +
+
+ +

◆ create1DRule_NCO()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_NCO (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Newton-Cotes open (i.e. excludes the endpoints)

+ +
+
+ +

◆ create1DRule_pdf()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_pdf (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr,
double a,
double b 
)
+
+private
+
+ +

Custom rule given the recursive coefficients of the corresponding orthogonal polynomials.

+
Todo:
Recursive coefficients are given in a file 'ab.dat'; will need to make this more friendly
+ +
+
+ +

◆ create1DRule_SW()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::create1DRule_SW (Array1D< double > & qdpts,
Array1D< double > & wghts,
int ngr 
)
+
+private
+
+ +

Stieltjes-Wigert.

+ +
+
+ +

◆ GetDomain() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void Quad::GetDomain (Array1D< double > & aa,
Array1D< double > & bb 
) const
+
+inline
+
+ +

Get the domain endpoints (for compact support domains)

+ +
+
+ +

◆ GetDomain() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::GetDomain (Array1D< double > & aa) const
+
+inline
+
+ +

Get the domain endpoint (for semi-infinite domains)

+ +
+
+ +

◆ getMultiIndexLevel()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::getMultiIndexLevel (Array2D< int > & multiIndexLevel,
int level,
int ndim 
)
+
+private
+
+ +

Auxilliary function: get the level of the multi-index.

+ +
+
+ +

◆ GetNQ()

+ +
+
+ + + + + +
+ + + + + + + +
int Quad::GetNQ ()
+
+inline
+
+ +

Get the number of quadrature points.

+ +
+
+ +

◆ GetQdpts()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::GetQdpts (Array2D< double > & q)
+
+inline
+
+ +

Externally set the indices.

+

Get quadrature points

+ +
+
+ +

◆ GetRule() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Quad::GetRule (Array2D< double > & q,
Array1D< double > & w 
)
+
+ +

Get the quadrature rule.

+ +
+
+ +

◆ GetRule() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::GetRule (Array2D< double > & q,
Array1D< double > & w,
Array2D< int > & ind 
)
+
+inline
+
+ +

Get the quadrature rule with indexing Dummy function for backward compatibility.

+ +
+
+ +

◆ GetWghts()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::GetWghts (Array1D< double > & w)
+
+inline
+
+ +

Get the weights.

+ +
+
+ +

◆ init()

+ +
+
+ + + + + + + +
void Quad::init ()
+
+ +

Initialization function.

+ +
+
+ +

◆ MultiplyManyRules()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::MultiplyManyRules (int nrules,
QuadRulerules,
QuadRulerule_prod 
)
+
+private
+
+ +

Multiply many rules (full tensor product)

+ +
+
+ +

◆ MultiplyTwoRules()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::MultiplyTwoRules (QuadRulerule1,
QuadRulerule2,
QuadRulerule_prod 
)
+
+private
+
+ +

Multiply two rules (full tensor product)

+ +
+
+ +

◆ nextLevel()

+ +
+
+ + + + + + + +
void Quad::nextLevel ()
+
+ +

Compute the indices of the next-level points.

+ +
+
+ +

◆ SetAlpha()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::SetAlpha (double alpha)
+
+inline
+
+ +

Set the parameter alpha.

+ +
+
+ +

◆ SetBeta()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::SetBeta (double betta)
+
+inline
+
+ +

Set the parameter beta.

+ +
+
+ +

◆ SetDomain() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Quad::SetDomain (Array1D< double > & aa,
Array1D< double > & bb 
)
+
+ +

Set the domain endpoints (for compact support domains)

+ +
+
+ +

◆ SetDomain() [2/2]

+ +
+
+ + + + + + + + +
void Quad::SetDomain (Array1D< double > & aa)
+
+ +

Set the domain endpoint (for semi-infinite domains)

+ +
+
+ +

◆ SetLevel()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::SetLevel (int param)
+
+inline
+
+ +

Get the indices.

+

Set the level parameter

+ +
+
+ +

◆ SetQdpts()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::SetQdpts (Array2D< double > & q)
+
+inline
+
+ +

Externally set quadrature points.

+ +
+
+ +

◆ SetRule() [1/3]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void Quad::SetRule (Array2D< double > & q,
Array1D< double > & w 
)
+
+ +

Set the rule externally (only quadrature points and weights)

+ +
+
+ +

◆ SetRule() [2/3]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::SetRule (Array2D< double > & q,
Array1D< double > & w,
Array2D< int > & ind 
)
+
+inline
+
+ +

Set the rule externally (quadrature points, weights and indices) Dummy function for backward compatibility.

+ +
+
+ +

◆ SetRule() [3/3]

+ +
+
+ + + + + + + +
void Quad::SetRule ()
+
+ +

Set the rule externally (quadrature points, weights, indices, and the level)

+

Set the rule (the function that builds quadrature points/weights/indices)

+ +
+
+ +

◆ SetVerbosity()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::SetVerbosity (int verbosity)
+
+inline
+
+ +

Set the verbosity level.

+
Note
Currently, the values of 0, 1 and 2 are implemented
+ +
+
+ +

◆ SetWghts()

+ +
+
+ + + + + +
+ + + + + + + + +
void Quad::SetWghts (Array1D< double > & w)
+
+inline
+
+ +

Externally set the weights.

+ +
+
+ +

◆ SubtractTwoRules()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void Quad::SubtractTwoRules (QuadRulerule1,
QuadRulerule2,
QuadRulerule_sum 
)
+
+private
+
+ +

Subtract two rules.

+ +
+
+

Member Data Documentation

+ +

◆ aa_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Quad::aa_
+
+private
+
+ +

The left endpoints of the domain.

+ +
+
+ +

◆ alpha_

+ +
+
+ + + + + +
+ + + + +
double Quad::alpha_
+
+private
+
+ +

The first parameter of the rule, if any.

+ +
+
+ +

◆ alphas_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Quad::alphas_
+
+private
+
+ +

The first parameter of the rule, if any.

+ +
+
+ +

◆ bb_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Quad::bb_
+
+private
+
+ +

the right endpoints of the domain

+ +
+
+ +

◆ beta_

+ +
+
+ + + + + +
+ + + + +
double Quad::beta_
+
+private
+
+ +

The second parameter of the rule, if any.

+ +
+
+ +

◆ betas_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> Quad::betas_
+
+private
+
+ +

The second parameter of the rule, if any.

+ +
+
+ +

◆ fs_type_

+ +
+
+ + + + + +
+ + + + +
string Quad::fs_type_
+
+private
+
+ +

Sparseness type (full or sparse)

+ +
+
+ +

◆ grid_type_

+ +
+
+ + + + + +
+ + + + +
string Quad::grid_type_
+
+private
+
+ +

Grid type: 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf', or 'GP3'.

+ +
+
+ +

◆ grid_types_

+ +
+
+ + + + + +
+ + + + +
Array1D<string> Quad::grid_types_
+
+private
+
+ +

Vector of grid types: 'CC','CCO','NC','NCO','LU', 'HG', 'JB', 'GLG', 'SW', 'pdf', or 'GP3'.

+ +
+
+ +

◆ growth_rule_

+ +
+
+ + + + + +
+ + + + +
int Quad::growth_rule_
+
+private
+
+ +

Growth rule: exponential(0) or linear(1)

+ +
+
+ +

◆ growth_rules_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> Quad::growth_rules_
+
+private
+
+ +

Growth rules: exponential(0) or linear(1)

+ +
+
+ +

◆ maxlevel_

+ +
+
+ + + + + +
+ + + + +
int Quad::maxlevel_
+
+private
+
+ +

The level for sparse rules, or the number of grid points per dim for full product rules.

+ +
+
+ +

◆ ndim_

+ +
+
+ + + + + +
+ + + + +
int Quad::ndim_
+
+private
+
+ +

The dimensionality.

+ +
+
+ +

◆ nlevel_

+ +
+
+ + + + + +
+ + + + +
int Quad::nlevel_
+
+private
+
+ +

The current level, working variable for hierarchical construction.

+ +
+
+ +

◆ param_

+ +
+
+ + + + + +
+ + + + +
Array1D<int> Quad::param_
+
+private
+
+ +
+
+ +

◆ quadverbose_

+ +
+
+ + + + + +
+ + + + +
int Quad::quadverbose_
+
+private
+
+ +

Verbosity level.

+
Note
Currently the values of 0, 1 or 2 are implemented.
+ +
+
+ +

◆ rule_

+ +
+
+ + + + + +
+ + + + +
QuadRule Quad::rule_
+
+private
+
+ +

The quadrature rule structure.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classRBFreg-members.html b/doc/doxygen/html/classRBFreg-members.html new file mode 100644 index 00000000..6a5a0142 --- /dev/null +++ b/doc/doxygen/html/classRBFreg-members.html @@ -0,0 +1,108 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
RBFreg Member List
+
+
+ +

This is the complete list of members for RBFreg, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A_Lregprotected
A_inv_Lregprotected
BCS_BuildRegr(Array1D< int > &selected, double eta)Lreg
bdata_Lregprotected
centers_RBFregprivate
coef_Lregprotected
coef_cov_Lregprotected
coef_erb_Lregprotected
computeErrorMetrics(string method)Lreg
computeRVE(Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)Lreg
diagP_Lregprotected
diagPFlag_Lregprotected
EvalBases(Array2D< double > &xx, Array2D< double > &bb)RBFregvirtual
EvalRegr(Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)Lreg
GetCoef(Array1D< double > &coef)Lreginline
GetCoefCov(Array2D< double > &coef_cov)Lreginline
getDiagP()Lreg
GetMindex(Array2D< int > &mindex)Lreginlinevirtual
GetNbas() constLreginline
GetNdim() constLreginline
GetNpt() constLreginline
getResid()Lreg
GetSigma2() constLreginline
Hty_Lregprotected
InitRegr()Lreg
Lreg()Lreginline
LSQ_BuildRegr()Lreg
LSQ_computeBestLambda()Lreg
LSQ_computeBestLambdas()Lreg
nbas_Lregprotected
ndim_Lregprotected
npt_Lregprotected
Proj(Array1D< double > &array, Array1D< double > &proj_array)Lreg
RBFreg(Array2D< double > &centers, Array1D< double > &widths)RBFreg
resid_Lregprotected
residFlag_Lregprotected
SetCenters(Array2D< double > &centers)RBFregvirtual
SetMindex(Array2D< int > &mindex)Lreginlinevirtual
SetParamsRBF()Lreginlinevirtual
SetRegMode(string regmode)Lreginline
SetRegWeights(Array1D< double > &weights)Lreg
SetupData(Array2D< double > &xdata, Array1D< double > &ydata)Lreg
SetupData(Array2D< double > &xdata, Array2D< double > &ydata)Lreg
SetWidths(Array1D< double > &widths)RBFregvirtual
sigma2_Lregprotected
StripBases(Array1D< int > &used)RBFregvirtual
weights_Lregprotected
widths_RBFregprivate
xdata_Lregprotected
ydata_Lregprotected
~Lreg()Lreginline
~RBFreg()RBFreginline
+ + + + diff --git a/doc/doxygen/html/classRBFreg.html b/doc/doxygen/html/classRBFreg.html new file mode 100644 index 00000000..57cf3336 --- /dev/null +++ b/doc/doxygen/html/classRBFreg.html @@ -0,0 +1,483 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: RBFreg Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
RBFreg Class Reference
+
+
+ +

Derived class for RBF regression. + More...

+ +

#include <lreg.h>

+
+Inheritance diagram for RBFreg:
+
+
+ + +Lreg + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 RBFreg (Array2D< double > &centers, Array1D< double > &widths)
 Constructor: More...
 
 ~RBFreg ()
 Destructor. More...
 
void SetCenters (Array2D< double > &centers)
 Set centers. More...
 
void SetWidths (Array1D< double > &widths)
 Set widths. More...
 
void EvalBases (Array2D< double > &xx, Array2D< double > &bb)
 Evaluate the bases. More...
 
void StripBases (Array1D< int > &used)
 Strip the bases. More...
 
- Public Member Functions inherited from Lreg
 Lreg ()
 Constructor. More...
 
 ~Lreg ()
 Destrcutor. More...
 
virtual void SetMindex (Array2D< int > &mindex)
 Set multiindex. More...
 
virtual void GetMindex (Array2D< int > &mindex)
 Get multiindex. More...
 
virtual void SetParamsRBF ()
 Set parameters (for RBF) More...
 
void InitRegr ()
 Initialize. More...
 
void SetupData (Array2D< double > &xdata, Array1D< double > &ydata)
 Setup data (1d ydata) More...
 
void SetupData (Array2D< double > &xdata, Array2D< double > &ydata)
 Setup data (2d ydata) More...
 
void SetRegMode (string regmode)
 Set the regression mode. More...
 
void SetRegWeights (Array1D< double > &weights)
 Set weights. More...
 
void BCS_BuildRegr (Array1D< int > &selected, double eta)
 Build BCS regression. More...
 
void LSQ_BuildRegr ()
 Build LSQ regression. More...
 
void EvalRegr (Array2D< double > &xcheck, Array1D< double > &ycheck, Array1D< double > &yvar, Array2D< double > &ycov)
 Evaluate the regression expansion. More...
 
int GetNpt () const
 Get the number of points. More...
 
int GetNdim () const
 Get dimensionality. More...
 
int GetNbas () const
 Get the number of bases. More...
 
double GetSigma2 () const
 Get the variance. More...
 
void GetCoefCov (Array2D< double > &coef_cov)
 Get coefficient covariance. More...
 
void GetCoef (Array1D< double > &coef)
 Get coefficients. More...
 
void Proj (Array1D< double > &array, Array1D< double > &proj_array)
 Project. More...
 
Array1D< double > LSQ_computeBestLambdas ()
 Compute the best values for regulariation parameter vector lambda, for LSQ. More...
 
double LSQ_computeBestLambda ()
 Compute the best value for regulariation parameter lambda, for LSQ. More...
 
void getResid ()
 Compute the residual vector, if not already computed. More...
 
void getDiagP ()
 Compute the diagonal of projection matrix, if not already computed. More...
 
Array1D< double > computeErrorMetrics (string method)
 Compote error according to a selected metrics. More...
 
double computeRVE (Array2D< double > &xval, Array1D< double > &yval, Array1D< double > &yval_regr)
 Compute validation error. More...
 
+ + + + + + + +

+Private Attributes

Array2D< double > centers_
 RBF centers. More...
 
Array1D< double > widths_
 RBF bases' widhts. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Protected Attributes inherited from Lreg
Array2D< double > xdata_
 xdata array More...
 
Array1D< double > ydata_
 ydata array More...
 
int npt_
 Number of samples. More...
 
int nbas_
 Number of bases. More...
 
int ndim_
 Dimensionality. More...
 
double sigma2_
 Variance. More...
 
Array1D< double > weights_
 Weights. More...
 
Array1D< double > resid_
 Residuals. More...
 
bool residFlag_
 Flag to indicate whether residual is computed. More...
 
Array1D< double > diagP_
 Diagonal of projection matrix. More...
 
bool diagPFlag_
 Flag to indicate whether diagonal of projetion matrix is computed. More...
 
Array2D< double > bdata_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > A_inv_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array2D< double > coef_cov_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > Hty_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
Array1D< double > coef_erb_
 Auxiliary matrix or vector; see UQTk Manual. More...
 
+

Detailed Description

+

Derived class for RBF regression.

+

Constructor & Destructor Documentation

+ +

◆ RBFreg()

+ +
+
+ + + + + + + + + + + + + + + + + + +
RBFreg::RBFreg (Array2D< double > & centers,
Array1D< double > & widths 
)
+
+ +

Constructor:

+ +
+
+ +

◆ ~RBFreg()

+ +
+
+ + + + + +
+ + + + + + + +
RBFreg::~RBFreg ()
+
+inline
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ EvalBases()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void RBFreg::EvalBases (Array2D< double > & xx,
Array2D< double > & bb 
)
+
+virtual
+
+ +

Evaluate the bases.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ SetCenters()

+ +
+
+ + + + + +
+ + + + + + + + +
void RBFreg::SetCenters (Array2D< double > & centers)
+
+virtual
+
+ +

Set centers.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ SetWidths()

+ +
+
+ + + + + +
+ + + + + + + + +
void RBFreg::SetWidths (Array1D< double > & widths)
+
+virtual
+
+ +

Set widths.

+ +

Reimplemented from Lreg.

+ +
+
+ +

◆ StripBases()

+ +
+
+ + + + + +
+ + + + + + + + +
void RBFreg::StripBases (Array1D< int > & used)
+
+virtual
+
+ +

Strip the bases.

+ +

Reimplemented from Lreg.

+ +
+
+

Member Data Documentation

+ +

◆ centers_

+ +
+
+ + + + + +
+ + + + +
Array2D<double> RBFreg::centers_
+
+private
+
+ +

RBF centers.

+ +
+
+ +

◆ widths_

+ +
+
+ + + + + +
+ + + + +
Array1D<double> RBFreg::widths_
+
+private
+
+ +

RBF bases' widhts.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classRBFreg.png b/doc/doxygen/html/classRBFreg.png new file mode 100644 index 00000000..a77b34ff Binary files /dev/null and b/doc/doxygen/html/classRBFreg.png differ diff --git a/doc/doxygen/html/classRefPtr-members.html b/doc/doxygen/html/classRefPtr-members.html new file mode 100644 index 00000000..1e7a7ae0 --- /dev/null +++ b/doc/doxygen/html/classRefPtr-members.html @@ -0,0 +1,79 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
RefPtr< T > Member List
+
+
+ +

This is the complete list of members for RefPtr< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + +
cast(Other *p)RefPtr< T >inline
cast(RefPtr< Other > p)RefPtr< T >inline
grab()RefPtr< T >inlineprivate
operator!=(const T *p) constRefPtr< T >inline
operator!=(const RefPtr< T > &p) constRefPtr< T >inline
operator*() constRefPtr< T >inline
operator->() constRefPtr< T >inline
operator<(const RefPtr< T > &p) constRefPtr< T >inline
operator<(const RefPtr< Other > &p) constRefPtr< T >inline
operator=(T *p)RefPtr< T >inline
operator=(const RefPtr< T > &p)RefPtr< T >inline
operator==(const T *p) constRefPtr< T >inline
operator==(const RefPtr< T > &p) constRefPtr< T >inline
pointee()RefPtr< T >inline
pointee() constRefPtr< T >inline
ptr_RefPtr< T >private
RefPtr()RefPtr< T >inline
RefPtr(T *p)RefPtr< T >inline
RefPtr(const RefPtr< T > &p)RefPtr< T >inline
RefPtr(RefPtr< Other > p)RefPtr< T >inline
release()RefPtr< T >inlineprivate
Type typedefRefPtr< T >
~RefPtr()RefPtr< T >inline
+ + + + diff --git a/doc/doxygen/html/classRefPtr.html b/doc/doxygen/html/classRefPtr.html new file mode 100644 index 00000000..7f709571 --- /dev/null +++ b/doc/doxygen/html/classRefPtr.html @@ -0,0 +1,819 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: RefPtr< T > Class Template Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

#include <RefPtr.h>

+ + + + + +

+Public Types

typedef T Type
 Make the typename that this pointer holds accessible to other objects. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 RefPtr ()
 Construct a new RefPtr and initialize the pointee to NULL. More...
 
 RefPtr (T *p)
 Construct a new RefPtr and initialize the pointee as given. More...
 
 RefPtr (const RefPtr< T > &p)
 Construct a new RefPtr and initialize to the given RefPtr pointee. More...
 
template<class Other >
 RefPtr (RefPtr< Other > p)
 
 ~RefPtr ()
 Destroy this RefPtr. More...
 
RefPtr< T > & operator= (T *p)
 Assign the value of this RefPtr to the given pointee. More...
 
RefPtr< T > & operator= (const RefPtr< T > &p)
 Assign the value of this RefPtr to the pointee of the given RefPtr. More...
 
template<class Other >
RefPtr< T > & cast (Other *p)
 
template<class Other >
RefPtr< T > & cast (RefPtr< Other > p)
 
T * operator-> () const
 
T & operator* () const
 
T * pointee ()
 Return the pointee of this RefPtr. More...
 
const T * pointee () const
 Return the pointee of this RefPtr in a const context. More...
 
bool operator== (const T *p) const
 Compare the pointee of this RefPtr with the given pointer. More...
 
bool operator== (const RefPtr< T > &p) const
 Compare the value of this pointee with the pointee of the given RefPtr. More...
 
bool operator!= (const T *p) const
 Test inequality. More...
 
bool operator!= (const RefPtr< T > &p) const
 Test inequality. More...
 
bool operator< (const RefPtr< T > &p) const
 Convenience routine to sort pointer values in standard containers. More...
 
template<class Other >
bool operator< (const RefPtr< Other > &p) const
 Convenience routine to sort pointer values in standard containers. More...
 
+ + + + + + +

+Private Member Functions

void grab ()
 Grab a reference to the current pointee if it is not NULL. More...
 
void release ()
 
+ + + +

+Private Attributes

T * ptr_
 
+

Detailed Description

+

template<class T>
+class RefPtr< T >

+ +

Reference counted pointer that gives the holder modification privileges to the pointee.

+

Part of the Particle Simulation Toolkit (pst)

+

Member Typedef Documentation

+ +

◆ Type

+ +
+
+
+template<class T>
+ + + + +
typedef T RefPtr< T >::Type
+
+ +

Make the typename that this pointer holds accessible to other objects.

+ +
+
+

Constructor & Destructor Documentation

+ +

◆ RefPtr() [1/4]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
RefPtr< T >::RefPtr ()
+
+inline
+
+ +

Construct a new RefPtr and initialize the pointee to NULL.

+ +
+
+ +

◆ RefPtr() [2/4]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
RefPtr< T >::RefPtr (T * p)
+
+inline
+
+ +

Construct a new RefPtr and initialize the pointee as given.

+ +
+
+ +

◆ RefPtr() [3/4]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
RefPtr< T >::RefPtr (const RefPtr< T > & p)
+
+inline
+
+ +

Construct a new RefPtr and initialize to the given RefPtr pointee.

+ +
+
+ +

◆ RefPtr() [4/4]

+ +
+
+
+template<class T>
+
+template<class Other >
+ + + + + +
+ + + + + + + + +
RefPtr< T >::RefPtr (RefPtr< Other > p)
+
+inline
+
+

Perform a static cast to initialize this pointee. This cast is only valid if T is a parent class of Other

+ +
+
+ +

◆ ~RefPtr()

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
RefPtr< T >::~RefPtr ()
+
+inline
+
+ +

Destroy this RefPtr.

+ +
+
+

Member Function Documentation

+ +

◆ cast() [1/2]

+ +
+
+
+template<class T>
+
+template<class Other >
+ + + + + +
+ + + + + + + + +
RefPtr<T>& RefPtr< T >::cast (Other * p)
+
+inline
+
+

Use dynamic_cast to set the pointee to the pointer that was passed in, and return *this. The returned value is NULL if the cast fails.

+ +
+
+ +

◆ cast() [2/2]

+ +
+
+
+template<class T>
+
+template<class Other >
+ + + + + +
+ + + + + + + + +
RefPtr<T>& RefPtr< T >::cast (RefPtr< Other > p)
+
+inline
+
+

Use dynamic_cast to set the pointee to the pointee of the RefPtr given, and return *this. The returned value is NULL if the cast fails.

+ +
+
+ +

◆ grab()

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
void RefPtr< T >::grab ()
+
+inlineprivate
+
+ +

Grab a reference to the current pointee if it is not NULL.

+ +
+
+ +

◆ operator!=() [1/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
bool RefPtr< T >::operator!= (const T * p) const
+
+inline
+
+ +

Test inequality.

+ +
+
+ +

◆ operator!=() [2/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
bool RefPtr< T >::operator!= (const RefPtr< T > & p) const
+
+inline
+
+ +

Test inequality.

+ +
+
+ +

◆ operator*()

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
T& RefPtr< T >::operator* () const
+
+inline
+
+

Return a reference to the pointee of this RefPtr. This will not work right if the pointee is NULL.

+ +
+
+ +

◆ operator->()

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
T* RefPtr< T >::operator-> () const
+
+inline
+
+

Return the pointee of this RefPtr. This will throw an exception if the pointee is NULL.

+ +
+
+ +

◆ operator<() [1/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
bool RefPtr< T >::operator< (const RefPtr< T > & p) const
+
+inline
+
+ +

Convenience routine to sort pointer values in standard containers.

+ +
+
+ +

◆ operator<() [2/2]

+ +
+
+
+template<class T>
+
+template<class Other >
+ + + + + +
+ + + + + + + + +
bool RefPtr< T >::operator< (const RefPtr< Other > & p) const
+
+inline
+
+ +

Convenience routine to sort pointer values in standard containers.

+ +
+
+ +

◆ operator=() [1/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
RefPtr<T>& RefPtr< T >::operator= (T * p)
+
+inline
+
+ +

Assign the value of this RefPtr to the given pointee.

+ +
+
+ +

◆ operator=() [2/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
RefPtr<T>& RefPtr< T >::operator= (const RefPtr< T > & p)
+
+inline
+
+ +

Assign the value of this RefPtr to the pointee of the given RefPtr.

+ +
+
+ +

◆ operator==() [1/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
bool RefPtr< T >::operator== (const T * p) const
+
+inline
+
+ +

Compare the pointee of this RefPtr with the given pointer.

+ +
+
+ +

◆ operator==() [2/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + + +
bool RefPtr< T >::operator== (const RefPtr< T > & p) const
+
+inline
+
+ +

Compare the value of this pointee with the pointee of the given RefPtr.

+ +
+
+ +

◆ pointee() [1/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
T* RefPtr< T >::pointee ()
+
+inline
+
+ +

Return the pointee of this RefPtr.

+ +
+
+ +

◆ pointee() [2/2]

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
const T* RefPtr< T >::pointee () const
+
+inline
+
+ +

Return the pointee of this RefPtr in a const context.

+ +
+
+ +

◆ release()

+ +
+
+
+template<class T>
+ + + + + +
+ + + + + + + +
void RefPtr< T >::release ()
+
+inlineprivate
+
+

Release the reference to the current pointee if it is not NULL. If this results in the reference count of the pointee dropping to zero, delete the object pointed to.

+ +
+
+

Member Data Documentation

+ +

◆ ptr_

+ +
+
+
+template<class T>
+ + + + + +
+ + + + +
T* RefPtr< T >::ptr_
+
+private
+
+ +
+
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/doc/doxygen/html/classXMLAttributeList-members.html b/doc/doxygen/html/classXMLAttributeList-members.html new file mode 100644 index 00000000..c2aad241 --- /dev/null +++ b/doc/doxygen/html/classXMLAttributeList-members.html @@ -0,0 +1,93 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
XMLAttributeList Member List
+
+
+ +

This is the complete list of members for XMLAttributeList, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
attribute_XMLAttributeListprivate
begin()XMLAttributeList
begin() constXMLAttributeList
boolean_value(const std::string &, const char *where) constXMLAttributeListprivate
const_iterator typedefXMLAttributeList
ConstRefPtr classXMLAttributeListfriend
end()XMLAttributeList
end() constXMLAttributeList
get(const std::string &) constXMLAttributeList
get(const std::string &, const std::string &) constXMLAttributeList
get_bool(const std::string &) constXMLAttributeList
get_bool(const std::string &, bool) constXMLAttributeList
get_double(const std::string &) constXMLAttributeList
get_double(const std::string &, double) constXMLAttributeList
get_int(const std::string &) constXMLAttributeList
get_int(const std::string &, int) constXMLAttributeList
get_location(const std::string &)XMLAttributeListprivate
get_location(const std::string &) constXMLAttributeListprivate
has(const std::string &) constXMLAttributeList
iterator typedefXMLAttributeList
make_lower_case(std::string &) constXMLAttributeListprivate
Map_t typedefXMLAttributeList
Object()Objectinline
operator=(const XMLAttributeList &)XMLAttributeListprivate
reference_count() constObjectinline
reference_grab() constObjectinlineprotected
reference_release() constObjectinlineprotected
RefPtr classXMLAttributeListfriend
set(const std::string &, const std::string &)XMLAttributeList
set_bool(const std::string &, bool)XMLAttributeList
set_double(const std::string &, double)XMLAttributeList
set_int(const std::string &, int)XMLAttributeList
size() constXMLAttributeList
XMLAttributeList()XMLAttributeList
XMLAttributeList(const XMLAttributeList &)XMLAttributeListprivate
~Object()Objectinlinevirtual
~XMLAttributeList()XMLAttributeListvirtual
+ + + + diff --git a/doc/doxygen/html/classXMLAttributeList.html b/doc/doxygen/html/classXMLAttributeList.html new file mode 100644 index 00000000..8e017df7 --- /dev/null +++ b/doc/doxygen/html/classXMLAttributeList.html @@ -0,0 +1,1016 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLAttributeList Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

#include <XMLAttributeList.h>

+
+Inheritance diagram for XMLAttributeList:
+
+
+ + +Object + +
+ + + + + + + + + + +

+Public Types

typedef std::map< std::string, std::string > Map_t
 The container type used to hold the attributes. More...
 
typedef Map_t::iterator iterator
 The iterator type returned by this implementation. More...
 
typedef Map_t::const_iterator const_iterator
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 XMLAttributeList ()
 Construct a blank attribute list. More...
 
virtual ~XMLAttributeList ()
 Destroy this list. More...
 
int size () const
 Get the number of attributes in the list. More...
 
bool has (const std::string &) const
 Return true if the given key is defined. More...
 
const std::string & get (const std::string &) const
 
std::string get (const std::string &, const std::string &) const
 
int get_int (const std::string &) const
 
int get_int (const std::string &, int) const
 
double get_double (const std::string &) const
 
double get_double (const std::string &, double) const
 
bool get_bool (const std::string &) const
 
bool get_bool (const std::string &, bool) const
 
void set (const std::string &, const std::string &)
 Assign a text attribute to the given key. More...
 
void set_int (const std::string &, int)
 Assign an integer value to the given key. More...
 
void set_double (const std::string &, double)
 Assign a numerical value to the given key. More...
 
void set_bool (const std::string &, bool)
 
iterator begin ()
 Get an iterator to the first element. More...
 
iterator end ()
 Get an iterator past the last element. More...
 
const_iterator begin () const
 Get an iterator to the first element in a const context. More...
 
const_iterator end () const
 Get an iterator past the last element in a const context. More...
 
- Public Member Functions inherited from Object
 Object ()
 Construct a new reference counted object with a zero reference count. More...
 
virtual ~Object ()
 Destroy this object. More...
 
long int reference_count () const
 Returns the number of references that are held to this object. More...
 
+ + + + + + + + + + + + + + + + +

+Private Member Functions

 XMLAttributeList (const XMLAttributeList &)
 Blocked copy constructor. Throws an exception. More...
 
XMLAttributeListoperator= (const XMLAttributeList &)
 
void make_lower_case (std::string &) const
 
iterator get_location (const std::string &)
 Get an iterator pointing to the location of the given string. More...
 
const_iterator get_location (const std::string &) const
 Get an iterator to a location in a const context. More...
 
bool boolean_value (const std::string &, const char *where) const
 
+ + + + +

+Private Attributes

Map_t attribute_
 The attributes. More...
 
+ + + + + + + +

+Friends

template<class T >
class RefPtr
 
template<class T >
class ConstRefPtr
 
+ + + + + + +

+Additional Inherited Members

- Protected Member Functions inherited from Object
long int reference_grab () const
 
long int reference_release () const
 
+

Detailed Description

+

The implementation of a container for XML attributes.

+

Attributes are stored as key-value pairs, both of which are stored as text strings. The keys are stored and handled in a case-sensitive manner, whereas the values are stored exactly as given.

+

The order in which attributes were added is not preserved. I am not sure whether this is a problem or not.

+

Boolean values are a special case. They are treated in a case-insensitive manner. True boolean values are returned for the strings 'true', 'yes', and non-zero numerical values. False boolean values are returned for the strings 'false', 'no', and zero values. All other strings are considered unacceptable boolean values.

+

Written by Helgi Adalsteinsson Modified by Bert Debusschere, 3/13/08 to make keys case-sensitive

+

Member Typedef Documentation

+ +

◆ const_iterator

+ +
+
+ + + + +
typedef Map_t::const_iterator XMLAttributeList::const_iterator
+
+ +
+
+ +

◆ iterator

+ +
+
+ + + + +
typedef Map_t::iterator XMLAttributeList::iterator
+
+ +

The iterator type returned by this implementation.

+ +
+
+ +

◆ Map_t

+ +
+
+ + + + +
typedef std::map< std::string, std::string > XMLAttributeList::Map_t
+
+ +

The container type used to hold the attributes.

+ +
+
+

Constructor & Destructor Documentation

+ +

◆ XMLAttributeList() [1/2]

+ +
+
+ + + + + + + +
XMLAttributeList::XMLAttributeList ()
+
+ +

Construct a blank attribute list.

+ +
+
+ +

◆ XMLAttributeList() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
XMLAttributeList::XMLAttributeList (const XMLAttributeList)
+
+private
+
+ +

Blocked copy constructor. Throws an exception.

+ +
+
+ +

◆ ~XMLAttributeList()

+ +
+
+ + + + + +
+ + + + + + + +
XMLAttributeList::~XMLAttributeList ()
+
+virtual
+
+ +

Destroy this list.

+ +
+
+

Member Function Documentation

+ +

◆ begin() [1/2]

+ +
+
+ + + + + + + +
XMLAttributeList::iterator XMLAttributeList::begin ()
+
+ +

Get an iterator to the first element.

+ +
+
+ +

◆ begin() [2/2]

+ +
+
+ + + + + + + +
XMLAttributeList::const_iterator XMLAttributeList::begin () const
+
+ +

Get an iterator to the first element in a const context.

+ +
+
+ +

◆ boolean_value()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
bool XMLAttributeList::boolean_value (const std::string & str,
const char * where 
) const
+
+private
+
+

Return the boolean value of the given string.

Exceptions
+ + +
MyExceptionif the string is not a valid boolean value.
+
+
+ +
+
+ +

◆ end() [1/2]

+ +
+
+ + + + + + + +
XMLAttributeList::iterator XMLAttributeList::end ()
+
+ +

Get an iterator past the last element.

+ +
+
+ +

◆ end() [2/2]

+ +
+
+ + + + + + + +
XMLAttributeList::const_iterator XMLAttributeList::end () const
+
+ +

Get an iterator past the last element in a const context.

+ +
+
+ +

◆ get() [1/2]

+ +
+
+ + + + + + + + +
const std::string & XMLAttributeList::get (const std::string & key) const
+
+

Get the attribute associated with the given key.

Exceptions
+ + +
MyExceptionif the key is not defined.
+
+
+ +
+
+ +

◆ get() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
std::string XMLAttributeList::get (const std::string & key,
const std::string & def 
) const
+
+

Get the attribute associated with the given key or return the given default value if the key is not defined.

+ +
+
+ +

◆ get_bool() [1/2]

+ +
+
+ + + + + + + + +
bool XMLAttributeList::get_bool (const std::string & key) const
+
+

Get the given attribute as a boolean value.

Exceptions
+ + + +
MyExceptionif the key is not defined.
MyExceptionif the value is not a valid boolean value. True boolean values are "yes", "true", and 'non-zero' numerical values. False boolean values are "no" "false", and 'zero' numerical values.
+
+
+ +
+
+ +

◆ get_bool() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
bool XMLAttributeList::get_bool (const std::string & key,
bool def 
) const
+
+

Get the given attribute as a boolean value or return the given default value if the key is not defined.

Exceptions
+ + +
MyExceptionif the value is not a valid boolean value.
+
+
+ +
+
+ +

◆ get_double() [1/2]

+ +
+
+ + + + + + + + +
double XMLAttributeList::get_double (const std::string & key) const
+
+

Get the given attribute as a real value.

Exceptions
+ + + +
MyExceptionif the key is not defined.
MyExceptionif the value is not a valid number.
+
+
+ +
+
+ +

◆ get_double() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
double XMLAttributeList::get_double (const std::string & key,
double def 
) const
+
+

Get the given attribute as a real value or return the given default value if the key is not defined.

Exceptions
+ + +
MyExceptionif the value is set and is not a valid number.
+
+
+ +
+
+ +

◆ get_int() [1/2]

+ +
+
+ + + + + + + + +
int XMLAttributeList::get_int (const std::string & key) const
+
+

Get the given attribute as an integer value.

Exceptions
+ + + +
MyExceptionif the key is not defined.
MyExceptionif the value is not a valid integer.
+
+
+ +
+
+ +

◆ get_int() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
int XMLAttributeList::get_int (const std::string & key,
int def 
) const
+
+

Get the given attribute as an integer value or return the given default value if the key is not defined.

Exceptions
+ + +
MyExceptionif the value is set and is not a valid integer.
+
+
+ +
+
+ +

◆ get_location() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
XMLAttributeList::iterator XMLAttributeList::get_location (const std::string & key)
+
+private
+
+ +

Get an iterator pointing to the location of the given string.

+ +
+
+ +

◆ get_location() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
XMLAttributeList::const_iterator XMLAttributeList::get_location (const std::string & key) const
+
+private
+
+ +

Get an iterator to a location in a const context.

+ +
+
+ +

◆ has()

+ +
+
+ + + + + + + + +
bool XMLAttributeList::has (const std::string & key) const
+
+ +

Return true if the given key is defined.

+ +
+
+ +

◆ make_lower_case()

+ +
+
+ + + + + +
+ + + + + + + + +
void XMLAttributeList::make_lower_case (std::string & str) const
+
+private
+
+

Convert a string to lower case (conversion in place). (needed to handle boolean values)

+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
XMLAttributeList & XMLAttributeList::operator= (const XMLAttributeList)
+
+private
+
+

Blocked assignment operator.

Exceptions
+ + +
MyException
+
+
+ +
+
+ +

◆ set()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void XMLAttributeList::set (const std::string & key,
const std::string & val 
)
+
+ +

Assign a text attribute to the given key.

+ +
+
+ +

◆ set_bool()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void XMLAttributeList::set_bool (const std::string & key,
bool val 
)
+
+

Assign a boolean attribute to the given key. True boolean values are added as "true", false as "false"

+ +
+
+ +

◆ set_double()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void XMLAttributeList::set_double (const std::string & key,
double val 
)
+
+ +

Assign a numerical value to the given key.

+ +
+
+ +

◆ set_int()

+ +
+
+ + + + + + + + + + + + + + + + + + +
void XMLAttributeList::set_int (const std::string & key,
int val 
)
+
+ +

Assign an integer value to the given key.

+ +
+
+ +

◆ size()

+ +
+
+ + + + + + + +
int XMLAttributeList::size () const
+
+ +

Get the number of attributes in the list.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ ConstRefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class ConstRefPtr
+
+friend
+
+ +
+
+ +

◆ RefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class RefPtr
+
+friend
+
+ +
+
+

Member Data Documentation

+ +

◆ attribute_

+ +
+
+ + + + + +
+ + + + +
Map_t XMLAttributeList::attribute_
+
+private
+
+ +

The attributes.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classXMLAttributeList.png b/doc/doxygen/html/classXMLAttributeList.png new file mode 100644 index 00000000..83043e1f Binary files /dev/null and b/doc/doxygen/html/classXMLAttributeList.png differ diff --git a/doc/doxygen/html/classXMLElement-members.html b/doc/doxygen/html/classXMLElement-members.html new file mode 100644 index 00000000..da882ba8 --- /dev/null +++ b/doc/doxygen/html/classXMLElement-members.html @@ -0,0 +1,87 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
XMLElement Member List
+
+
+ +

This is the complete list of members for XMLElement, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
add_child(RefPtr< XMLElement >)XMLElement
add_child_rpt(RefPtr< XMLElement >)XMLElement
add_content_line(const std::string &)XMLElement
attributes()XMLElement
attributes_XMLElementprivate
children_XMLElementprivate
clear_children()XMLElement
clear_content()XMLElement
ConstRefPtr classXMLElementfriend
content_XMLElementprivate
count_attributes() constXMLElement
count_children() constXMLElement
count_content() constXMLElement
get_child(int)XMLElement
get_child(const std::string &)XMLElement
get_content_line(int)XMLElement
label() constXMLElement
label_XMLElementprivate
Object()Objectinline
operator=(const XMLElement &)XMLElementprivate
recurse(RefPtr< XMLElement >, std::set< RefPtr< XMLElement > >)XMLElementprivate
reference_count() constObjectinline
reference_grab() constObjectinlineprotected
reference_release() constObjectinlineprotected
RefPtr classXMLElementfriend
set_attributes(RefPtr< XMLAttributeList >)XMLElement
set_label(const std::string &)XMLElement
XMLElement(const std::string &)XMLElement
XMLElement(const XMLElement &)XMLElementprivate
~Object()Objectinlinevirtual
~XMLElement()XMLElementvirtual
+ + + + diff --git a/doc/doxygen/html/classXMLElement.html b/doc/doxygen/html/classXMLElement.html new file mode 100644 index 00000000..e532ec75 --- /dev/null +++ b/doc/doxygen/html/classXMLElement.html @@ -0,0 +1,787 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLElement Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

#include <XMLElement.h>

+
+Inheritance diagram for XMLElement:
+
+
+ + +Object + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 XMLElement (const std::string &)
 Construct a new xml element object and give it a label. More...
 
virtual ~XMLElement ()
 Destructor. More...
 
const std::string & label () const
 Get the label of this node. More...
 
void set_label (const std::string &)
 Assign a new label to this node. More...
 
int count_attributes () const
 
RefPtr< XMLAttributeListattributes ()
 Get access to the attribute list. More...
 
void set_attributes (RefPtr< XMLAttributeList >)
 Assign an attribute list to this element. More...
 
int count_children () const
 Utility function to check how many children this element has. More...
 
RefPtr< XMLElementget_child (int)
 
RefPtr< XMLElementget_child (const std::string &)
 
void add_child (RefPtr< XMLElement >)
 
void add_child_rpt (RefPtr< XMLElement >)
 Same as add_child, but this allows for repeating children. More...
 
void clear_children ()
 Erase all child elements from this node. More...
 
int count_content () const
 
const std::string & get_content_line (int)
 
void add_content_line (const std::string &)
 Add a line of content. More...
 
void clear_content ()
 Clear all text content. More...
 
- Public Member Functions inherited from Object
 Object ()
 Construct a new reference counted object with a zero reference count. More...
 
virtual ~Object ()
 Destroy this object. More...
 
long int reference_count () const
 Returns the number of references that are held to this object. More...
 
+ + + + + + + +

+Private Member Functions

 XMLElement (const XMLElement &)
 
XMLElementoperator= (const XMLElement &)
 
void recurse (RefPtr< XMLElement >, std::set< RefPtr< XMLElement > >)
 
+ + + + + + + + + + + + + +

+Private Attributes

std::string label_
 The iterator type returned for list of children. More...
 
RefPtr< XMLAttributeListattributes_
 The list of attributes associated with this element. More...
 
std::vector< RefPtr< XMLElement > > children_
 The list of children associated with this element. More...
 
std::vector< std::string > content_
 The list of content associated with this element. More...
 
+ + + + + + + +

+Friends

template<class T >
class RefPtr
 
template<class T >
class ConstRefPtr
 
+ + + + + + +

+Additional Inherited Members

- Protected Member Functions inherited from Object
long int reference_grab () const
 
long int reference_release () const
 
+

Detailed Description

+

This is the implementation of a node in an XML parse tree. Each node contains the following three containers, any (or all) of which may be empty.

+

attributes (XMLAttributeList): Contains attributes (key/value pairs). children (Vector<XMLElement>): Contains children of this node. content (Vector<std::string>): Contains content (text) data.

+

The implementation is very limited. In particular, the following advanced features are missing:

+

encoding: Support for character types other than char/std::string. comments: Allowing comment blocks to accompany each element. other xml types (control statements, etc.).

+

This implementation is heavily based on Kevin Long's XMLObject.

+

Constructor & Destructor Documentation

+ +

◆ XMLElement() [1/2]

+ +
+
+ + + + + + + + +
XMLElement::XMLElement (const std::string & lbl)
+
+ +

Construct a new xml element object and give it a label.

+ +
+
+ +

◆ XMLElement() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
XMLElement::XMLElement (const XMLElement)
+
+private
+
+

Blocked copy constructor.

Exceptions
+ + +
MyException.
+
+
+ +
+
+ +

◆ ~XMLElement()

+ +
+
+ + + + + +
+ + + + + + + +
XMLElement::~XMLElement ()
+
+virtual
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ add_child()

+ +
+
+ + + + + + + + +
void XMLElement::add_child (RefPtr< XMLElementkid)
+
+

Add a child to the back of the list. Ignored if the child is already in the list.

Exceptions
+ + + +
MyExceptionif adding the child would result in a cyclic relationship.
MyExceptionif the child holds a NULL pointer.
+
+
+ +
+
+ +

◆ add_child_rpt()

+ +
+
+ + + + + + + + +
void XMLElement::add_child_rpt (RefPtr< XMLElementkid)
+
+ +

Same as add_child, but this allows for repeating children.

+ +
+
+ +

◆ add_content_line()

+ +
+
+ + + + + + + + +
void XMLElement::add_content_line (const std::string & text)
+
+ +

Add a line of content.

+ +
+
+ +

◆ attributes()

+ +
+
+ + + + + + + +
RefPtr< XMLAttributeList > XMLElement::attributes ()
+
+ +

Get access to the attribute list.

+ +
+
+ +

◆ clear_children()

+ +
+
+ + + + + + + +
void XMLElement::clear_children ()
+
+ +

Erase all child elements from this node.

+ +
+
+ +

◆ clear_content()

+ +
+
+ + + + + + + +
void XMLElement::clear_content ()
+
+ +

Clear all text content.

+ +
+
+ +

◆ count_attributes()

+ +
+
+ + + + + + + +
int XMLElement::count_attributes () const
+
+

Utility function to check how many attributes this element has. This amounts to the same as calling '.attributes().size()'

+ +
+
+ +

◆ count_children()

+ +
+
+ + + + + + + +
int XMLElement::count_children () const
+
+ +

Utility function to check how many children this element has.

+ +
+
+ +

◆ count_content()

+ +
+
+ + + + + + + +
int XMLElement::count_content () const
+
+

Utility function to check how many lines of text content are associated with this element.

+ +
+
+ +

◆ get_child() [1/2]

+ +
+
+ + + + + + + + +
RefPtr< XMLElement > XMLElement::get_child (int index)
+
+

Get the child with the given index.

Exceptions
+ + +
MyExceptionif the index is invalid.
+
+
+ +
+
+ +

◆ get_child() [2/2]

+ +
+
+ + + + + + + + +
RefPtr< XMLElement > XMLElement::get_child (const std::string & lbl)
+
+

Find the first instance of a child with a given label and return a pointer to it.

Note
Since child labels do not need to be unique, there may be multiple instances matching children
+
Exceptions
+ + +
MyExceptionif the child label can not be found
+
+
+
Todo:
Make this more elegant with the STL find_if function
+ +
+
+ +

◆ get_content_line()

+ +
+
+ + + + + + + + +
const std::string & XMLElement::get_content_line (int index)
+
+

Get a line of content by index.

Exceptions
+ + +
MyExceptionif the index is out of range.
+
+
+ +
+
+ +

◆ label()

+ +
+
+ + + + + + + +
const std::string & XMLElement::label () const
+
+ +

Get the label of this node.

+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
XMLElement & XMLElement::operator= (const XMLElement)
+
+private
+
+

Blocked assignment operator.

Exceptions
+ + +
MyExcepiton.
+
+
+ +
+
+ +

◆ recurse()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void XMLElement::recurse (RefPtr< XMLElementkid,
std::set< RefPtr< XMLElement > > seen 
)
+
+private
+
+

A private routine called recursively to ensure that we don't have a cyclic relationship.

+ +
+
+ +

◆ set_attributes()

+ +
+
+ + + + + + + + +
void XMLElement::set_attributes (RefPtr< XMLAttributeListatt)
+
+ +

Assign an attribute list to this element.

+ +
+
+ +

◆ set_label()

+ +
+
+ + + + + + + + +
void XMLElement::set_label (const std::string & lbl)
+
+ +

Assign a new label to this node.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ ConstRefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class ConstRefPtr
+
+friend
+
+ +
+
+ +

◆ RefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class RefPtr
+
+friend
+
+ +
+
+

Member Data Documentation

+ +

◆ attributes_

+ +
+
+ + + + + +
+ + + + +
RefPtr<XMLAttributeList> XMLElement::attributes_
+
+private
+
+ +

The list of attributes associated with this element.

+ +
+
+ +

◆ children_

+ +
+
+ + + + + +
+ + + + +
std::vector< RefPtr<XMLElement> > XMLElement::children_
+
+private
+
+ +

The list of children associated with this element.

+ +
+
+ +

◆ content_

+ +
+
+ + + + + +
+ + + + +
std::vector<std::string> XMLElement::content_
+
+private
+
+ +

The list of content associated with this element.

+ +
+
+ +

◆ label_

+ +
+
+ + + + + +
+ + + + +
std::string XMLElement::label_
+
+private
+
+ +

The iterator type returned for list of children.

+

The label of this element.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classXMLElement.png b/doc/doxygen/html/classXMLElement.png new file mode 100644 index 00000000..b2ac6262 Binary files /dev/null and b/doc/doxygen/html/classXMLElement.png differ diff --git a/doc/doxygen/html/classXMLExpatParser-members.html b/doc/doxygen/html/classXMLExpatParser-members.html new file mode 100644 index 00000000..a028d64f --- /dev/null +++ b/doc/doxygen/html/classXMLExpatParser-members.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
XMLExpatParser Member List
+
+
+ +

This is the complete list of members for XMLExpatParser, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
character_data_(void *, const XML_Char *, int)XMLExpatParserstatic
ConstRefPtr classXMLExpatParserfriend
do_character_data(const XML_Char *, int)XMLExpatParserprivate
do_end(const XML_Char *)XMLExpatParserprivate
do_start(const XML_Char *, const XML_Char **)XMLExpatParserprivate
end_(void *, const XML_Char *)XMLExpatParserstatic
init()XMLExpatParserprivate
leaf_XMLExpatParserprivate
Object()Objectinline
operator=(const XMLExpatParser &)XMLExpatParserprivate
parse(std::istream &)XMLExpatParservirtual
parser_XMLExpatParserprivate
path_XMLExpatParserprivate
reference_count() constObjectinline
reference_grab() constObjectinlineprotected
reference_release() constObjectinlineprotected
RefPtr classXMLExpatParserfriend
start_(void *, const XML_Char *, const XML_Char **)XMLExpatParserstatic
XMLExpatParser()XMLExpatParser
XMLExpatParser(const XMLExpatParser &)XMLExpatParserprivate
XMLParser()XMLParser
~Object()Objectinlinevirtual
~XMLExpatParser()XMLExpatParservirtual
~XMLParser()XMLParservirtual
+ + + + diff --git a/doc/doxygen/html/classXMLExpatParser.html b/doc/doxygen/html/classXMLExpatParser.html new file mode 100644 index 00000000..59252cf9 --- /dev/null +++ b/doc/doxygen/html/classXMLExpatParser.html @@ -0,0 +1,683 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLExpatParser Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+ +

#include <XMLExpatParser.h>

+
+Inheritance diagram for XMLExpatParser:
+
+
+ + +XMLParser +Object + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 XMLExpatParser ()
 Construct a new parser. More...
 
virtual ~XMLExpatParser () throw ()
 Destructor. More...
 
RefPtr< XMLElementparse (std::istream &)
 Parse the given input buffer and return a parse tree. More...
 
- Public Member Functions inherited from XMLParser
 XMLParser ()
 Default constructor. Intended for derived classes. More...
 
virtual ~XMLParser ()
 Destructor. More...
 
- Public Member Functions inherited from Object
 Object ()
 Construct a new reference counted object with a zero reference count. More...
 
virtual ~Object ()
 Destroy this object. More...
 
long int reference_count () const
 Returns the number of references that are held to this object. More...
 
+ + + + + + + +

+Static Public Member Functions

static void start_ (void *, const XML_Char *, const XML_Char **)
 
static void end_ (void *, const XML_Char *)
 
static void character_data_ (void *, const XML_Char *, int)
 
+ + + + + + + + + + + + + + + + + + +

+Private Member Functions

 XMLExpatParser (const XMLExpatParser &)
 
XMLExpatParseroperator= (const XMLExpatParser &)
 Blocked assignment operator. Not for public consumption. More...
 
void do_start (const XML_Char *, const XML_Char **)
 The method used to parse the start tag. More...
 
void do_end (const XML_Char *)
 The method used to parse the end tag. More...
 
void do_character_data (const XML_Char *, int)
 The method used to parse character (content) data. More...
 
void init ()
 Initialize the state of the parser. More...
 
+ + + + + + + + + + +

+Private Attributes

XML_Parser parser_
 The Expat parser. More...
 
std::vector< RefPtr< XMLElement > > path_
 The path that we have traversed so far in building the tree. More...
 
RefPtr< XMLElementleaf_
 The current leaf of the parse tree. More...
 
+ + + + + + + +

+Friends

template<class T >
class RefPtr
 
template<class T >
class ConstRefPtr
 
+ + + + + + +

+Additional Inherited Members

- Protected Member Functions inherited from Object
long int reference_grab () const
 
long int reference_release () const
 
+

Detailed Description

+

An XML parser that uses the Expat library to handle the gruntwork. This class requires that the Expat be installed on your system.

+

Expat is available at the Expat site

+

This class may not be fully exception safe, since there is no good way of enforcing that the Expat parser is destroyed cleanly.

+

Constructor & Destructor Documentation

+ +

◆ XMLExpatParser() [1/2]

+ +
+
+ + + + + + + +
XMLExpatParser::XMLExpatParser ()
+
+ +

Construct a new parser.

+ +
+
+ +

◆ XMLExpatParser() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + +
XMLExpatParser::XMLExpatParser (const XMLExpatParser)
+
+private
+
+

Blocked copy constructor. It is not safe to copy this object since the Expat parser may save state which cannot be duplicated.

+ +
+
+ +

◆ ~XMLExpatParser()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + +
XMLExpatParser::~XMLExpatParser ()
throw (
)
+
+virtual
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ character_data_()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void XMLExpatParser::character_data_ (void * object,
const XML_Char * data,
int size 
)
+
+static
+
+

Static wrapper method used as a callback to get character data. This method is for internal use only. Calling this method directly will most likely result in a segmentation fault.

+ +
+
+ +

◆ do_character_data()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void XMLExpatParser::do_character_data (const XML_Char * data,
int size 
)
+
+private
+
+ +

The method used to parse character (content) data.

+ +
+
+ +

◆ do_end()

+ +
+
+ + + + + +
+ + + + + + + + +
void XMLExpatParser::do_end (const XML_Char * )
+
+private
+
+ +

The method used to parse the end tag.

+ +
+
+ +

◆ do_start()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void XMLExpatParser::do_start (const XML_Char * lbl,
const XML_Char ** attr 
)
+
+private
+
+ +

The method used to parse the start tag.

+ +
+
+ +

◆ end_()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void XMLExpatParser::end_ (void * object,
const XML_Char * label 
)
+
+static
+
+

Static wrapper method used as a callback to get the 'end' tag. This method is for internal use only. Calling this method directly will most likely result in a segmentation fault.

+ +
+
+ +

◆ init()

+ +
+
+ + + + + +
+ + + + + + + +
void XMLExpatParser::init ()
+
+private
+
+ +

Initialize the state of the parser.

+ +
+
+ +

◆ operator=()

+ +
+
+ + + + + +
+ + + + + + + + +
XMLExpatParser & XMLExpatParser::operator= (const XMLExpatParser)
+
+private
+
+ +

Blocked assignment operator. Not for public consumption.

+ +
+
+ +

◆ parse()

+ +
+
+ + + + + +
+ + + + + + + + +
RefPtr< XMLElement > XMLExpatParser::parse (std::istream & buf)
+
+virtual
+
+ +

Parse the given input buffer and return a parse tree.

+ +

Implements XMLParser.

+ +
+
+ +

◆ start_()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void XMLExpatParser::start_ (void * object,
const XML_Char * label,
const XML_Char ** attributes 
)
+
+static
+
+

Static wrapper method used as a callback to get the 'start' tag. This method is for internal use only. Calling this method directly will most likely result in a segmentation fault.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ ConstRefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class ConstRefPtr
+
+friend
+
+ +
+
+ +

◆ RefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class RefPtr
+
+friend
+
+ +
+
+

Member Data Documentation

+ +

◆ leaf_

+ +
+
+ + + + + +
+ + + + +
RefPtr<XMLElement> XMLExpatParser::leaf_
+
+private
+
+ +

The current leaf of the parse tree.

+ +
+
+ +

◆ parser_

+ +
+
+ + + + + +
+ + + + +
XML_Parser XMLExpatParser::parser_
+
+private
+
+ +

The Expat parser.

+ +
+
+ +

◆ path_

+ +
+
+ + + + + +
+ + + + +
std::vector< RefPtr<XMLElement> > XMLExpatParser::path_
+
+private
+
+ +

The path that we have traversed so far in building the tree.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classXMLExpatParser.png b/doc/doxygen/html/classXMLExpatParser.png new file mode 100644 index 00000000..39b6dd4a Binary files /dev/null and b/doc/doxygen/html/classXMLExpatParser.png differ diff --git a/doc/doxygen/html/classXMLParser-members.html b/doc/doxygen/html/classXMLParser-members.html new file mode 100644 index 00000000..5a7eecc0 --- /dev/null +++ b/doc/doxygen/html/classXMLParser-members.html @@ -0,0 +1,66 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Member List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
XMLParser Member List
+
+
+ +

This is the complete list of members for XMLParser, including all inherited members.

+ + + + + + + + + + + +
ConstRefPtr classXMLParserfriend
Object()Objectinline
parse(std::istream &)=0XMLParserpure virtual
reference_count() constObjectinline
reference_grab() constObjectinlineprotected
reference_release() constObjectinlineprotected
RefPtr classXMLParserfriend
XMLParser()XMLParser
~Object()Objectinlinevirtual
~XMLParser()XMLParservirtual
+ + + + diff --git a/doc/doxygen/html/classXMLParser.html b/doc/doxygen/html/classXMLParser.html new file mode 100644 index 00000000..033642d5 --- /dev/null +++ b/doc/doxygen/html/classXMLParser.html @@ -0,0 +1,242 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: XMLParser Class Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+ +
+
XMLParser Class Referenceabstract
+
+
+ +

#include <XMLParser.h>

+
+Inheritance diagram for XMLParser:
+
+
+ + +Object +XMLExpatParser + +
+ + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 XMLParser ()
 Default constructor. Intended for derived classes. More...
 
virtual ~XMLParser ()
 Destructor. More...
 
virtual RefPtr< XMLElementparse (std::istream &)=0
 Parse the given input buffer and return the parse tree. More...
 
- Public Member Functions inherited from Object
 Object ()
 Construct a new reference counted object with a zero reference count. More...
 
virtual ~Object ()
 Destroy this object. More...
 
long int reference_count () const
 Returns the number of references that are held to this object. More...
 
+ + + + + + + +

+Friends

template<class T >
class RefPtr
 
template<class T >
class ConstRefPtr
 
+ + + + + + +

+Additional Inherited Members

- Protected Member Functions inherited from Object
long int reference_grab () const
 
long int reference_release () const
 
+

Detailed Description

+

A pure abstract base class for parsers that read data from an XML file and return the top node of a parse tree. The parse tree node is a RefPtr< XMLElement >.

+

Constructor & Destructor Documentation

+ +

◆ XMLParser()

+ +
+
+ + + + + + + +
XMLParser::XMLParser ()
+
+ +

Default constructor. Intended for derived classes.

+ +
+
+ +

◆ ~XMLParser()

+ +
+
+ + + + + +
+ + + + + + + +
XMLParser::~XMLParser ()
+
+virtual
+
+ +

Destructor.

+ +
+
+

Member Function Documentation

+ +

◆ parse()

+ +
+
+ + + + + +
+ + + + + + + + +
virtual RefPtr<XMLElement> XMLParser::parse (std::istream & )
+
+pure virtual
+
+ +

Parse the given input buffer and return the parse tree.

+ +

Implemented in XMLExpatParser.

+ +
+
+

Friends And Related Function Documentation

+ +

◆ ConstRefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class ConstRefPtr
+
+friend
+
+ +
+
+ +

◆ RefPtr

+ +
+
+
+template<class T >
+ + + + + +
+ + + + +
friend class RefPtr
+
+friend
+
+ +
+
+
The documentation for this class was generated from the following files: +
+ + + + diff --git a/doc/doxygen/html/classXMLParser.png b/doc/doxygen/html/classXMLParser.png new file mode 100644 index 00000000..bd780376 Binary files /dev/null and b/doc/doxygen/html/classXMLParser.png differ diff --git a/doc/doxygen/html/classes.html b/doc/doxygen/html/classes.html new file mode 100644 index 00000000..c9c13e53 --- /dev/null +++ b/doc/doxygen/html/classes.html @@ -0,0 +1,86 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Index + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Class Index
+
+
+
a | c | d | g | k | l | m | o | p | q | r | x
+ + + + + + + + + + + + + + + + + + +
  a  
+
DFISetup   Lik_GausMarg   MCMC::outputpar   RefPtr   
DFISetupBase   Lik_GausMargD   
  p  
+
  x  
+
Array1D   
  g  
+
Lik_Koh   
Array1D< double >   Lik_Marg   PCBasis   XMLAttributeList   
Array1D< int >   Gproc   Lik_MVN   PCreg   XMLElement   
Array2D   
  k  
+
LikelihoodBase   PCSet   XMLExpatParser   
Array3D   Lreg   PLreg   XMLParser   
  c  
+
KLDecompUni   
  m  
+
Post   
  l  
+
  q  
+
MCMC::chainstate   MCMC   
  d  
+
Lik_ABC   MCMC::methodpar   Quad   
Lik_ABCm   Mrv   Quad::QuadRule   
DFI   Lik_Classical   MyException   
  r  
+
DFIInner   Lik_Full   
  o  
+
RBFreg   
Object   
+
a | c | d | g | k | l | m | o | p | q | r | x
+
+ + + + diff --git a/doc/doxygen/html/closed.png b/doc/doxygen/html/closed.png new file mode 100644 index 00000000..98cc2c90 Binary files /dev/null and b/doc/doxygen/html/closed.png differ diff --git a/doc/doxygen/html/combin_8cpp.html b/doc/doxygen/html/combin_8cpp.html new file mode 100644 index 00000000..26e6c445 --- /dev/null +++ b/doc/doxygen/html/combin_8cpp.html @@ -0,0 +1,566 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: combin.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
combin.cpp File Reference
+
+
+ +

Tools to evaluate combinatorial quantities. +More...

+
#include "Array1D.h"
+#include "Array2D.h"
+#include "gen_defs.h"
+#include "probability.h"
+#include "combin.h"
+#include <math.h>
+#include <float.h>
+#include "error_handlers.h"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

int choose (int n, int k)
 Calculates binomial coefficient C(n,k): n-choose-k. More...
 
int factorial (int number)
 Calculates the factorial of a number. More...
 
double logfactorial (int number)
 Calculates the logfactorial of a number. More...
 
void chooseComb (int n, int k, Array2D< int > &fullInd)
 Computes all possible k-combinations of the first n non-negative integers and returns them in fullInd. More...
 
void get_perm (Array1D< int > &perm, int seed)
 Computes a random permutation of the first n non-negative integers and returns is in perm. More...
 
void get_perm (int nn, int *perm, int seed)
 Computes a random permutation of the first n non-negative integers and returns is in perm. More...
 
double gammai (const double p, const double x)
 Compute the incomplete Gamma function with parameter a at point x. More...
 
double beta (const double z, const double w)
 Compute the Beta function at the point pair (z,w) More...
 
double betai (const double p, const double q, const double x)
 Compute the incomplete Beta function with parameters a and b at point x. More...
 
double digama (double x)
 Computes the digamma, or psi, function, i.e. derivative of the logarithm of gamma function. More...
 
void clust (Array2D< double > &data_in, Array1D< double > &w, int ncl, Array1D< int > &numData, int *pClusterIndex)
 K-center clustering of data. More...
 
double clust_best (Array2D< double > &data_in, Array1D< double > &w, int ncl, Array1D< int > &bestnumData, int *bestClusterIndex, int ntry)
 Multiple trials of K-center clustering and picking the best one according to explained variance criterion. More...
 
int findNumCl (Array2D< double > &data_in, Array1D< double > &w, int ntry)
 Find the best number of clusters in a dataset according to one of three (hardcoded) criteria. More...
 
+

Detailed Description

+

Tools to evaluate combinatorial quantities.

+

Function Documentation

+ +

◆ beta()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double beta (const double z,
const double w 
)
+
+ +

Compute the Beta function at the point pair (z,w)

+ +
+
+ +

◆ betai()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double betai (const double p,
const double q,
const double x 
)
+
+ +

Compute the incomplete Beta function with parameters a and b at point x.

+
Note
This is a slightly modified version of a code distributed by John Burkardt
+
+see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa063/asa063.html
+
+see comments under the function file
+ +
+
+ +

◆ choose()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int choose (int n,
int k 
)
+
+ +

Calculates binomial coefficient C(n,k): n-choose-k.

+ +
+
+ +

◆ chooseComb()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void chooseComb (int n,
int k,
Array2D< int > & fullInd 
)
+
+ +

Computes all possible k-combinations of the first n non-negative integers and returns them in fullInd.

+ +
+
+ +

◆ clust()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void clust (Array2D< double > & data_in,
Array1D< double > & w,
int ncl,
Array1D< int > & numData,
int * pClusterIndex 
)
+
+ +

K-center clustering of data.

+
Parameters
+ + + + + + +
[in]data_in: Nxd matrix of data
[in]w: Array of size d; dimension-wise scaling weights
[in]ncl: Number of clusters
[out]numData: Array of size ncl; stores the number of elements for each cluster
[out]pClusterIndex: Array of size N indicating the cluster index for each data point
+
+
+ +
+
+ +

◆ clust_best()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
double clust_best (Array2D< double > & data_in,
Array1D< double > & w,
int ncl,
Array1D< int > & bestnumData,
int * bestClusterIndex,
int ntry 
)
+
+ +

Multiple trials of K-center clustering and picking the best one according to explained variance criterion.

+ +
+
+ +

◆ digama()

+ +
+
+ + + + + + + + +
double digama (double x)
+
+ +

Computes the digamma, or psi, function, i.e. derivative of the logarithm of gamma function.

+
Note
This is a slightly modified version of a code distributed by John Burkardt
+
+see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa103/asa103.cpp
+ +
+
+ +

◆ factorial()

+ +
+
+ + + + + + + + +
int factorial (int number)
+
+ +

Calculates the factorial of a number.

+ +
+
+ +

◆ findNumCl()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int findNumCl (Array2D< double > & data_in,
Array1D< double > & w,
int ntry 
)
+
+ +

Find the best number of clusters in a dataset according to one of three (hardcoded) criteria.

+ +
+
+ +

◆ gammai()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double gammai (const double a,
const double x 
)
+
+ +

Compute the incomplete Gamma function with parameter a at point x.

+
Note
This is a slightly modified version of a code distributed by John Burkardt
+
+see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa147/asa147.html
+
+see comments under the function definition
+ +
+
+ +

◆ get_perm() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void get_perm (Array1D< int > & perm,
int seed 
)
+
+ +

Computes a random permutation of the first n non-negative integers and returns is in perm.

+
Note
n is the size of the array argument perm
+ +
+
+ +

◆ get_perm() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void get_perm (int nn,
int * perm,
int seed 
)
+
+ +

Computes a random permutation of the first n non-negative integers and returns is in perm.

+ +
+
+ +

◆ logfactorial()

+ +
+
+ + + + + + + + +
double logfactorial (int number)
+
+ +

Calculates the logfactorial of a number.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/combin_8h.html b/doc/doxygen/html/combin_8h.html new file mode 100644 index 00000000..cc1dbace --- /dev/null +++ b/doc/doxygen/html/combin_8h.html @@ -0,0 +1,562 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: combin.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
combin.h File Reference
+
+
+ +

Header for combinatorial tools. +More...

+
#include "Array2D.h"
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

int choose (int n, int k)
 Calculates binomial coefficient C(n,k): n-choose-k. More...
 
int factorial (int number)
 Calculates the factorial of a number. More...
 
double logfactorial (int number)
 Calculates the logfactorial of a number. More...
 
void chooseComb (int n, int k, Array2D< int > &fullInd)
 Computes all possible k-combinations of the first n non-negative integers and returns them in fullInd. More...
 
void get_perm (int n, int *perm, int seed)
 Computes a random permutation of the first n non-negative integers and returns is in perm. More...
 
void get_perm (Array1D< int > &perm, int seed)
 Computes a random permutation of the first n non-negative integers and returns is in perm. More...
 
double gammai (const double a, const double x)
 Compute the incomplete Gamma function with parameter a at point x. More...
 
double beta (const double z, const double w)
 Compute the Beta function at the point pair (z,w) More...
 
double betai (const double p, const double q, const double x)
 Compute the incomplete Beta function with parameters a and b at point x. More...
 
double digama (double x)
 Computes the digamma, or psi, function, i.e. derivative of the logarithm of gamma function. More...
 
void clust (Array2D< double > &data_in, Array1D< double > &w, int ncl, Array1D< int > &numData, int *pClusterIndex)
 K-center clustering of data. More...
 
double clust_best (Array2D< double > &data_in, Array1D< double > &w, int ncl, Array1D< int > &bestnumData, int *bestClusterIndex, int ntry)
 Multiple trials of K-center clustering and picking the best one according to explained variance criterion. More...
 
int findNumCl (Array2D< double > &data_in, Array1D< double > &w, int ntry)
 Find the best number of clusters in a dataset according to one of three (hardcoded) criteria. More...
 
+

Detailed Description

+

Header for combinatorial tools.

+
Note
Some functions are likely not optimal and could have been computed more efficiently.
+

Function Documentation

+ +

◆ beta()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double beta (const double z,
const double w 
)
+
+ +

Compute the Beta function at the point pair (z,w)

+ +
+
+ +

◆ betai()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double betai (const double p,
const double q,
const double x 
)
+
+ +

Compute the incomplete Beta function with parameters a and b at point x.

+
Note
This is a slightly modified version of a code distributed by John Burkardt
+
+see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa063/asa063.html
+
+see comments under the function file
+ +
+
+ +

◆ choose()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int choose (int n,
int k 
)
+
+ +

Calculates binomial coefficient C(n,k): n-choose-k.

+ +
+
+ +

◆ chooseComb()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void chooseComb (int n,
int k,
Array2D< int > & fullInd 
)
+
+ +

Computes all possible k-combinations of the first n non-negative integers and returns them in fullInd.

+ +
+
+ +

◆ clust()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void clust (Array2D< double > & data_in,
Array1D< double > & w,
int ncl,
Array1D< int > & numData,
int * pClusterIndex 
)
+
+ +

K-center clustering of data.

+
Parameters
+ + + + + + +
[in]data_in: Nxd matrix of data
[in]w: Array of size d; dimension-wise scaling weights
[in]ncl: Number of clusters
[out]numData: Array of size ncl; stores the number of elements for each cluster
[out]pClusterIndex: Array of size N indicating the cluster index for each data point
+
+
+ +
+
+ +

◆ clust_best()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
double clust_best (Array2D< double > & data_in,
Array1D< double > & w,
int ncl,
Array1D< int > & bestnumData,
int * bestClusterIndex,
int ntry 
)
+
+ +

Multiple trials of K-center clustering and picking the best one according to explained variance criterion.

+ +
+
+ +

◆ digama()

+ +
+
+ + + + + + + + +
double digama (double x)
+
+ +

Computes the digamma, or psi, function, i.e. derivative of the logarithm of gamma function.

+
Note
This is a slightly modified version of a code distributed by John Burkardt
+
+see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa103/asa103.cpp
+ +
+
+ +

◆ factorial()

+ +
+
+ + + + + + + + +
int factorial (int number)
+
+ +

Calculates the factorial of a number.

+ +
+
+ +

◆ findNumCl()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int findNumCl (Array2D< double > & data_in,
Array1D< double > & w,
int ntry 
)
+
+ +

Find the best number of clusters in a dataset according to one of three (hardcoded) criteria.

+ +
+
+ +

◆ gammai()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double gammai (const double a,
const double x 
)
+
+ +

Compute the incomplete Gamma function with parameter a at point x.

+
Note
This is a slightly modified version of a code distributed by John Burkardt
+
+see http://people.sc.fsu.edu/~jburkardt/cpp_src/asa147/asa147.html
+
+see comments under the function definition
+ +
+
+ +

◆ get_perm() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void get_perm (int n,
int * perm,
int seed 
)
+
+ +

Computes a random permutation of the first n non-negative integers and returns is in perm.

+ +
+
+ +

◆ get_perm() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + +
void get_perm (Array1D< int > & perm,
int seed 
)
+
+ +

Computes a random permutation of the first n non-negative integers and returns is in perm.

+
Note
n is the size of the array argument perm
+ +
+
+ +

◆ logfactorial()

+ +
+
+ + + + + + + + +
double logfactorial (int number)
+
+ +

Calculates the logfactorial of a number.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/combin_8h_source.html b/doc/doxygen/html/combin_8h_source.html new file mode 100644 index 00000000..a582e92c --- /dev/null +++ b/doc/doxygen/html/combin_8h_source.html @@ -0,0 +1,73 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: combin.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
combin.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
30 
31 #ifndef COMBIN_H
32 #define COMBIN_H
33 
34 #include "Array2D.h"
35 
36 
37 
39 int choose(int n,int k);
40 
42 int factorial(int number);
43 
45 double logfactorial(int number);
46 
49 void chooseComb(int n, int k,Array2D<int>& fullInd);
50 
51 
54 void get_perm(int n, int* perm,int seed);
55 
59 void get_perm(Array1D<int>& perm, int seed);
60 
61 
66 double gammai(const double a, const double x);
67 
69 double beta(const double z, const double w);
70 
75 double betai(const double p, const double q, const double x);
76 
80 double digama ( double x );
81 
88 void clust(Array2D<double>& data_in, Array1D<double>& w,int ncl, Array1D<int>& numData,int *pClusterIndex);
89 
91 double clust_best(Array2D<double>& data_in, Array1D<double>& w,int ncl, Array1D<int>& bestnumData,int *bestClusterIndex,int ntry);
93 int findNumCl(Array2D<double>& data_in,Array1D<double>& w,int ntry);
94 //---------------------------------------------------------------------------------------
95 #endif // COMBIN_H
double betai(const double p, const double q, const double x)
Compute the incomplete Beta function with parameters a and b at point x.
Definition: combin.cpp:268
+
void clust(Array2D< double > &data_in, Array1D< double > &w, int ncl, Array1D< int > &numData, int *pClusterIndex)
K-center clustering of data.
Definition: combin.cpp:538
+
int findNumCl(Array2D< double > &data_in, Array1D< double > &w, int ntry)
Find the best number of clusters in a dataset according to one of three (hardcoded) criteria...
Definition: combin.cpp:623
+
void get_perm(int n, int *perm, int seed)
Computes a random permutation of the first n non-negative integers and returns is in perm...
Definition: combin.cpp:122
+
Definition: Array1D.h:471
+
void chooseComb(int n, int k, Array2D< int > &fullInd)
Computes all possible k-combinations of the first n non-negative integers and returns them in fullInd...
Definition: combin.cpp:79
+ +
int factorial(int number)
Calculates the factorial of a number.
Definition: combin.cpp:58
+
2D Array class for any type T
+
double digama(double x)
Computes the digamma, or psi, function, i.e. derivative of the logarithm of gamma function...
Definition: combin.cpp:442
+
double beta(const double z, const double w)
Compute the Beta function at the point pair (z,w)
Definition: combin.cpp:260
+
Definition: Array1D.h:261
+
double clust_best(Array2D< double > &data_in, Array1D< double > &w, int ncl, Array1D< int > &bestnumData, int *bestClusterIndex, int ntry)
Multiple trials of K-center clustering and picking the best one according to explained variance crite...
Definition: combin.cpp:567
+
double gammai(const double a, const double x)
Compute the incomplete Gamma function with parameter a at point x.
Definition: combin.cpp:144
+
double logfactorial(int number)
Calculates the logfactorial of a number.
Definition: combin.cpp:68
+
int choose(int n, int k)
Calculates binomial coefficient C(n,k): n-choose-k.
Definition: combin.cpp:40
+
+ + + + diff --git a/doc/doxygen/html/dfi_8cpp.html b/doc/doxygen/html/dfi_8cpp.html new file mode 100644 index 00000000..40acb8bf --- /dev/null +++ b/doc/doxygen/html/dfi_8cpp.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: dfi.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
dfi.cpp File Reference
+
+
+
#include <iostream>
+#include <math.h>
+#include "error_handlers.h"
+#include "Array1D.h"
+#include "Array2D.h"
+#include "quad.h"
+#include "tools.h"
+#include "arraytools.h"
+#include "mcmc.h"
+#include "gen_defs.h"
+#include "lbfgs_routines.h"
+#include "deplapack.h"
+#include "depblas.h"
+#include "dfi.h"
+
+ + + + diff --git a/doc/doxygen/html/dfi_8h.html b/doc/doxygen/html/dfi_8h.html new file mode 100644 index 00000000..1ad73cfa --- /dev/null +++ b/doc/doxygen/html/dfi_8h.html @@ -0,0 +1,73 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: dfi.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
dfi.h File Reference
+
+
+
#include "dsfmt_add.h"
+#include "mcmc.h"
+
+

Go to the source code of this file.

+ + + + + + + + +

+Classes

class  DFISetupBase
 
class  DFIInner
 
class  DFI
 
+
+ + + + diff --git a/doc/doxygen/html/dfi_8h_source.html b/doc/doxygen/html/dfi_8h_source.html new file mode 100644 index 00000000..23adac3d --- /dev/null +++ b/doc/doxygen/html/dfi_8h_source.html @@ -0,0 +1,87 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: dfi.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
dfi.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (2013) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 #ifndef UQTKDFI_H_SEEN
28 #define UQTKDFI_H_SEEN
29 
30 
31 #include "dsfmt_add.h"
32 #include "mcmc.h"
33 
35 public:
36 
38  virtual double S(Array1D<MCMC::chainstate> inner_samples){};
39 };
40 
41 class DFIInner: public LikelihoodBase{
42 public:
44  DFIInner(){};
45  ~DFIInner(){};
46 
47  // params for running the inner chain
48  int ndim, nBurn, nCalls; // dim of inner chain
49  Array1D<double> beta0_; // initial start
50  Array1D<double> gammas_; // initial proposal covariance
51  Array1D<MCMC::chainstate> samples_; // holds beta samples from inner chain
52 
53  DFISetupBase* d_; // class which holds logposterior
54  Array1D<double> z_; // internal z data (change in outer loop)
55  Array1D<double> sigma_; // internal sigma (change in outer loop)
56 
57  // variables for holding mean and variance
61 
62  double eval(Array1D<double>&); // evaluate logposterior
63  void getSamples(); // get Array1D of samples
64 
65  // params for summary statistics
68  double delta1, delta2;
69  double S(); // comparison of summary statistics
70 
71 };
72 
73 class DFI: public LikelihoodBase{
74 public:
75  int zdim;
76  int sdim;
77  int nBeta;
78 
80  int nCalls;
81 
82  DFI(DFIInner&);
83  ~DFI(){};
84 
85  // params for eval function
86  Array1D<double> z_;
88 
89  double eval(Array1D<double>&);
90  void runChain(int nCalls, Array1D<double> gammas, Array1D<double> start, int seed, int node);
91 
92  void getMLE(Array1D<double>& xstart);
93 };
94 
95 #endif /* UQTKDFI_H_SEEN */
+
~DFI()
Definition: dfi.h:83
+
Definition: mcmc.h:45
+
Array1D< double > quants
Definition: dfi.h:60
+
Array1D< double > means0
Definition: dfi.h:66
+
Array1D< double > sigma_
Definition: dfi.h:87
+
int nBeta
Definition: dfi.h:77
+
Array1D< double > stds_
Definition: dfi.h:59
+
DFIInner * dfi_inner_
Definition: dfi.h:79
+
Array1D< double > sigma_
Definition: dfi.h:55
+
double delta2
Definition: dfi.h:68
+
virtual double S(Array1D< MCMC::chainstate > inner_samples)
Definition: dfi.h:38
+
Definition: Array1D.h:471
+
int sdim
Definition: dfi.h:76
+
Array1D< double > means_
Definition: dfi.h:58
+
virtual double f(Array1D< double > &, Array1D< double > &, Array1D< double > &)
Definition: dfi.h:37
+
Definition: dfi.h:34
+
Array1D< double > beta0_
Definition: dfi.h:49
+
Array1D< double > z_
Definition: dfi.h:54
+
~DFIInner()
Definition: dfi.h:45
+
int zdim
Definition: dfi.h:75
+
DFISetupBase * d_
Definition: dfi.h:53
+
Definition: dfi.h:73
+
Array1D< double > stds0
Definition: dfi.h:67
+
Array1D< MCMC::chainstate > samples_
Definition: dfi.h:51
+
Array1D< double > gammas_
Definition: dfi.h:50
+
Definition: dfi.h:41
+
Header file for the Markov chain Monte Carlo class.
+
DFIInner()
Definition: dfi.h:44
+
int nCalls
Definition: dfi.h:80
+
+ + + + diff --git a/doc/doxygen/html/dfi__test_8cpp.html b/doc/doxygen/html/dfi__test_8cpp.html new file mode 100644 index 00000000..5ed815fb --- /dev/null +++ b/doc/doxygen/html/dfi__test_8cpp.html @@ -0,0 +1,150 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: dfi_test.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
dfi_test.cpp File Reference
+
+
+
#include <iostream>
+#include "math.h"
+#include "Array1D.h"
+#include "Array2D.h"
+#include "mcmc.h"
+#include "quad.h"
+#include "dfi.h"
+#include "dsfmt_add.h"
+
+ + + +

+Classes

class  DFISetup
 
+ + + + + +

+Functions

void setup_data (Array1D< double > &beta0, Array1D< double > &z0, Array1D< double > &sigma0, Array1D< double > &zs0)
 
int main (int argc, char **argv)
 
+

Function Documentation

+ +

◆ main()

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

◆ setup_data()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void setup_data (Array1D< double > & beta0,
Array1D< double > & z0,
Array1D< double > & sigma0,
Array1D< double > & zs0 
)
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/dir_006721c806d6821325371dd377832d8c.html b/doc/doxygen/html/dir_006721c806d6821325371dd377832d8c.html new file mode 100644 index 00000000..0c4edd42 --- /dev/null +++ b/doc/doxygen/html/dir_006721c806d6821325371dd377832d8c.html @@ -0,0 +1,66 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: mcmc Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
mcmc Directory Reference
+
+
+ + + + + + + +

+Files

file  mcmc.cpp
 
file  mcmc.h [code]
 Header file for the Markov chain Monte Carlo class.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_06694bf5fd41ba74684056be78273ad2.html b/doc/doxygen/html/dir_06694bf5fd41ba74684056be78273ad2.html new file mode 100644 index 00000000..9114499c --- /dev/null +++ b/doc/doxygen/html/dir_06694bf5fd41ba74684056be78273ad2.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: lreg Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
lreg Directory Reference
+
+
+ + + + + + + + +

+Files

file  lreg.cpp
 Linear regression class.
 
file  lreg.h [code]
 Header file for the linear regression class A great deal of notations and computations follow [1].
 
+
+ + + + diff --git a/doc/doxygen/html/dir_093fd1291c916f9be3adb1135a493bae.html b/doc/doxygen/html/dir_093fd1291c916f9be3adb1135a493bae.html new file mode 100644 index 00000000..2297b231 --- /dev/null +++ b/doc/doxygen/html/dir_093fd1291c916f9be3adb1135a493bae.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gproc Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gproc Directory Reference
+
+
+ + + + + + + + +

+Files

file  gproc.cpp
 Gaussian Process class.
 
file  gproc.h [code]
 Header file for Gaussian Process class.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_128519fc8b37a5a067b4c5f6cc8f4c49.html b/doc/doxygen/html/dir_128519fc8b37a5a067b4c5f6cc8f4c49.html new file mode 100644 index 00000000..28955cd1 --- /dev/null +++ b/doc/doxygen/html/dir_128519fc8b37a5a067b4c5f6cc8f4c49.html @@ -0,0 +1,82 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: array Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
array Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  Array1D.h [code]
 1D Array class for any type T
 
file  Array2D.h [code]
 2D Array class for any type T
 
file  Array3D.h [code]
 3D Array class for any type T
 
file  arrayio.cpp
 Read/write capabilities from/to matrix or vector form arrays/files.
 
file  arrayio.h [code]
 Header file for array read/write utilities.
 
file  arraytools.cpp
 Tools to manipulate Array 1D and 2D objects. Some tools mimick MATLAB functionalities.
 
file  arraytools.h [code]
 Header file for array tools.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_16a870b7d07bdaacfd3f0908a78f5e9d.html b/doc/doxygen/html/dir_16a870b7d07bdaacfd3f0908a78f5e9d.html new file mode 100644 index 00000000..4d7099e1 --- /dev/null +++ b/doc/doxygen/html/dir_16a870b7d07bdaacfd3f0908a78f5e9d.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: bcs Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
bcs Directory Reference
+
+
+ + + + + + + + +

+Files

file  bcs.cpp
 Implemenations of Bayesian compressive sensing algorithm.
 
file  bcs.h [code]
 Header for the implemenations of Bayesian compressive sensing algorithm.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_19007e3130b5965ca6c49213286cf7eb.html b/doc/doxygen/html/dir_19007e3130b5965ca6c49213286cf7eb.html new file mode 100644 index 00000000..91a1c674 --- /dev/null +++ b/doc/doxygen/html/dir_19007e3130b5965ca6c49213286cf7eb.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: pdf_cl Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
pdf_cl Directory Reference
+
+
+ + + + + +

+Files

file  pdf_cl.cpp
 Command-line utility for KDE given samples.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_1eb400768e3494ee2ca629243c22fbce.html b/doc/doxygen/html/dir_1eb400768e3494ee2ca629243c22fbce.html new file mode 100644 index 00000000..50e5e012 --- /dev/null +++ b/doc/doxygen/html/dir_1eb400768e3494ee2ca629243c22fbce.html @@ -0,0 +1,79 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: infer Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
infer Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + +

+Files

file  inference.cpp
 Model inference tools.
 
file  inference.h [code]
 Header for the model inference tools.
 
file  mrv.cpp
 Multivariate random variable class.
 
file  mrv.h [code]
 Header for multivariate random variable class.
 
file  post.cpp
 Posterior computation class.
 
file  post.h [code]
 Header for the posterior computation class.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_20f2680a3977f3851122b2d6066a454e.html b/doc/doxygen/html/dir_20f2680a3977f3851122b2d6066a454e.html new file mode 100644 index 00000000..37a6ed6d --- /dev/null +++ b/doc/doxygen/html/dir_20f2680a3977f3851122b2d6066a454e.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gp_regr Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gp_regr Directory Reference
+
+
+ + + + + +

+Files

file  gp_regr.cpp
 Command-line utility for Gaussian Process regression.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_28e3df397f43e8f1af7e6c2b7d87b0e6.html b/doc/doxygen/html/dir_28e3df397f43e8f1af7e6c2b7d87b0e6.html new file mode 100644 index 00000000..6dcf1ba3 --- /dev/null +++ b/doc/doxygen/html/dir_28e3df397f43e8f1af7e6c2b7d87b0e6.html @@ -0,0 +1,112 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: tools Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
tools Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  combin.cpp
 Tools to evaluate combinatorial quantities.
 
file  combin.h [code]
 Header for combinatorial tools.
 
file  func.cpp
 Implements several functions of form $y=f(\lambda;x)$.
 
file  func.h [code]
 Header for implementation of functions of form $y=f(\lambda;x)$.
 
file  gq.cpp
 Utilities to generate quadrature rules.
 
file  gq.h [code]
 Header for quadrature generation utilities.
 
file  minmax.cpp
 Tools to find min/max values of arrays.
 
file  minmax.h [code]
 Header for min/max tools.
 
file  multiindex.cpp
 Tools that deal with integer multiindices.
 
file  multiindex.h [code]
 Header for tools that deal with integer multiindices.
 
file  pcmaps.cpp
 Suite of functions to help map one kind of a PC variable to another.
 
file  pcmaps.h [code]
 Header for suite of functions to help map one kind of a PC variable to another.
 
file  probability.cpp
 Probability and random number generation- related tools.
 
file  probability.h [code]
 Header for probability and random number generation- related tools.
 
file  rosenblatt.cpp
 Tools related to Rosenblatt transformation.
 
file  rosenblatt.h [code]
 Header for tools related to Rosenblatt transformation.
 
file  tools.h [code]
 A header function that includes all tools.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_40ca0f9b78da4ccbb14e5a28ee282e45.html b/doc/doxygen/html/dir_40ca0f9b78da4ccbb14e5a28ee282e45.html new file mode 100644 index 00000000..d6aac322 --- /dev/null +++ b/doc/doxygen/html/dir_40ca0f9b78da4ccbb14e5a28ee282e45.html @@ -0,0 +1,73 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: pce Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
pce Directory Reference
+
+
+ + + + + + + + + + + + + + +

+Files

file  PCBasis.cpp
 Univariate PC class.
 
file  PCBasis.h [code]
 Header file for the univariate PC class.
 
file  PCSet.cpp
 Multivariate PC class.
 
file  PCSet.h [code]
 Header file for the Multivariate PC class.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_4532e4717bdbef31626f1f4eec1ad1de.html b/doc/doxygen/html/dir_4532e4717bdbef31626f1f4eec1ad1de.html new file mode 100644 index 00000000..b7c651ac --- /dev/null +++ b/doc/doxygen/html/dir_4532e4717bdbef31626f1f4eec1ad1de.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gkpSparse Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gkpSparse Directory Reference
+
+
+ + + + + + + + +

+Files

file  gkpclib.cpp
 
file  gkplib.h [code]
 
file  gkpSparse.cpp
 
+
+ + + + diff --git a/doc/doxygen/html/dir_5c4c5ed82fd393e0105f6bcdb5914010.html b/doc/doxygen/html/dir_5c4c5ed82fd393e0105f6bcdb5914010.html new file mode 100644 index 00000000..5cedc99a --- /dev/null +++ b/doc/doxygen/html/dir_5c4c5ed82fd393e0105f6bcdb5914010.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: regression Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
regression Directory Reference
+
+
+ + + + + +

+Files

file  regression.cpp
 Command-line utility for linear regression.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_7a58a101592a95cebbfd07e6a75340e1.html b/doc/doxygen/html/dir_7a58a101592a95cebbfd07e6a75340e1.html new file mode 100644 index 00000000..314b9b34 --- /dev/null +++ b/doc/doxygen/html/dir_7a58a101592a95cebbfd07e6a75340e1.html @@ -0,0 +1,85 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: lib Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
lib Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+Directories

directory  array
 
directory  bcs
 
directory  dfi
 
directory  gproc
 
directory  infer
 
directory  kle
 
directory  lreg
 
directory  mcmc
 
directory  pce
 
directory  quad
 
directory  tools
 
directory  xmlutils
 
+
+ + + + diff --git a/doc/doxygen/html/dir_7b5ab9ffb3898dc1cc468814aa6ead1a.html b/doc/doxygen/html/dir_7b5ab9ffb3898dc1cc468814aa6ead1a.html new file mode 100644 index 00000000..a6cca6e1 --- /dev/null +++ b/doc/doxygen/html/dir_7b5ab9ffb3898dc1cc468814aa6ead1a.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: dfi Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
dfi Directory Reference
+
+
+ + + + + + +

+Files

file  dfi.cpp
 
file  dfi.h [code]
 
+
+ + + + diff --git a/doc/doxygen/html/dir_7e9b6b5d4305474956bab61a81ab07f7.html b/doc/doxygen/html/dir_7e9b6b5d4305474956bab61a81ab07f7.html new file mode 100644 index 00000000..7104b1b0 --- /dev/null +++ b/doc/doxygen/html/dir_7e9b6b5d4305474956bab61a81ab07f7.html @@ -0,0 +1,87 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: xmlutils Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
xmlutils Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

file  MyException.h [code]
 
file  Object.h [code]
 
file  RefPtr.h [code]
 
file  XMLAttributeList.cpp
 
file  XMLAttributeList.h [code]
 
file  XMLElement.cpp
 
file  XMLElement.h [code]
 
file  XMLExpatParser.cpp
 
file  XMLExpatParser.h [code]
 
file  XMLParser.cpp
 
file  XMLParser.h [code]
 
file  XMLUtils.cpp
 
file  XMLUtils.h [code]
 
+
+ + + + diff --git a/doc/doxygen/html/dir_8dadda8c97c669c14bc759cc9927688a.html b/doc/doxygen/html/dir_8dadda8c97c669c14bc759cc9927688a.html new file mode 100644 index 00000000..45077142 --- /dev/null +++ b/doc/doxygen/html/dir_8dadda8c97c669c14bc759cc9927688a.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: quad Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
quad Directory Reference
+
+
+ + + + + + + + +

+Files

file  quad.cpp
 Quadrature class.
 
file  quad.h [code]
 Header file for the quadrature class.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_93836573b90394f9b606bea0a1f27892.html b/doc/doxygen/html/dir_93836573b90394f9b606bea0a1f27892.html new file mode 100644 index 00000000..33243d74 --- /dev/null +++ b/doc/doxygen/html/dir_93836573b90394f9b606bea0a1f27892.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gen_mi Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gen_mi Directory Reference
+
+
+ + + + + +

+Files

file  gen_mi.cpp
 Command-line utility to generate multiindex.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_97f84c1072eb90142eaac1b180b6d7c5.html b/doc/doxygen/html/dir_97f84c1072eb90142eaac1b180b6d7c5.html new file mode 100644 index 00000000..2731bebf --- /dev/null +++ b/doc/doxygen/html/dir_97f84c1072eb90142eaac1b180b6d7c5.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: pce_quad Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
pce_quad Directory Reference
+
+
+ + + + + +

+Files

file  pce_quad.cpp
 Command-line utility for PC construction given samples.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_9edb83e4ed44c497265383775a8507cd.html b/doc/doxygen/html/dir_9edb83e4ed44c497265383775a8507cd.html new file mode 100644 index 00000000..6341fd98 --- /dev/null +++ b/doc/doxygen/html/dir_9edb83e4ed44c497265383775a8507cd.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: generate_quad Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
generate_quad Directory Reference
+
+
+ + + + + +

+Files

file  generate_quad.cpp
 Command-line utility to generate quadrature points.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_9faeda79623e471167af325f01dc9fc9.html b/doc/doxygen/html/dir_9faeda79623e471167af325f01dc9fc9.html new file mode 100644 index 00000000..09628b62 --- /dev/null +++ b/doc/doxygen/html/dir_9faeda79623e471167af325f01dc9fc9.html @@ -0,0 +1,87 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: app Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
app Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Directories

directory  dfi_test
 
directory  gen_mi
 
directory  generate_quad
 
directory  gkpSparse
 
directory  gp_regr
 
directory  model_inf
 
directory  pce_eval
 
directory  pce_quad
 
directory  pce_rv
 
directory  pce_sens
 
directory  pdf_cl
 
directory  regression
 
directory  sens
 
+
+ + + + diff --git a/doc/doxygen/html/dir_a3750b93c2443f2a35afa7a30a5b3dee.html b/doc/doxygen/html/dir_a3750b93c2443f2a35afa7a30a5b3dee.html new file mode 100644 index 00000000..b1b254ad --- /dev/null +++ b/doc/doxygen/html/dir_a3750b93c2443f2a35afa7a30a5b3dee.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: pce_sens Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
pce_sens Directory Reference
+
+
+ + + + + +

+Files

file  pce_sens.cpp
 Command-line utility for Sobol sensitivity index computation given PC.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_b5a0728fb7018a88df0fa60e862f7cd4.html b/doc/doxygen/html/dir_b5a0728fb7018a88df0fa60e862f7cd4.html new file mode 100644 index 00000000..b4392734 --- /dev/null +++ b/doc/doxygen/html/dir_b5a0728fb7018a88df0fa60e862f7cd4.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: model_inf Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
model_inf Directory Reference
+
+
+ + + + + +

+Files

file  model_inf.cpp
 Command-line utility for model parameter inference.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_b915a5b945a42a3919ddfe29e13bcb81.html b/doc/doxygen/html/dir_b915a5b945a42a3919ddfe29e13bcb81.html new file mode 100644 index 00000000..d0cefb94 --- /dev/null +++ b/doc/doxygen/html/dir_b915a5b945a42a3919ddfe29e13bcb81.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: pce_eval Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
pce_eval Directory Reference
+
+
+ + + + + +

+Files

file  pce_eval.cpp
 Command-line utility for PC-related evaluations.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_dc842bf419791690b2dfdb2fe51d5bc8.html b/doc/doxygen/html/dir_dc842bf419791690b2dfdb2fe51d5bc8.html new file mode 100644 index 00000000..3006c45c --- /dev/null +++ b/doc/doxygen/html/dir_dc842bf419791690b2dfdb2fe51d5bc8.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: kle Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
kle Directory Reference
+
+
+ + + + + + +

+Files

file  kle.cpp
 
file  kle.h [code]
 
+
+ + + + diff --git a/doc/doxygen/html/dir_df511e5bd85cec96854b39d5e1c27aa8.html b/doc/doxygen/html/dir_df511e5bd85cec96854b39d5e1c27aa8.html new file mode 100644 index 00000000..24cd9eaa --- /dev/null +++ b/doc/doxygen/html/dir_df511e5bd85cec96854b39d5e1c27aa8.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: cpp Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
cpp Directory Reference
+
+
+ + + + + + +

+Directories

directory  app
 
directory  lib
 
+
+ + + + diff --git a/doc/doxygen/html/dir_e002628c42d6516cdcbe6e17a7fdfaec.html b/doc/doxygen/html/dir_e002628c42d6516cdcbe6e17a7fdfaec.html new file mode 100644 index 00000000..d749b8cd --- /dev/null +++ b/doc/doxygen/html/dir_e002628c42d6516cdcbe6e17a7fdfaec.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: pce_rv Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
pce_rv Directory Reference
+
+
+ + + + + +

+Files

file  pce_rv.cpp
 Command-line utility for PC-related random variable generation.
 
+
+ + + + diff --git a/doc/doxygen/html/dir_e58731ca8e0565c57e37fcca21aedc0f.html b/doc/doxygen/html/dir_e58731ca8e0565c57e37fcca21aedc0f.html new file mode 100644 index 00000000..273962c9 --- /dev/null +++ b/doc/doxygen/html/dir_e58731ca8e0565c57e37fcca21aedc0f.html @@ -0,0 +1,63 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: dfi_test Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
dfi_test Directory Reference
+
+
+ + + + +

+Files

file  dfi_test.cpp
 
+
+ + + + diff --git a/doc/doxygen/html/dir_fcacb3c2852ebd65abb669ef5bd9c0b5.html b/doc/doxygen/html/dir_fcacb3c2852ebd65abb669ef5bd9c0b5.html new file mode 100644 index 00000000..efaf7c2b --- /dev/null +++ b/doc/doxygen/html/dir_fcacb3c2852ebd65abb669ef5bd9c0b5.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: sens Directory Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
sens Directory Reference
+
+
+ + + + + + +

+Files

file  sens.cpp
 
file  trdSpls.cpp
 
+
+ + + + diff --git a/doc/doxygen/html/doc.png b/doc/doxygen/html/doc.png new file mode 100644 index 00000000..17edabff Binary files /dev/null and b/doc/doxygen/html/doc.png differ diff --git a/doc/doxygen/html/doxygen.css b/doc/doxygen/html/doxygen.css new file mode 100644 index 00000000..4f1ab919 --- /dev/null +++ b/doc/doxygen/html/doxygen.css @@ -0,0 +1,1596 @@ +/* The standard CSS for doxygen 1.8.13 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +p.reference, p.definition { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url('nav_f.png'); + background-repeat: repeat-x; + background-color: #E2E8F2; + line-height: 1.25; + font-weight: 300; + float:left; +} + +.permalink +{ + font-size: 65%; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-color: #DFE5F1; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + +} + +.overload { + font-family: "courier new",courier,monospace; + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +/* +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTableHead tr { +} + +table.markdownTableBodyLeft td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft { + text-align: left +} + +th.markdownTableHeadRight { + text-align: right +} + +th.markdownTableHeadCenter { + text-align: center +} +*/ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + + +/* @end */ diff --git a/doc/doxygen/html/doxygen.png b/doc/doxygen/html/doxygen.png new file mode 100644 index 00000000..3ff17d80 Binary files /dev/null and b/doc/doxygen/html/doxygen.png differ diff --git a/doc/doxygen/html/dynsections.js b/doc/doxygen/html/dynsections.js new file mode 100644 index 00000000..85e18369 --- /dev/null +++ b/doc/doxygen/html/dynsections.js @@ -0,0 +1,97 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} + +function toggleLevel(level) +{ + $('table.directory tr').each(function() { + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + + +UQTk: Uncertainty Quantification Toolkit: File List + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
File List
+
+
+
Here is a list of all files with brief descriptions:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Array1D.h1D Array class for any type T
 Array2D.h2D Array class for any type T
 Array3D.h3D Array class for any type T
 arrayio.cppRead/write capabilities from/to matrix or vector form arrays/files
 arrayio.hHeader file for array read/write utilities
 arraytools.cppTools to manipulate Array 1D and 2D objects. Some tools mimick MATLAB functionalities
 arraytools.hHeader file for array tools
 bcs.cppImplemenations of Bayesian compressive sensing algorithm
 bcs.hHeader for the implemenations of Bayesian compressive sensing algorithm
 combin.cppTools to evaluate combinatorial quantities
 combin.hHeader for combinatorial tools
 dfi.cpp
 dfi.h
 dfi_test.cpp
 func.cppImplements several functions of form $y=f(\lambda;x)$
 func.hHeader for implementation of functions of form $y=f(\lambda;x)$
 gen_mi.cppCommand-line utility to generate multiindex
 generate_quad.cppCommand-line utility to generate quadrature points
 gkpclib.cpp
 gkplib.h
 gkpSparse.cpp
 gp_regr.cppCommand-line utility for Gaussian Process regression
 gproc.cppGaussian Process class
 gproc.hHeader file for Gaussian Process class
 gq.cppUtilities to generate quadrature rules
 gq.hHeader for quadrature generation utilities
 inference.cppModel inference tools
 inference.hHeader for the model inference tools
 kle.cpp
 kle.h
 lreg.cppLinear regression class
 lreg.hHeader file for the linear regression class A great deal of notations and computations follow [1]
 mcmc.cpp
 mcmc.hHeader file for the Markov chain Monte Carlo class
 minmax.cppTools to find min/max values of arrays
 minmax.hHeader for min/max tools
 model_inf.cppCommand-line utility for model parameter inference
 mrv.cppMultivariate random variable class
 mrv.hHeader for multivariate random variable class
 multiindex.cppTools that deal with integer multiindices
 multiindex.hHeader for tools that deal with integer multiindices
 MyException.h
 Object.h
 PCBasis.cppUnivariate PC class
 PCBasis.hHeader file for the univariate PC class
 pce_eval.cppCommand-line utility for PC-related evaluations
 pce_quad.cppCommand-line utility for PC construction given samples
 pce_rv.cppCommand-line utility for PC-related random variable generation
 pce_sens.cppCommand-line utility for Sobol sensitivity index computation given PC
 pcmaps.cppSuite of functions to help map one kind of a PC variable to another
 pcmaps.hHeader for suite of functions to help map one kind of a PC variable to another
 PCSet.cppMultivariate PC class
 PCSet.hHeader file for the Multivariate PC class
 pdf_cl.cppCommand-line utility for KDE given samples
 post.cppPosterior computation class
 post.hHeader for the posterior computation class
 probability.cppProbability and random number generation- related tools
 probability.hHeader for probability and random number generation- related tools
 quad.cppQuadrature class
 quad.hHeader file for the quadrature class
 RefPtr.h
 regression.cppCommand-line utility for linear regression
 rosenblatt.cppTools related to Rosenblatt transformation
 rosenblatt.hHeader for tools related to Rosenblatt transformation
 sens.cpp
 tools.hA header function that includes all tools
 trdSpls.cpp
 XMLAttributeList.cpp
 XMLAttributeList.h
 XMLElement.cpp
 XMLElement.h
 XMLExpatParser.cpp
 XMLExpatParser.h
 XMLParser.cpp
 XMLParser.h
 XMLUtils.cpp
 XMLUtils.h
+
+
+ + + + diff --git a/doc/doxygen/html/folderclosed.png b/doc/doxygen/html/folderclosed.png new file mode 100644 index 00000000..bb8ab35e Binary files /dev/null and b/doc/doxygen/html/folderclosed.png differ diff --git a/doc/doxygen/html/folderopen.png b/doc/doxygen/html/folderopen.png new file mode 100644 index 00000000..d6c7f676 Binary files /dev/null and b/doc/doxygen/html/folderopen.png differ diff --git a/doc/doxygen/html/form_0.png b/doc/doxygen/html/form_0.png new file mode 100644 index 00000000..10eb4c1d Binary files /dev/null and b/doc/doxygen/html/form_0.png differ diff --git a/doc/doxygen/html/form_1.png b/doc/doxygen/html/form_1.png new file mode 100644 index 00000000..e4e5a496 Binary files /dev/null and b/doc/doxygen/html/form_1.png differ diff --git a/doc/doxygen/html/form_10.png b/doc/doxygen/html/form_10.png new file mode 100644 index 00000000..c86f363d Binary files /dev/null and b/doc/doxygen/html/form_10.png differ diff --git a/doc/doxygen/html/form_11.png b/doc/doxygen/html/form_11.png new file mode 100644 index 00000000..cece0970 Binary files /dev/null and b/doc/doxygen/html/form_11.png differ diff --git a/doc/doxygen/html/form_12.png b/doc/doxygen/html/form_12.png new file mode 100644 index 00000000..82156bcf Binary files /dev/null and b/doc/doxygen/html/form_12.png differ diff --git a/doc/doxygen/html/form_13.png b/doc/doxygen/html/form_13.png new file mode 100644 index 00000000..51ebf741 Binary files /dev/null and b/doc/doxygen/html/form_13.png differ diff --git a/doc/doxygen/html/form_14.png b/doc/doxygen/html/form_14.png new file mode 100644 index 00000000..feb967c9 Binary files /dev/null and b/doc/doxygen/html/form_14.png differ diff --git a/doc/doxygen/html/form_15.png b/doc/doxygen/html/form_15.png new file mode 100644 index 00000000..cf209c5d Binary files /dev/null and b/doc/doxygen/html/form_15.png differ diff --git a/doc/doxygen/html/form_16.png b/doc/doxygen/html/form_16.png new file mode 100644 index 00000000..f38be71c Binary files /dev/null and b/doc/doxygen/html/form_16.png differ diff --git a/doc/doxygen/html/form_17.png b/doc/doxygen/html/form_17.png new file mode 100644 index 00000000..5360a0c3 Binary files /dev/null and b/doc/doxygen/html/form_17.png differ diff --git a/doc/doxygen/html/form_18.png b/doc/doxygen/html/form_18.png new file mode 100644 index 00000000..ee6dec7b Binary files /dev/null and b/doc/doxygen/html/form_18.png differ diff --git a/doc/doxygen/html/form_19.png b/doc/doxygen/html/form_19.png new file mode 100644 index 00000000..b82dc56f Binary files /dev/null and b/doc/doxygen/html/form_19.png differ diff --git a/doc/doxygen/html/form_2.png b/doc/doxygen/html/form_2.png new file mode 100644 index 00000000..3e0e5bff Binary files /dev/null and b/doc/doxygen/html/form_2.png differ diff --git a/doc/doxygen/html/form_20.png b/doc/doxygen/html/form_20.png new file mode 100644 index 00000000..7fde8a3b Binary files /dev/null and b/doc/doxygen/html/form_20.png differ diff --git a/doc/doxygen/html/form_21.png b/doc/doxygen/html/form_21.png new file mode 100644 index 00000000..86d142b2 Binary files /dev/null and b/doc/doxygen/html/form_21.png differ diff --git a/doc/doxygen/html/form_22.png b/doc/doxygen/html/form_22.png new file mode 100644 index 00000000..76645cfd Binary files /dev/null and b/doc/doxygen/html/form_22.png differ diff --git a/doc/doxygen/html/form_23.png b/doc/doxygen/html/form_23.png new file mode 100644 index 00000000..94d82ec6 Binary files /dev/null and b/doc/doxygen/html/form_23.png differ diff --git a/doc/doxygen/html/form_24.png b/doc/doxygen/html/form_24.png new file mode 100644 index 00000000..5afed88e Binary files /dev/null and b/doc/doxygen/html/form_24.png differ diff --git a/doc/doxygen/html/form_25.png b/doc/doxygen/html/form_25.png new file mode 100644 index 00000000..437eba33 Binary files /dev/null and b/doc/doxygen/html/form_25.png differ diff --git a/doc/doxygen/html/form_26.png b/doc/doxygen/html/form_26.png new file mode 100644 index 00000000..e5fac0a2 Binary files /dev/null and b/doc/doxygen/html/form_26.png differ diff --git a/doc/doxygen/html/form_27.png b/doc/doxygen/html/form_27.png new file mode 100644 index 00000000..8a976d42 Binary files /dev/null and b/doc/doxygen/html/form_27.png differ diff --git a/doc/doxygen/html/form_28.png b/doc/doxygen/html/form_28.png new file mode 100644 index 00000000..41ac916b Binary files /dev/null and b/doc/doxygen/html/form_28.png differ diff --git a/doc/doxygen/html/form_29.png b/doc/doxygen/html/form_29.png new file mode 100644 index 00000000..339a5f46 Binary files /dev/null and b/doc/doxygen/html/form_29.png differ diff --git a/doc/doxygen/html/form_3.png b/doc/doxygen/html/form_3.png new file mode 100644 index 00000000..5420deeb Binary files /dev/null and b/doc/doxygen/html/form_3.png differ diff --git a/doc/doxygen/html/form_30.png b/doc/doxygen/html/form_30.png new file mode 100644 index 00000000..a2e42668 Binary files /dev/null and b/doc/doxygen/html/form_30.png differ diff --git a/doc/doxygen/html/form_31.png b/doc/doxygen/html/form_31.png new file mode 100644 index 00000000..8d27e840 Binary files /dev/null and b/doc/doxygen/html/form_31.png differ diff --git a/doc/doxygen/html/form_32.png b/doc/doxygen/html/form_32.png new file mode 100644 index 00000000..cce03494 Binary files /dev/null and b/doc/doxygen/html/form_32.png differ diff --git a/doc/doxygen/html/form_33.png b/doc/doxygen/html/form_33.png new file mode 100644 index 00000000..bf306f69 Binary files /dev/null and b/doc/doxygen/html/form_33.png differ diff --git a/doc/doxygen/html/form_34.png b/doc/doxygen/html/form_34.png new file mode 100644 index 00000000..ad640ed0 Binary files /dev/null and b/doc/doxygen/html/form_34.png differ diff --git a/doc/doxygen/html/form_35.png b/doc/doxygen/html/form_35.png new file mode 100644 index 00000000..ab55710b Binary files /dev/null and b/doc/doxygen/html/form_35.png differ diff --git a/doc/doxygen/html/form_36.png b/doc/doxygen/html/form_36.png new file mode 100644 index 00000000..db642547 Binary files /dev/null and b/doc/doxygen/html/form_36.png differ diff --git a/doc/doxygen/html/form_37.png b/doc/doxygen/html/form_37.png new file mode 100644 index 00000000..a296bfac Binary files /dev/null and b/doc/doxygen/html/form_37.png differ diff --git a/doc/doxygen/html/form_38.png b/doc/doxygen/html/form_38.png new file mode 100644 index 00000000..6b0eaba1 Binary files /dev/null and b/doc/doxygen/html/form_38.png differ diff --git a/doc/doxygen/html/form_39.png b/doc/doxygen/html/form_39.png new file mode 100644 index 00000000..037f5203 Binary files /dev/null and b/doc/doxygen/html/form_39.png differ diff --git a/doc/doxygen/html/form_4.png b/doc/doxygen/html/form_4.png new file mode 100644 index 00000000..2c16fcf0 Binary files /dev/null and b/doc/doxygen/html/form_4.png differ diff --git a/doc/doxygen/html/form_40.png b/doc/doxygen/html/form_40.png new file mode 100644 index 00000000..91e459e9 Binary files /dev/null and b/doc/doxygen/html/form_40.png differ diff --git a/doc/doxygen/html/form_41.png b/doc/doxygen/html/form_41.png new file mode 100644 index 00000000..97b4dfbf Binary files /dev/null and b/doc/doxygen/html/form_41.png differ diff --git a/doc/doxygen/html/form_42.png b/doc/doxygen/html/form_42.png new file mode 100644 index 00000000..92e7d792 Binary files /dev/null and b/doc/doxygen/html/form_42.png differ diff --git a/doc/doxygen/html/form_43.png b/doc/doxygen/html/form_43.png new file mode 100644 index 00000000..22f6f8c1 Binary files /dev/null and b/doc/doxygen/html/form_43.png differ diff --git a/doc/doxygen/html/form_44.png b/doc/doxygen/html/form_44.png new file mode 100644 index 00000000..43dcf323 Binary files /dev/null and b/doc/doxygen/html/form_44.png differ diff --git a/doc/doxygen/html/form_45.png b/doc/doxygen/html/form_45.png new file mode 100644 index 00000000..0ee8dfeb Binary files /dev/null and b/doc/doxygen/html/form_45.png differ diff --git a/doc/doxygen/html/form_46.png b/doc/doxygen/html/form_46.png new file mode 100644 index 00000000..ec31adc0 Binary files /dev/null and b/doc/doxygen/html/form_46.png differ diff --git a/doc/doxygen/html/form_47.png b/doc/doxygen/html/form_47.png new file mode 100644 index 00000000..14b23f5b Binary files /dev/null and b/doc/doxygen/html/form_47.png differ diff --git a/doc/doxygen/html/form_48.png b/doc/doxygen/html/form_48.png new file mode 100644 index 00000000..79e11a10 Binary files /dev/null and b/doc/doxygen/html/form_48.png differ diff --git a/doc/doxygen/html/form_49.png b/doc/doxygen/html/form_49.png new file mode 100644 index 00000000..83009927 Binary files /dev/null and b/doc/doxygen/html/form_49.png differ diff --git a/doc/doxygen/html/form_5.png b/doc/doxygen/html/form_5.png new file mode 100644 index 00000000..bcb2cf11 Binary files /dev/null and b/doc/doxygen/html/form_5.png differ diff --git a/doc/doxygen/html/form_50.png b/doc/doxygen/html/form_50.png new file mode 100644 index 00000000..c90bdd06 Binary files /dev/null and b/doc/doxygen/html/form_50.png differ diff --git a/doc/doxygen/html/form_51.png b/doc/doxygen/html/form_51.png new file mode 100644 index 00000000..bebda966 Binary files /dev/null and b/doc/doxygen/html/form_51.png differ diff --git a/doc/doxygen/html/form_52.png b/doc/doxygen/html/form_52.png new file mode 100644 index 00000000..cc3ecbf5 Binary files /dev/null and b/doc/doxygen/html/form_52.png differ diff --git a/doc/doxygen/html/form_53.png b/doc/doxygen/html/form_53.png new file mode 100644 index 00000000..f358b87e Binary files /dev/null and b/doc/doxygen/html/form_53.png differ diff --git a/doc/doxygen/html/form_54.png b/doc/doxygen/html/form_54.png new file mode 100644 index 00000000..dd8c645f Binary files /dev/null and b/doc/doxygen/html/form_54.png differ diff --git a/doc/doxygen/html/form_55.png b/doc/doxygen/html/form_55.png new file mode 100644 index 00000000..acb9021f Binary files /dev/null and b/doc/doxygen/html/form_55.png differ diff --git a/doc/doxygen/html/form_56.png b/doc/doxygen/html/form_56.png new file mode 100644 index 00000000..c9e54c45 Binary files /dev/null and b/doc/doxygen/html/form_56.png differ diff --git a/doc/doxygen/html/form_57.png b/doc/doxygen/html/form_57.png new file mode 100644 index 00000000..4922c349 Binary files /dev/null and b/doc/doxygen/html/form_57.png differ diff --git a/doc/doxygen/html/form_58.png b/doc/doxygen/html/form_58.png new file mode 100644 index 00000000..a3e9e8dd Binary files /dev/null and b/doc/doxygen/html/form_58.png differ diff --git a/doc/doxygen/html/form_59.png b/doc/doxygen/html/form_59.png new file mode 100644 index 00000000..20a360df Binary files /dev/null and b/doc/doxygen/html/form_59.png differ diff --git a/doc/doxygen/html/form_6.png b/doc/doxygen/html/form_6.png new file mode 100644 index 00000000..81dc4f53 Binary files /dev/null and b/doc/doxygen/html/form_6.png differ diff --git a/doc/doxygen/html/form_60.png b/doc/doxygen/html/form_60.png new file mode 100644 index 00000000..4f673021 Binary files /dev/null and b/doc/doxygen/html/form_60.png differ diff --git a/doc/doxygen/html/form_61.png b/doc/doxygen/html/form_61.png new file mode 100644 index 00000000..2fcb0db9 Binary files /dev/null and b/doc/doxygen/html/form_61.png differ diff --git a/doc/doxygen/html/form_62.png b/doc/doxygen/html/form_62.png new file mode 100644 index 00000000..29001251 Binary files /dev/null and b/doc/doxygen/html/form_62.png differ diff --git a/doc/doxygen/html/form_63.png b/doc/doxygen/html/form_63.png new file mode 100644 index 00000000..e3775210 Binary files /dev/null and b/doc/doxygen/html/form_63.png differ diff --git a/doc/doxygen/html/form_64.png b/doc/doxygen/html/form_64.png new file mode 100644 index 00000000..42e62ab6 Binary files /dev/null and b/doc/doxygen/html/form_64.png differ diff --git a/doc/doxygen/html/form_65.png b/doc/doxygen/html/form_65.png new file mode 100644 index 00000000..1b5ce103 Binary files /dev/null and b/doc/doxygen/html/form_65.png differ diff --git a/doc/doxygen/html/form_66.png b/doc/doxygen/html/form_66.png new file mode 100644 index 00000000..2e09c98d Binary files /dev/null and b/doc/doxygen/html/form_66.png differ diff --git a/doc/doxygen/html/form_67.png b/doc/doxygen/html/form_67.png new file mode 100644 index 00000000..f505cf2a Binary files /dev/null and b/doc/doxygen/html/form_67.png differ diff --git a/doc/doxygen/html/form_68.png b/doc/doxygen/html/form_68.png new file mode 100644 index 00000000..4b7241a7 Binary files /dev/null and b/doc/doxygen/html/form_68.png differ diff --git a/doc/doxygen/html/form_69.png b/doc/doxygen/html/form_69.png new file mode 100644 index 00000000..f056ec38 Binary files /dev/null and b/doc/doxygen/html/form_69.png differ diff --git a/doc/doxygen/html/form_7.png b/doc/doxygen/html/form_7.png new file mode 100644 index 00000000..ba2be112 Binary files /dev/null and b/doc/doxygen/html/form_7.png differ diff --git a/doc/doxygen/html/form_70.png b/doc/doxygen/html/form_70.png new file mode 100644 index 00000000..3a1fb3df Binary files /dev/null and b/doc/doxygen/html/form_70.png differ diff --git a/doc/doxygen/html/form_71.png b/doc/doxygen/html/form_71.png new file mode 100644 index 00000000..dc411e6f Binary files /dev/null and b/doc/doxygen/html/form_71.png differ diff --git a/doc/doxygen/html/form_72.png b/doc/doxygen/html/form_72.png new file mode 100644 index 00000000..beb920a0 Binary files /dev/null and b/doc/doxygen/html/form_72.png differ diff --git a/doc/doxygen/html/form_73.png b/doc/doxygen/html/form_73.png new file mode 100644 index 00000000..3d0b8e89 Binary files /dev/null and b/doc/doxygen/html/form_73.png differ diff --git a/doc/doxygen/html/form_74.png b/doc/doxygen/html/form_74.png new file mode 100644 index 00000000..58e90a85 Binary files /dev/null and b/doc/doxygen/html/form_74.png differ diff --git a/doc/doxygen/html/form_75.png b/doc/doxygen/html/form_75.png new file mode 100644 index 00000000..c31aeb8f Binary files /dev/null and b/doc/doxygen/html/form_75.png differ diff --git a/doc/doxygen/html/form_76.png b/doc/doxygen/html/form_76.png new file mode 100644 index 00000000..feaa0f4b Binary files /dev/null and b/doc/doxygen/html/form_76.png differ diff --git a/doc/doxygen/html/form_77.png b/doc/doxygen/html/form_77.png new file mode 100644 index 00000000..27cb9b7e Binary files /dev/null and b/doc/doxygen/html/form_77.png differ diff --git a/doc/doxygen/html/form_78.png b/doc/doxygen/html/form_78.png new file mode 100644 index 00000000..27ec37d6 Binary files /dev/null and b/doc/doxygen/html/form_78.png differ diff --git a/doc/doxygen/html/form_79.png b/doc/doxygen/html/form_79.png new file mode 100644 index 00000000..abe8a56a Binary files /dev/null and b/doc/doxygen/html/form_79.png differ diff --git a/doc/doxygen/html/form_8.png b/doc/doxygen/html/form_8.png new file mode 100644 index 00000000..fd8d50fd Binary files /dev/null and b/doc/doxygen/html/form_8.png differ diff --git a/doc/doxygen/html/form_80.png b/doc/doxygen/html/form_80.png new file mode 100644 index 00000000..12ced88d Binary files /dev/null and b/doc/doxygen/html/form_80.png differ diff --git a/doc/doxygen/html/form_81.png b/doc/doxygen/html/form_81.png new file mode 100644 index 00000000..2456fd14 Binary files /dev/null and b/doc/doxygen/html/form_81.png differ diff --git a/doc/doxygen/html/form_82.png b/doc/doxygen/html/form_82.png new file mode 100644 index 00000000..e6b80773 Binary files /dev/null and b/doc/doxygen/html/form_82.png differ diff --git a/doc/doxygen/html/form_83.png b/doc/doxygen/html/form_83.png new file mode 100644 index 00000000..9bbd3030 Binary files /dev/null and b/doc/doxygen/html/form_83.png differ diff --git a/doc/doxygen/html/form_84.png b/doc/doxygen/html/form_84.png new file mode 100644 index 00000000..e084303c Binary files /dev/null and b/doc/doxygen/html/form_84.png differ diff --git a/doc/doxygen/html/form_85.png b/doc/doxygen/html/form_85.png new file mode 100644 index 00000000..e9e2268b Binary files /dev/null and b/doc/doxygen/html/form_85.png differ diff --git a/doc/doxygen/html/form_86.png b/doc/doxygen/html/form_86.png new file mode 100644 index 00000000..a31f9653 Binary files /dev/null and b/doc/doxygen/html/form_86.png differ diff --git a/doc/doxygen/html/form_87.png b/doc/doxygen/html/form_87.png new file mode 100644 index 00000000..20fd5079 Binary files /dev/null and b/doc/doxygen/html/form_87.png differ diff --git a/doc/doxygen/html/form_88.png b/doc/doxygen/html/form_88.png new file mode 100644 index 00000000..587aedb5 Binary files /dev/null and b/doc/doxygen/html/form_88.png differ diff --git a/doc/doxygen/html/form_89.png b/doc/doxygen/html/form_89.png new file mode 100644 index 00000000..dc401458 Binary files /dev/null and b/doc/doxygen/html/form_89.png differ diff --git a/doc/doxygen/html/form_9.png b/doc/doxygen/html/form_9.png new file mode 100644 index 00000000..2cb221cb Binary files /dev/null and b/doc/doxygen/html/form_9.png differ diff --git a/doc/doxygen/html/form_90.png b/doc/doxygen/html/form_90.png new file mode 100644 index 00000000..354f074a Binary files /dev/null and b/doc/doxygen/html/form_90.png differ diff --git a/doc/doxygen/html/form_91.png b/doc/doxygen/html/form_91.png new file mode 100644 index 00000000..96722337 Binary files /dev/null and b/doc/doxygen/html/form_91.png differ diff --git a/doc/doxygen/html/formula.repository b/doc/doxygen/html/formula.repository new file mode 100644 index 00000000..f8e5a637 --- /dev/null +++ b/doc/doxygen/html/formula.repository @@ -0,0 +1,92 @@ +\form#0:$j+i\times ny$ +\form#1:$ C=A\backslash B$ +\form#2:$y=\alpha Ax$ +\form#3:$\left[n\times m\right]$ +\form#4:$m$ +\form#5:$n$ +\form#6:$y=\alpha A^Tx$ +\form#7:$\left[m\times n\right]$ +\form#8:$C=\alpha AB$ +\form#9:$m\times m$ +\form#10:$C=\alpha A^TB$ +\form#11:$x_i=x_i+\alpha y_i^ip$ +\form#12:$a^T B c$ +\form#13:$A^T A$ +\form#14:$\left[n\times k\right]$ +\form#15:$\left[n\times n\right]$ +\form#16:$A_{n+1,i}=A_{i,n+1}=x_i$ +\form#17:$A_{n+1,n+1}=scal$ +\form#18:$V^*$ +\form#19:$A$ +\form#20:$\alpha$ +\form#21:$\beta$ +\form#22:$y=f(\lambda;x)$ +\form#23:$x\in\mathbf{R}^s$ +\form#24:$\lambda\in\mathbf{R}^d$ +\form#25:$r$ +\form#26:$\lambda$ +\form#27:$x$ +\form#28:$r\times d$ +\form#29:$n\times s$ +\form#30:$r\times n$ +\form#31:$y=f(\lambda;x)=\lambda x$ +\form#32:$x\in\mathbf{R}^1$ +\form#33:$\lambda\in\mathbf{R}^1$ +\form#34:$y=f(\lambda;x)=\lambda_1 x+\lambda_2x^2$ +\form#35:$\lambda\in\mathbf{R}^2$ +\form#36:$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x}$ +\form#37:$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x+\lambda_3x^2}$ +\form#38:$\lambda\in\mathbf{R}^3$ +\form#39:$y=f(\lambda;x)=\lambda$ +\form#40:$y=f(\lambda;x)=\lambda_1+\lambda_2x$ +\form#41:$y=f(\lambda;x)=\frac{x d_w}{A_w \lambda}+T_0$ +\form#42:$d_w=0.1, A_w=0.04, T_0=273$ +\form#43:$y=f(\lambda;x)=\frac{x Q}{A_w \lambda_1}+\lambda_2$ +\form#44:$A_w=0.04, Q=20.0$ +\form#45:$y=f(\lambda;x)=\lambda_1+\lambda_2 x+\lambda_3 x^2+ \lambda_4 (x+1)^{3.5}$ +\form#46:$\lambda\in\mathbf{R}^4$ +\form#47:$y=f(\lambda;x)=\lambda_2 e^{\lambda_1 x} - 2$ +\form#48:$y=f(\lambda;x_i)=\lambda_i$ +\form#49:$i=1,...,d$ +\form#50:$x_i\in\mathbf{R}^1$ +\form#51:$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} \lambda_\alpha \Psi_\alpha(x)$ +\form#52:$\lambda\in\mathbf{R}^{|{\cal S}|}$ +\form#53:${\cal S}$ +\form#54:$z=(\lambda,x)$ +\form#55:$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} c_\alpha \Psi_\alpha(\lambda,x)$ +\form#56:$c_\alpha$ +\form#57:$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}} c_{\alpha,i} \Psi_\alpha(\lambda)$ +\form#58:$c_{\alpha,i}$ +\form#59:$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}_i} c_{\alpha,i} \Psi_\alpha(\lambda)$ +\form#60:$(-\infty,\infty)$ +\form#61:$[-1,1]$ +\form#62:$\xi=R^{-1}(u)\in\mathbf{R}^d$ +\form#63:$u\in[0,1]^d$ +\form#64:$d$ +\form#65:$d\times M$ +\form#66:$N\times d$ +\form#67:$u=R(\xi)$ +\form#68:$\xi$ +\form#69:$M\times d$ +\form#70:$\xi_d$ +\form#71:$[0,1]^d$ +\form#72:\[ F(t,\theta) = \left < F(t,\theta) \right >_{\theta} + \sum_{k=1}^{\infty} \sqrt{\lambda_k} f_k(t) \xi_k\] +\form#73:$C$ +\form#74:$t$ +\form#75:$w$ +\form#76:\[ \int C(s,t)f(t)dt=\lambda f(s) \rightarrow \sum w_j C(s_i,t_j) f_k(t_j) = \lambda_k f_k(s_i)\] +\form#77:\[A g=\lambda g \] +\form#78:$A=W K W$ +\form#79:$g=Wf$ +\form#80:$W$ +\form#81:$W_{ii}=\sqrt{w_i}$ +\form#82:$K_{ij}=Cov(t_i,t_j)$ +\form#83:$\lambda_k$ +\form#84:$f_k=W^{-1}g_k$ +\form#85:$F(t,\theta_l)$ +\form#86:$\xi_k$ +\form#87:$F$ +\form#88:$f_k$ +\form#89:\[ \left.\xi_k\right\vert_{\theta_l}=\left _{\theta}, f_k(t) \right >_t/\sqrt{\lambda_k} \] +\form#90:\[ \left.\xi_k\right\vert_{\theta_l}=\sum_{i=1}^{N_p} w_i\left(F(t_i,\theta_l)-\left < F(t_i,\theta) \right >_{\theta} \right) f_k(t_i)/\sqrt{\lambda_k} \] +\form#91:\[ F(t_i,\theta_l) = \left < F(t_i,\theta) \right >_{\theta} + \sum_{k=1}^{nKL} \sqrt{\lambda_k} f_k(t_i) \left. \xi_k\right\vert_{\theta_l} \] diff --git a/doc/doxygen/html/func_8cpp.html b/doc/doxygen/html/func_8cpp.html new file mode 100644 index 00000000..09869f7e --- /dev/null +++ b/doc/doxygen/html/func_8cpp.html @@ -0,0 +1,837 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: func.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
func.cpp File Reference
+
+
+ +

Implements several functions of form $y=f(\lambda;x)$. +More...

+
#include <math.h>
+#include <cfloat>
+#include <assert.h>
+#include "func.h"
+#include "gen_defs.h"
+#include "PCSet.h"
+#include "error_handlers.h"
+#include "arrayio.h"
+#include "arraytools.h"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

Array2D< double > Func_Prop (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^1$ More...
 
Array2D< double > Func_PropQuad (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_1 x+\lambda_2x^2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_Exp (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_ExpQuad (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x+\lambda_3x^2}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^3$ More...
 
Array2D< double > Func_Const (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^1$ More...
 
Array2D< double > Func_Linear (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_1+\lambda_2x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_BB (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)$ a black-box function with a script bb.x which takes p.dat and x.dat and returns output in y.dat More...
 
Array2D< double > Func_HT1 (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Heat_transfer1: a custom model designed for a tutorial case of a heat conduction problem. More...
 
Array2D< double > Func_HT2 (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Heat_transfer2: a custom model designed for a tutorial case of a heat conduction problem. More...
 
Array2D< double > Func_FracPower (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_1+\lambda_2 x+\lambda_3 x^2+ \lambda_4 (x+1)^{3.5}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^4$ More...
 
Array2D< double > Func_ExpSketch (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_2 e^{\lambda_1 x} - 2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_Inputs (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x_i)=\lambda_i$ for $i=1,...,d$, $x_i\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^d$ More...
 
Array2D< double > Func_PCl (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion with $\lambda$'s as coefficients. More...
 
Array2D< double > Func_PCx (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion with respect to $z=(\lambda,x)$. More...
 
Array2D< double > Func_PC (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion for each value of $x$. More...
 
Array2D< double > Func_PCs (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion for each value of $x$. More...
 
Array2D< double > augment (Array2D< double > &p, Array2D< double > &fixindnom)
 Augments a parameter matrix with 'fixed' columns given indices and nominal values of those. More...
 
+

Detailed Description

+

Implements several functions of form $y=f(\lambda;x)$.

+

Function Documentation

+ +

◆ augment()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> augment (Array2D< double > & p,
Array2D< double > & fixindnom 
)
+
+ +

Augments a parameter matrix with 'fixed' columns given indices and nominal values of those.

+ +
+
+ +

◆ Func_BB()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_BB (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)$ a black-box function with a script bb.x which takes p.dat and x.dat and returns output in y.dat

+ +
+
+ +

◆ Func_Const()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Const (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^1$

+ +
+
+ +

◆ Func_Exp()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Exp (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+ +

◆ Func_ExpQuad()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_ExpQuad (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x+\lambda_3x^2}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^3$

+ +
+
+ +

◆ Func_ExpSketch()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_ExpSketch (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_2 e^{\lambda_1 x} - 2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+ +

◆ Func_FracPower()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_FracPower (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_1+\lambda_2 x+\lambda_3 x^2+ \lambda_4 (x+1)^{3.5}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^4$

+ +
+
+ +

◆ Func_HT1()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_HT1 (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Heat_transfer1: a custom model designed for a tutorial case of a heat conduction problem.

+

$y=f(\lambda;x)=\frac{x d_w}{A_w \lambda}+T_0$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^1$

Note
hardwired parameters: $d_w=0.1, A_w=0.04, T_0=273$
+ +
+
+ +

◆ Func_HT2()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_HT2 (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Heat_transfer2: a custom model designed for a tutorial case of a heat conduction problem.

+

$y=f(\lambda;x)=\frac{x Q}{A_w \lambda_1}+\lambda_2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

Note
hardwired parameters: $A_w=0.04, Q=20.0$
+ +
+
+ +

◆ Func_Inputs()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Inputs (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x_i)=\lambda_i$ for $i=1,...,d$, $x_i\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^d$

+ +
+
+ +

◆ Func_Linear()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Linear (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_1+\lambda_2x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+ +

◆ Func_PC()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PC (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion for each value of $x$.

+

$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}} c_{\alpha,i} \Psi_\alpha(\lambda)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$

Note
hardwired parameters: common multiindex set for all PCs ${\cal S}$ is given in a file mindexp.dat, coefficients $c_{\alpha,i}$ are given in a file pccf_all.dat
+ +
+
+ +

◆ Func_PCl()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PCl (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion with $\lambda$'s as coefficients.

+

$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} \lambda_\alpha \Psi_\alpha(x)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^{|{\cal S}|}$

Note
hardwired parameter: multiindex set ${\cal S}$ is given in a file mindexx.dat
+ +
+
+ +

◆ Func_PCs()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PCs (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion for each value of $x$.

+

$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}_i} c_{\alpha,i} \Psi_\alpha(\lambda)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$

Note
hardwired parameters: multiindex sets for all PCs ${\cal S}$ are given in files mindexp.i.dat, coefficients $c_{\alpha,i}$ are given in files pccfp.i.dat
+ +
+
+ +

◆ Func_PCx()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PCx (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion with respect to $z=(\lambda,x)$.

+

$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} c_\alpha \Psi_\alpha(\lambda,x)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$

Note
hardwired parameters: multiindex set ${\cal S}$ is given in a file mindexpx.dat, coefficients $c_\alpha$ given in a file pccfpx.dat
+ +
+
+ +

◆ Func_Prop()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Prop (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^1$

+ +
+
+ +

◆ Func_PropQuad()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PropQuad (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_1 x+\lambda_2x^2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/func_8h.html b/doc/doxygen/html/func_8h.html new file mode 100644 index 00000000..fea3214a --- /dev/null +++ b/doc/doxygen/html/func_8h.html @@ -0,0 +1,846 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: func.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
func.h File Reference
+
+
+ +

Header for implementation of functions of form $y=f(\lambda;x)$. +More...

+
#include "Array1D.h"
+#include "Array2D.h"
+#include <iostream>
+#include <string.h>
+#include <stdio.h>
+#include <sstream>
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

Array2D< double > Func_Prop (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^1$ More...
 
Array2D< double > Func_PropQuad (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_1 x+\lambda_2x^2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_Exp (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_ExpQuad (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x+\lambda_3x^2}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^3$ More...
 
Array2D< double > Func_Const (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^1$ More...
 
Array2D< double > Func_Linear (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_1+\lambda_2x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_BB (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)$ a black-box function with a script bb.x which takes p.dat and x.dat and returns output in y.dat More...
 
Array2D< double > Func_HT1 (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Heat_transfer1: a custom model designed for a tutorial case of a heat conduction problem. More...
 
Array2D< double > Func_HT2 (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Heat_transfer2: a custom model designed for a tutorial case of a heat conduction problem. More...
 
Array2D< double > Func_FracPower (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_1+\lambda_2 x+\lambda_3 x^2+ \lambda_4 (x+1)^{3.5}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^4$ More...
 
Array2D< double > Func_ExpSketch (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x)=\lambda_2 e^{\lambda_1 x} - 2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$ More...
 
Array2D< double > Func_Inputs (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 $y=f(\lambda;x_i)=\lambda_i$ for $i=1,...,d$, $x_i\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^d$ More...
 
Array2D< double > Func_PCl (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion with $\lambda$'s as coefficients. More...
 
Array2D< double > Func_PCx (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion with respect to $z=(\lambda,x)$. More...
 
Array2D< double > Func_PC (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion for each value of $x$. More...
 
Array2D< double > Func_PCs (Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
 Legendre PC expansion for each value of $x$. More...
 
Array2D< double > augment (Array2D< double > &p, Array2D< double > &fixindnom)
 Augments a parameter matrix with 'fixed' columns given indices and nominal values of those. More...
 
+

Detailed Description

+

Header for implementation of functions of form $y=f(\lambda;x)$.

+
Note
Functions of form $y=f(\lambda;x)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$ at $r$ values of model parameters $\lambda$ and $n$ values of design parameters $x$
+
Parameters
+ + + + +
pModel parameters $\lambda$ as a matrix $r\times d$
xDesign parameters $x$ as a matrix $n\times s$
*funcinfoPotentially function-specific information
+
+
+
Returns
y Output as a matrix $r\times n$
+

Function Documentation

+ +

◆ augment()

+ +
+
+ + + + + + + + + + + + + + + + + + +
Array2D<double> augment (Array2D< double > & p,
Array2D< double > & fixindnom 
)
+
+ +

Augments a parameter matrix with 'fixed' columns given indices and nominal values of those.

+ +
+
+ +

◆ Func_BB()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_BB (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)$ a black-box function with a script bb.x which takes p.dat and x.dat and returns output in y.dat

+ +
+
+ +

◆ Func_Const()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Const (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^1$

+ +
+
+ +

◆ Func_Exp()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Exp (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+ +

◆ Func_ExpQuad()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_ExpQuad (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=e^{\lambda_1 +\lambda_2x+\lambda_3x^2}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^3$

+ +
+
+ +

◆ Func_ExpSketch()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_ExpSketch (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_2 e^{\lambda_1 x} - 2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+ +

◆ Func_FracPower()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_FracPower (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_1+\lambda_2 x+\lambda_3 x^2+ \lambda_4 (x+1)^{3.5}$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^4$

+ +
+
+ +

◆ Func_HT1()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_HT1 (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Heat_transfer1: a custom model designed for a tutorial case of a heat conduction problem.

+

$y=f(\lambda;x)=\frac{x d_w}{A_w \lambda}+T_0$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^1$

Note
hardwired parameters: $d_w=0.1, A_w=0.04, T_0=273$
+ +
+
+ +

◆ Func_HT2()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_HT2 (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Heat_transfer2: a custom model designed for a tutorial case of a heat conduction problem.

+

$y=f(\lambda;x)=\frac{x Q}{A_w \lambda_1}+\lambda_2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

Note
hardwired parameters: $A_w=0.04, Q=20.0$
+ +
+
+ +

◆ Func_Inputs()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Inputs (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x_i)=\lambda_i$ for $i=1,...,d$, $x_i\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^d$

+ +
+
+ +

◆ Func_Linear()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Linear (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_1+\lambda_2x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+ +

◆ Func_PC()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PC (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion for each value of $x$.

+

$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}} c_{\alpha,i} \Psi_\alpha(\lambda)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$

Note
hardwired parameters: common multiindex set for all PCs ${\cal S}$ is given in a file mindexp.dat, coefficients $c_{\alpha,i}$ are given in a file pccf_all.dat
+ +
+
+ +

◆ Func_PCl()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PCl (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion with $\lambda$'s as coefficients.

+

$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} \lambda_\alpha \Psi_\alpha(x)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^{|{\cal S}|}$

Note
hardwired parameter: multiindex set ${\cal S}$ is given in a file mindexx.dat
+ +
+
+ +

◆ Func_PCs()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PCs (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion for each value of $x$.

+

$y=f(\lambda;x^{(i)})=\sum_{\alpha\in{\cal S}_i} c_{\alpha,i} \Psi_\alpha(\lambda)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$

Note
hardwired parameters: multiindex sets for all PCs ${\cal S}$ are given in files mindexp.i.dat, coefficients $c_{\alpha,i}$ are given in files pccfp.i.dat
+ +
+
+ +

◆ Func_PCx()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PCx (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

Legendre PC expansion with respect to $z=(\lambda,x)$.

+

$y=f(\lambda;x)=\sum_{\alpha\in{\cal S}} c_\alpha \Psi_\alpha(\lambda,x)$ for $x\in\mathbf{R}^s$ and $\lambda\in\mathbf{R}^d$

Note
hardwired parameters: multiindex set ${\cal S}$ is given in a file mindexpx.dat, coefficients $c_\alpha$ given in a file pccfpx.dat
+ +
+
+ +

◆ Func_Prop()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_Prop (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda x$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^1$

+ +
+
+ +

◆ Func_PropQuad()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Array2D<double> Func_PropQuad (Array2D< double > & p,
Array2D< double > & x,
Array2D< double > & fixindnom,
void * funcinfo 
)
+
+ +

$y=f(\lambda;x)=\lambda_1 x+\lambda_2x^2$ for $x\in\mathbf{R}^1$ and $\lambda\in\mathbf{R}^2$

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/func_8h_source.html b/doc/doxygen/html/func_8h_source.html new file mode 100644 index 00000000..f5c7ebc9 --- /dev/null +++ b/doc/doxygen/html/func_8h_source.html @@ -0,0 +1,78 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: func.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
func.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
36 
37 #ifndef FUNC_H_SEEN
38 #define FUNC_H_SEEN
39 
40 #include "Array1D.h"
41 #include "Array2D.h"
42 
43 #include <iostream>
44 #include <string.h>
45 #include <stdio.h>
46 #include <sstream>
47 
48 using namespace std; // needed for python string conversion
49 
50 
51 
53 Array2D<double> Func_Prop(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
54 
57 
59 Array2D<double> Func_Exp(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
60 
63 
66 
69 
71 Array2D<double> Func_BB(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
72 
76 Array2D<double> Func_HT1(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
77 
81 Array2D<double> Func_HT2(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
82 
85 
88 
91 
95 Array2D<double> Func_PCl(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
96 
100 Array2D<double> Func_PCx(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
101 
105 Array2D<double> Func_PC(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
106 
110 Array2D<double> Func_PCs(Array2D<double>& p, Array2D<double>& x, Array2D<double>& fixindnom, void* funcinfo);
111 
112 
115 
116 
117 #endif /* FUNC_H_SEEN */
+
Array2D< double > Func_Const(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:136
+
Array2D< double > Func_Linear(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:158
+
Array2D< double > Func_PCl(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
Legendre PC expansion with &#39;s as coefficients.
Definition: func.cpp:327
+
Array2D< double > augment(Array2D< double > &p, Array2D< double > &fixindnom)
Augments a parameter matrix with &#39;fixed&#39; columns given indices and nominal values of those...
Definition: func.cpp:506
+
Array2D< double > Func_PropQuad(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:67
+ +
Array2D< double > Func_ExpQuad(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:113
+
Array2D< double > Func_PC(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
Legendre PC expansion for each value of .
Definition: func.cpp:410
+
Array2D< double > Func_PCx(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
Legendre PC expansion with respect to .
Definition: func.cpp:367
+
2D Array class for any type T
+
Array2D< double > Func_HT1(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
Heat_transfer1: a custom model designed for a tutorial case of a heat conduction problem.
Definition: func.cpp:205
+
Array2D< double > Func_Inputs(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for , and
Definition: func.cpp:304
+
Array2D< double > Func_BB(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
a black-box function with a script bb.x which takes p.dat and x.dat and returns output in y...
Definition: func.cpp:181
+
Array2D< double > Func_PCs(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
Legendre PC expansion for each value of .
Definition: func.cpp:455
+
Array2D< double > Func_Prop(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:44
+
Array2D< double > Func_ExpSketch(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:281
+
Array2D< double > Func_Exp(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:90
+
1D Array class for any type T
+
Array2D< double > Func_FracPower(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
for and
Definition: func.cpp:257
+
Array2D< double > Func_HT2(Array2D< double > &p, Array2D< double > &x, Array2D< double > &fixindnom, void *funcinfo)
Heat_transfer2: a custom model designed for a tutorial case of a heat conduction problem.
Definition: func.cpp:231
+
+ + + + diff --git a/doc/doxygen/html/functions.html b/doc/doxygen/html/functions.html new file mode 100644 index 00000000..4b2c1af4 --- /dev/null +++ b/doc/doxygen/html/functions.html @@ -0,0 +1,149 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- a -

+
+ + + + diff --git a/doc/doxygen/html/functions_0x7e.html b/doc/doxygen/html/functions_0x7e.html new file mode 100644 index 00000000..7437f5ee --- /dev/null +++ b/doc/doxygen/html/functions_0x7e.html @@ -0,0 +1,160 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- ~ -

+
+ + + + diff --git a/doc/doxygen/html/functions_b.html b/doc/doxygen/html/functions_b.html new file mode 100644 index 00000000..295f261c --- /dev/null +++ b/doc/doxygen/html/functions_b.html @@ -0,0 +1,95 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- b -

+
+ + + + diff --git a/doc/doxygen/html/functions_c.html b/doc/doxygen/html/functions_c.html new file mode 100644 index 00000000..95479de2 --- /dev/null +++ b/doc/doxygen/html/functions_c.html @@ -0,0 +1,241 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- c -

+
+ + + + diff --git a/doc/doxygen/html/functions_d.html b/doc/doxygen/html/functions_d.html new file mode 100644 index 00000000..44018c62 --- /dev/null +++ b/doc/doxygen/html/functions_d.html @@ -0,0 +1,169 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- d -

+
+ + + + diff --git a/doc/doxygen/html/functions_e.html b/doc/doxygen/html/functions_e.html new file mode 100644 index 00000000..08762080 --- /dev/null +++ b/doc/doxygen/html/functions_e.html @@ -0,0 +1,201 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- e -

+
+ + + + diff --git a/doc/doxygen/html/functions_f.html b/doc/doxygen/html/functions_f.html new file mode 100644 index 00000000..c02b8c24 --- /dev/null +++ b/doc/doxygen/html/functions_f.html @@ -0,0 +1,96 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- f -

+
+ + + + diff --git a/doc/doxygen/html/functions_func.html b/doc/doxygen/html/functions_func.html new file mode 100644 index 00000000..a756fd45 --- /dev/null +++ b/doc/doxygen/html/functions_func.html @@ -0,0 +1,88 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- a -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_0x7e.html b/doc/doxygen/html/functions_func_0x7e.html new file mode 100644 index 00000000..42711f07 --- /dev/null +++ b/doc/doxygen/html/functions_func_0x7e.html @@ -0,0 +1,160 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- ~ -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_b.html b/doc/doxygen/html/functions_func_b.html new file mode 100644 index 00000000..af6e4089 --- /dev/null +++ b/doc/doxygen/html/functions_func_b.html @@ -0,0 +1,68 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- b -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_c.html b/doc/doxygen/html/functions_func_c.html new file mode 100644 index 00000000..dac4ef2b --- /dev/null +++ b/doc/doxygen/html/functions_func_c.html @@ -0,0 +1,165 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- c -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_d.html b/doc/doxygen/html/functions_func_d.html new file mode 100644 index 00000000..97dd01ab --- /dev/null +++ b/doc/doxygen/html/functions_func_d.html @@ -0,0 +1,117 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- d -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_e.html b/doc/doxygen/html/functions_func_e.html new file mode 100644 index 00000000..430b6777 --- /dev/null +++ b/doc/doxygen/html/functions_func_e.html @@ -0,0 +1,174 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- e -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_f.html b/doc/doxygen/html/functions_func_f.html new file mode 100644 index 00000000..24443e26 --- /dev/null +++ b/doc/doxygen/html/functions_func_f.html @@ -0,0 +1,69 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- f -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_g.html b/doc/doxygen/html/functions_func_g.html new file mode 100644 index 00000000..d0a23561 --- /dev/null +++ b/doc/doxygen/html/functions_func_g.html @@ -0,0 +1,341 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- g -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_h.html b/doc/doxygen/html/functions_func_h.html new file mode 100644 index 00000000..8ff140f1 --- /dev/null +++ b/doc/doxygen/html/functions_func_h.html @@ -0,0 +1,56 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- h -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_i.html b/doc/doxygen/html/functions_func_i.html new file mode 100644 index 00000000..58896f04 --- /dev/null +++ b/doc/doxygen/html/functions_func_i.html @@ -0,0 +1,131 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- i -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_k.html b/doc/doxygen/html/functions_func_k.html new file mode 100644 index 00000000..880b1901 --- /dev/null +++ b/doc/doxygen/html/functions_func_k.html @@ -0,0 +1,62 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- k -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_l.html b/doc/doxygen/html/functions_func_l.html new file mode 100644 index 00000000..66f0be34 --- /dev/null +++ b/doc/doxygen/html/functions_func_l.html @@ -0,0 +1,124 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- l -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_m.html b/doc/doxygen/html/functions_func_m.html new file mode 100644 index 00000000..85736855 --- /dev/null +++ b/doc/doxygen/html/functions_func_m.html @@ -0,0 +1,89 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- m -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_n.html b/doc/doxygen/html/functions_func_n.html new file mode 100644 index 00000000..80f37d08 --- /dev/null +++ b/doc/doxygen/html/functions_func_n.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- n -

    +
  • namesPrepended() +: MCMC +
  • +
  • newModeFound() +: MCMC +
  • +
  • nextLevel() +: Quad +
  • +
  • NormSq_Exact() +: PCBasis +
  • +
+
+ + + + diff --git a/doc/doxygen/html/functions_func_o.html b/doc/doxygen/html/functions_func_o.html new file mode 100644 index 00000000..fc44fe08 --- /dev/null +++ b/doc/doxygen/html/functions_func_o.html @@ -0,0 +1,93 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- o -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_p.html b/doc/doxygen/html/functions_func_p.html new file mode 100644 index 00000000..e3ba7d1f --- /dev/null +++ b/doc/doxygen/html/functions_func_p.html @@ -0,0 +1,131 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- p -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_q.html b/doc/doxygen/html/functions_func_q.html new file mode 100644 index 00000000..7387db2c --- /dev/null +++ b/doc/doxygen/html/functions_func_q.html @@ -0,0 +1,59 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- q -

    +
  • Quad() +: Quad +
  • +
  • quadParam() +: Mrv +
  • +
+
+ + + + diff --git a/doc/doxygen/html/functions_func_r.html b/doc/doxygen/html/functions_func_r.html new file mode 100644 index 00000000..98f792f9 --- /dev/null +++ b/doc/doxygen/html/functions_func_r.html @@ -0,0 +1,113 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- r -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_s.html b/doc/doxygen/html/functions_func_s.html new file mode 100644 index 00000000..713c0cf6 --- /dev/null +++ b/doc/doxygen/html/functions_func_s.html @@ -0,0 +1,253 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- s -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_t.html b/doc/doxygen/html/functions_func_t.html new file mode 100644 index 00000000..f82cd6e2 --- /dev/null +++ b/doc/doxygen/html/functions_func_t.html @@ -0,0 +1,62 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- t -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_u.html b/doc/doxygen/html/functions_func_u.html new file mode 100644 index 00000000..b16009da --- /dev/null +++ b/doc/doxygen/html/functions_func_u.html @@ -0,0 +1,56 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- u -

    +
  • updateMode() +: MCMC +
  • +
+
+ + + + diff --git a/doc/doxygen/html/functions_func_w.html b/doc/doxygen/html/functions_func_w.html new file mode 100644 index 00000000..81e59262 --- /dev/null +++ b/doc/doxygen/html/functions_func_w.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- w -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_x.html b/doc/doxygen/html/functions_func_x.html new file mode 100644 index 00000000..855490f3 --- /dev/null +++ b/doc/doxygen/html/functions_func_x.html @@ -0,0 +1,72 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- x -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_y.html b/doc/doxygen/html/functions_func_y.html new file mode 100644 index 00000000..1cdbcab2 --- /dev/null +++ b/doc/doxygen/html/functions_func_y.html @@ -0,0 +1,57 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- y -

+
+ + + + diff --git a/doc/doxygen/html/functions_func_z.html b/doc/doxygen/html/functions_func_z.html new file mode 100644 index 00000000..3f13ae34 --- /dev/null +++ b/doc/doxygen/html/functions_func_z.html @@ -0,0 +1,56 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- z -

+
+ + + + diff --git a/doc/doxygen/html/functions_g.html b/doc/doxygen/html/functions_g.html new file mode 100644 index 00000000..5427ef4b --- /dev/null +++ b/doc/doxygen/html/functions_g.html @@ -0,0 +1,368 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- g -

+
+ + + + diff --git a/doc/doxygen/html/functions_h.html b/doc/doxygen/html/functions_h.html new file mode 100644 index 00000000..7ca3f5d1 --- /dev/null +++ b/doc/doxygen/html/functions_h.html @@ -0,0 +1,74 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- h -

+
+ + + + diff --git a/doc/doxygen/html/functions_i.html b/doc/doxygen/html/functions_i.html new file mode 100644 index 00000000..9860f61f --- /dev/null +++ b/doc/doxygen/html/functions_i.html @@ -0,0 +1,152 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- i -

+
+ + + + diff --git a/doc/doxygen/html/functions_j.html b/doc/doxygen/html/functions_j.html new file mode 100644 index 00000000..ca1a64a6 --- /dev/null +++ b/doc/doxygen/html/functions_j.html @@ -0,0 +1,62 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- j -

+
+ + + + diff --git a/doc/doxygen/html/functions_k.html b/doc/doxygen/html/functions_k.html new file mode 100644 index 00000000..c7d82c0a --- /dev/null +++ b/doc/doxygen/html/functions_k.html @@ -0,0 +1,68 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- k -

+
+ + + + diff --git a/doc/doxygen/html/functions_l.html b/doc/doxygen/html/functions_l.html new file mode 100644 index 00000000..8c535775 --- /dev/null +++ b/doc/doxygen/html/functions_l.html @@ -0,0 +1,151 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- l -

+
+ + + + diff --git a/doc/doxygen/html/functions_m.html b/doc/doxygen/html/functions_m.html new file mode 100644 index 00000000..250ae670 --- /dev/null +++ b/doc/doxygen/html/functions_m.html @@ -0,0 +1,144 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- m -

+
+ + + + diff --git a/doc/doxygen/html/functions_n.html b/doc/doxygen/html/functions_n.html new file mode 100644 index 00000000..c3fb4b56 --- /dev/null +++ b/doc/doxygen/html/functions_n.html @@ -0,0 +1,143 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- n -

+
+ + + + diff --git a/doc/doxygen/html/functions_o.html b/doc/doxygen/html/functions_o.html new file mode 100644 index 00000000..47cd730f --- /dev/null +++ b/doc/doxygen/html/functions_o.html @@ -0,0 +1,109 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- o -

+
+ + + + diff --git a/doc/doxygen/html/functions_p.html b/doc/doxygen/html/functions_p.html new file mode 100644 index 00000000..5693b5c6 --- /dev/null +++ b/doc/doxygen/html/functions_p.html @@ -0,0 +1,221 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- p -

+
+ + + + diff --git a/doc/doxygen/html/functions_q.html b/doc/doxygen/html/functions_q.html new file mode 100644 index 00000000..ae560e03 --- /dev/null +++ b/doc/doxygen/html/functions_q.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- q -

+
+ + + + diff --git a/doc/doxygen/html/functions_r.html b/doc/doxygen/html/functions_r.html new file mode 100644 index 00000000..e1404040 --- /dev/null +++ b/doc/doxygen/html/functions_r.html @@ -0,0 +1,161 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- r -

+
+ + + + diff --git a/doc/doxygen/html/functions_rela.html b/doc/doxygen/html/functions_rela.html new file mode 100644 index 00000000..ee7be52e --- /dev/null +++ b/doc/doxygen/html/functions_rela.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Related Functions + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ + + + + diff --git a/doc/doxygen/html/functions_s.html b/doc/doxygen/html/functions_s.html new file mode 100644 index 00000000..a501fbf6 --- /dev/null +++ b/doc/doxygen/html/functions_s.html @@ -0,0 +1,290 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- s -

+
+ + + + diff --git a/doc/doxygen/html/functions_t.html b/doc/doxygen/html/functions_t.html new file mode 100644 index 00000000..a80aa30f --- /dev/null +++ b/doc/doxygen/html/functions_t.html @@ -0,0 +1,73 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- t -

+
+ + + + diff --git a/doc/doxygen/html/functions_type.html b/doc/doxygen/html/functions_type.html new file mode 100644 index 00000000..5c37da07 --- /dev/null +++ b/doc/doxygen/html/functions_type.html @@ -0,0 +1,66 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Typedefs + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+ + + + diff --git a/doc/doxygen/html/functions_u.html b/doc/doxygen/html/functions_u.html new file mode 100644 index 00000000..c769358c --- /dev/null +++ b/doc/doxygen/html/functions_u.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- u -

+
+ + + + diff --git a/doc/doxygen/html/functions_v.html b/doc/doxygen/html/functions_v.html new file mode 100644 index 00000000..96731db1 --- /dev/null +++ b/doc/doxygen/html/functions_v.html @@ -0,0 +1,77 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- v -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars.html b/doc/doxygen/html/functions_vars.html new file mode 100644 index 00000000..eb922f13 --- /dev/null +++ b/doc/doxygen/html/functions_vars.html @@ -0,0 +1,114 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- a -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_b.html b/doc/doxygen/html/functions_vars_b.html new file mode 100644 index 00000000..6367144c --- /dev/null +++ b/doc/doxygen/html/functions_vars_b.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- b -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_c.html b/doc/doxygen/html/functions_vars_c.html new file mode 100644 index 00000000..48607b15 --- /dev/null +++ b/doc/doxygen/html/functions_vars_c.html @@ -0,0 +1,119 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- c -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_d.html b/doc/doxygen/html/functions_vars_d.html new file mode 100644 index 00000000..e7fec818 --- /dev/null +++ b/doc/doxygen/html/functions_vars_d.html @@ -0,0 +1,105 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- d -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_e.html b/doc/doxygen/html/functions_vars_e.html new file mode 100644 index 00000000..4f199624 --- /dev/null +++ b/doc/doxygen/html/functions_vars_e.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- e -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_f.html b/doc/doxygen/html/functions_vars_f.html new file mode 100644 index 00000000..acfa2142 --- /dev/null +++ b/doc/doxygen/html/functions_vars_f.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- f -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_g.html b/doc/doxygen/html/functions_vars_g.html new file mode 100644 index 00000000..e8ceb5a9 --- /dev/null +++ b/doc/doxygen/html/functions_vars_g.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- g -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_h.html b/doc/doxygen/html/functions_vars_h.html new file mode 100644 index 00000000..2e4f4858 --- /dev/null +++ b/doc/doxygen/html/functions_vars_h.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- h -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_i.html b/doc/doxygen/html/functions_vars_i.html new file mode 100644 index 00000000..d89cc374 --- /dev/null +++ b/doc/doxygen/html/functions_vars_i.html @@ -0,0 +1,71 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- i -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_j.html b/doc/doxygen/html/functions_vars_j.html new file mode 100644 index 00000000..7886755a --- /dev/null +++ b/doc/doxygen/html/functions_vars_j.html @@ -0,0 +1,62 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- j -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_k.html b/doc/doxygen/html/functions_vars_k.html new file mode 100644 index 00000000..5ef395a6 --- /dev/null +++ b/doc/doxygen/html/functions_vars_k.html @@ -0,0 +1,59 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- k -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_l.html b/doc/doxygen/html/functions_vars_l.html new file mode 100644 index 00000000..a0e46436 --- /dev/null +++ b/doc/doxygen/html/functions_vars_l.html @@ -0,0 +1,80 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- l -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_m.html b/doc/doxygen/html/functions_vars_m.html new file mode 100644 index 00000000..a50e7bd2 --- /dev/null +++ b/doc/doxygen/html/functions_vars_m.html @@ -0,0 +1,105 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- m -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_n.html b/doc/doxygen/html/functions_vars_n.html new file mode 100644 index 00000000..8150eec7 --- /dev/null +++ b/doc/doxygen/html/functions_vars_n.html @@ -0,0 +1,131 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- n -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_o.html b/doc/doxygen/html/functions_vars_o.html new file mode 100644 index 00000000..c3cab09e --- /dev/null +++ b/doc/doxygen/html/functions_vars_o.html @@ -0,0 +1,66 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- o -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_p.html b/doc/doxygen/html/functions_vars_p.html new file mode 100644 index 00000000..8afc352c --- /dev/null +++ b/doc/doxygen/html/functions_vars_p.html @@ -0,0 +1,143 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- p -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_q.html b/doc/doxygen/html/functions_vars_q.html new file mode 100644 index 00000000..558d89f3 --- /dev/null +++ b/doc/doxygen/html/functions_vars_q.html @@ -0,0 +1,74 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- q -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_r.html b/doc/doxygen/html/functions_vars_r.html new file mode 100644 index 00000000..a6e252cd --- /dev/null +++ b/doc/doxygen/html/functions_vars_r.html @@ -0,0 +1,96 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- r -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_s.html b/doc/doxygen/html/functions_vars_s.html new file mode 100644 index 00000000..4bb6bd22 --- /dev/null +++ b/doc/doxygen/html/functions_vars_s.html @@ -0,0 +1,90 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- s -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_t.html b/doc/doxygen/html/functions_vars_t.html new file mode 100644 index 00000000..c5c3bd41 --- /dev/null +++ b/doc/doxygen/html/functions_vars_t.html @@ -0,0 +1,63 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- t -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_u.html b/doc/doxygen/html/functions_vars_u.html new file mode 100644 index 00000000..81c7318c --- /dev/null +++ b/doc/doxygen/html/functions_vars_u.html @@ -0,0 +1,68 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- u -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_v.html b/doc/doxygen/html/functions_vars_v.html new file mode 100644 index 00000000..f37edb0a --- /dev/null +++ b/doc/doxygen/html/functions_vars_v.html @@ -0,0 +1,77 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- v -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_w.html b/doc/doxygen/html/functions_vars_w.html new file mode 100644 index 00000000..f019c048 --- /dev/null +++ b/doc/doxygen/html/functions_vars_w.html @@ -0,0 +1,74 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- w -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_x.html b/doc/doxygen/html/functions_vars_x.html new file mode 100644 index 00000000..a5266446 --- /dev/null +++ b/doc/doxygen/html/functions_vars_x.html @@ -0,0 +1,70 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- x -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_y.html b/doc/doxygen/html/functions_vars_y.html new file mode 100644 index 00000000..39a642c7 --- /dev/null +++ b/doc/doxygen/html/functions_vars_y.html @@ -0,0 +1,70 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- y -

+
+ + + + diff --git a/doc/doxygen/html/functions_vars_z.html b/doc/doxygen/html/functions_vars_z.html new file mode 100644 index 00000000..30eccdf3 --- /dev/null +++ b/doc/doxygen/html/functions_vars_z.html @@ -0,0 +1,64 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members - Variables + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- z -

+
+ + + + diff --git a/doc/doxygen/html/functions_w.html b/doc/doxygen/html/functions_w.html new file mode 100644 index 00000000..10817223 --- /dev/null +++ b/doc/doxygen/html/functions_w.html @@ -0,0 +1,86 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- w -

+
+ + + + diff --git a/doc/doxygen/html/functions_x.html b/doc/doxygen/html/functions_x.html new file mode 100644 index 00000000..9f278036 --- /dev/null +++ b/doc/doxygen/html/functions_x.html @@ -0,0 +1,89 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- x -

+
+ + + + diff --git a/doc/doxygen/html/functions_y.html b/doc/doxygen/html/functions_y.html new file mode 100644 index 00000000..6cde22e5 --- /dev/null +++ b/doc/doxygen/html/functions_y.html @@ -0,0 +1,74 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- y -

+
+ + + + diff --git a/doc/doxygen/html/functions_z.html b/doc/doxygen/html/functions_z.html new file mode 100644 index 00000000..20b436cb --- /dev/null +++ b/doc/doxygen/html/functions_z.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all class members with links to the classes they belong to:
+ +

- z -

+
+ + + + diff --git a/doc/doxygen/html/gen__mi_8cpp.html b/doc/doxygen/html/gen__mi_8cpp.html new file mode 100644 index 00000000..6214ad90 --- /dev/null +++ b/doc/doxygen/html/gen__mi_8cpp.html @@ -0,0 +1,252 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gen_mi.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gen_mi.cpp File Reference
+
+
+ +

Command-line utility to generate multiindex. +More...

+
#include "tools.h"
+#include "arrayio.h"
+#include "arraytools.h"
+#include <unistd.h>
+
+ + + + + + + + + + + + + + + + + + + +

+Macros

#define MI_TYPE   "TO"
 default multiindex type More...
 
#define MI_SEQ   "NONE"
 default multiindex sequence More...
 
#define ORD   1
 default order More...
 
#define DIM   3
 default dimensionality More...
 
#define PARAM_FILE   "mi_param.dat"
 default parameter filename More...
 
#define VERBOSITY   1
 default verbosity More...
 
+ + + + + + + +

+Functions

int usage ()
 Displays information about this program. More...
 
int main (int argc, char *argv[])
 Main program: Generates multiindex of requested type with given parameters. More...
 
+

Detailed Description

+

Command-line utility to generate multiindex.

+
Author
K. Sargsyan 2014 -
+

Macro Definition Documentation

+ +

◆ DIM

+ +
+
+ + + + +
#define DIM   3
+
+ +

default dimensionality

+ +
+
+ +

◆ MI_SEQ

+ +
+
+ + + + +
#define MI_SEQ   "NONE"
+
+ +

default multiindex sequence

+ +
+
+ +

◆ MI_TYPE

+ +
+
+ + + + +
#define MI_TYPE   "TO"
+
+ +

default multiindex type

+ +
+
+ +

◆ ORD

+ +
+
+ + + + +
#define ORD   1
+
+ +

default order

+ +
+
+ +

◆ PARAM_FILE

+ +
+
+ + + + +
#define PARAM_FILE   "mi_param.dat"
+
+ +

default parameter filename

+ +
+
+ +

◆ VERBOSITY

+ +
+
+ + + + +
#define VERBOSITY   1
+
+ +

default verbosity

+ +
+
+

Function Documentation

+ +

◆ main()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int main (int argc,
char * argv[] 
)
+
+ +

Main program: Generates multiindex of requested type with given parameters.

+

Set the default values

+

Read the user input

+

Print the input information on screen

+

Write to file mindex.dat

+ +
+
+ +

◆ usage()

+ +
+
+ + + + + + + +
int usage ()
+
+ +

Displays information about this program.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/generate__quad_8cpp.html b/doc/doxygen/html/generate__quad_8cpp.html new file mode 100644 index 00000000..c7491262 --- /dev/null +++ b/doc/doxygen/html/generate__quad_8cpp.html @@ -0,0 +1,296 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: generate_quad.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
generate_quad.cpp File Reference
+
+
+ +

Command-line utility to generate quadrature points. +More...

+
#include <unistd.h>
+#include "quad.h"
+#include "tools.h"
+#include "arrayio.h"
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Macros

#define PARAM   3
 default value of parameter (level for sparse quadrature, or number of grid points for full quadrature) More...
 
#define DIM   2
 default data dimensionality More...
 
#define FSTYPE   "sparse"
 default sparseness type (full or sparse) More...
 
#define QUADTYPE   "CC"
 default quadrature type More...
 
#define ALPHA   0.0
 default alpha parameter for chaos More...
 
#define BETA   1.0
 default beta parameter for chaos More...
 
#define DOMAIN_FILE   "param_domain.dat"
 default domain file More...
 
#define VERBOSITY   1
 default verbosity More...
 
+ + + + + + + +

+Functions

int usage ()
 Displays information about this program. More...
 
int main (int argc, char *argv[])
 Main program: Generates various kinds of quadrature points and weights. More...
 
+

Detailed Description

+

Command-line utility to generate quadrature points.

+
Author
K. Sargsyan 2013 -
+

Macro Definition Documentation

+ +

◆ ALPHA

+ +
+
+ + + + +
#define ALPHA   0.0
+
+ +

default alpha parameter for chaos

+ +
+
+ +

◆ BETA

+ +
+
+ + + + +
#define BETA   1.0
+
+ +

default beta parameter for chaos

+ +
+
+ +

◆ DIM

+ +
+
+ + + + +
#define DIM   2
+
+ +

default data dimensionality

+ +
+
+ +

◆ DOMAIN_FILE

+ +
+
+ + + + +
#define DOMAIN_FILE   "param_domain.dat"
+
+ +

default domain file

+ +
+
+ +

◆ FSTYPE

+ +
+
+ + + + +
#define FSTYPE   "sparse"
+
+ +

default sparseness type (full or sparse)

+ +
+
+ +

◆ PARAM

+ +
+
+ + + + +
#define PARAM   3
+
+ +

default value of parameter (level for sparse quadrature, or number of grid points for full quadrature)

+ +
+
+ +

◆ QUADTYPE

+ +
+
+ + + + +
#define QUADTYPE   "CC"
+
+ +

default quadrature type

+ +
+
+ +

◆ VERBOSITY

+ +
+
+ + + + +
#define VERBOSITY   1
+
+ +

default verbosity

+ +
+
+

Function Documentation

+ +

◆ main()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int main (int argc,
char * argv[] 
)
+
+ +

Main program: Generates various kinds of quadrature points and weights.

+

Set the default values

+

Read the user input

+

Print the input information on screen

+

Parameter sanity checks

+

Declare the quadrature rule object

+

Extract the properties of the rule

+

Write-out to files

+

Scale if domain is provided

+

Set the domain

+

Write-out to files

+ +
+
+ +

◆ usage()

+ +
+
+ + + + + + + +
int usage ()
+
+ +

Displays information about this program.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gkpSparse_8cpp.html b/doc/doxygen/html/gkpSparse_8cpp.html new file mode 100644 index 00000000..331dad8f --- /dev/null +++ b/doc/doxygen/html/gkpSparse_8cpp.html @@ -0,0 +1,194 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gkpSparse.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gkpSparse.cpp File Reference
+
+
+
#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <unistd.h>
+#include <math.h>
+#include <assert.h>
+#include "arrayio.h"
+#include "gkplib.h"
+
+ + + + + + + + + +

+Macros

#define NDIM   2
 
#define NLEV   2
 
#define VERBOSITY   1
 
#define PDFTYPE   "unif"
 
+ + + + + + +

+Functions

int usage ()
 Displays information about this program. More...
 
int main (int argc, char *argv[])
 
+

Macro Definition Documentation

+ +

◆ NDIM

+ +
+
+ + + + +
#define NDIM   2
+
+ +
+
+ +

◆ NLEV

+ +
+
+ + + + +
#define NLEV   2
+
+ +
+
+ +

◆ PDFTYPE

+ +
+
+ + + + +
#define PDFTYPE   "unif"
+
+ +
+
+ +

◆ VERBOSITY

+ +
+
+ + + + +
#define VERBOSITY   1
+
+ +
+
+

Function Documentation

+ +

◆ main()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int main (int argc,
char * argv[] 
)
+
+

Read the user input

+ +
+
+ +

◆ usage()

+ +
+
+ + + + + + + +
int usage ()
+
+ +

Displays information about this program.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gkpclib_8cpp.html b/doc/doxygen/html/gkpclib_8cpp.html new file mode 100644 index 00000000..d1d2a760 --- /dev/null +++ b/doc/doxygen/html/gkpclib_8cpp.html @@ -0,0 +1,1160 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gkpclib.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gkpclib.cpp File Reference
+
+
+
#include "math.h"
+#include "tools.h"
+#include "gkplib.h"
+
+ + + +

+Macros

#define MAX(a, b)   (((a) > (b)) ? (a) : (b))
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

void getCC (int n, int *nq, double **x, double **w)
 retrieve pointers to 1D Clenshaw-Curtis rules More...
 
void getGKPunif (int n, int *nq, double **x, double **w)
 retrieve pointers to 1D Gauss-Kronrod-Patterson rules for uniform pdf based on the quadrature level More...
 
void getGKPnorm (int n, int *nq, double **x, double **w)
 retrieve pointers to 1D Kronrod-Patterson rules for normal pdf based on the quadrature level More...
 
int getOrderCC (int lev)
 get order of Clenshaw-Curtis rules based on level More...
 
int getOrderGKPunif (int lev)
 get order of uniform Gauss-Kronrod-Patterson rules based on level More...
 
int getOrderGKPnorm (int lev)
 get order of normal Gauss-Kronrod-Patterson rules based on level More...
 
void getCompNintoDim (int n, int dim, int *nelem, int **plist)
 List of decompositions of 'n' into 'dim' parts. The implementation is based on Algorithm 5 of Combinatorial Algorithms by Albert Nijenhuis, Herbert Wilf. More...
 
int getSpgSize (int getOrder(int), int dim, int lev)
 Initial estimate for sparse grid size. More...
 
void getSpgQW (void get1DQW(int, int *, double **, double **), int getOrder(int), int dim, int lev, int *nqpts, double **qpts, double **w)
 Main function that connects the user setup for pdftype, dimensionality, and quadrature level and various pieces of the sparse quadrature algorithm employing Gauss-Kronrod-Patterson rules. More...
 
void getSpgAnisQW (void get1DQW(int, int *, double **, double **), int getOrder(int), int dim, int *levList, int *nqpts, double **qpts, double **w)
 
void sortSpg (int dim, int spgSize, double *qpts, double *w)
 Sort sparse grid in lexicographical order. More...
 
void getTensorProd (int dim, double *qpts, double *w, int *spgSize, int *n1D, double **x1D, double **w1D, double qfac)
 compute dim-dimensional tensor grid based a series of 1D rules More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Variables

static double x1 [] = {0.0000000}
 
static double w1 [] = {2.0000000}
 
static double x3 [] = {-0.77459666924148337704,0.0, 0.77459666924148337704 }
 
static double w3 [] = {0.555555555555555555556,0.888888888888888888889,0.555555555555555555556}
 
static double x7 []
 
static double w7 []
 
static double x15 []
 
static double w15 []
 
static double x31 []
 
static double w31 []
 
static double x63 []
 
static double w63 []
 
static double xn1 [] = {0.0000000000000000}
 
static double wn1 [] = {1.0000000000000000}
 
static double xn3 [] = {-1.73205080756887719, 0.000000000000000000, 1.73205080756887719}
 
static double wn3 [] = {0.166666666666666657, 0.66666666666666663, 0.166666666666666657}
 
static double xn9 []
 
static double wn9 []
 
static double xn19 []
 
static double wn19 []
 
static double xn35 []
 
static double wn35 []
 
+

Macro Definition Documentation

+ +

◆ MAX

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define MAX( a,
 
)   (((a) > (b)) ? (a) : (b))
+
+ +
+
+

Function Documentation

+ +

◆ getCC()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getCC (int n,
int * nq,
double ** x,
double ** w 
)
+
+ +

retrieve pointers to 1D Clenshaw-Curtis rules

+ +
+
+ +

◆ getCompNintoDim()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getCompNintoDim (int n,
int dim,
int * nelem,
int ** plist 
)
+
+ +

List of decompositions of 'n' into 'dim' parts. The implementation is based on Algorithm 5 of Combinatorial Algorithms by Albert Nijenhuis, Herbert Wilf.

+ +
+
+ +

◆ getGKPnorm()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getGKPnorm (int n,
int * nq,
double ** x,
double ** w 
)
+
+ +

retrieve pointers to 1D Kronrod-Patterson rules for normal pdf based on the quadrature level

+ +
+
+ +

◆ getGKPunif()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getGKPunif (int n,
int * nq,
double ** x,
double ** w 
)
+
+ +

retrieve pointers to 1D Gauss-Kronrod-Patterson rules for uniform pdf based on the quadrature level

+ +
+
+ +

◆ getOrderCC()

+ +
+
+ + + + + + + + +
int getOrderCC (int lev)
+
+ +

get order of Clenshaw-Curtis rules based on level

+ +
+
+ +

◆ getOrderGKPnorm()

+ +
+
+ + + + + + + + +
int getOrderGKPnorm (int lev)
+
+ +

get order of normal Gauss-Kronrod-Patterson rules based on level

+ +
+
+ +

◆ getOrderGKPunif()

+ +
+
+ + + + + + + + +
int getOrderGKPunif (int lev)
+
+ +

get order of uniform Gauss-Kronrod-Patterson rules based on level

+ +
+
+ +

◆ getSpgAnisQW()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getSpgAnisQW (void  get1DQWint, int *, double **, double **,
int  getOrderint,
int dim,
int * levList,
int * nqpts,
double ** qpts,
double ** w 
)
+
+ +
+
+ +

◆ getSpgQW()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getSpgQW (void  get1DQWint, int *, double **, double **,
int  getOrderint,
int dim,
int lev,
int * nqpts,
double ** qpts,
double ** w 
)
+
+ +

Main function that connects the user setup for pdftype, dimensionality, and quadrature level and various pieces of the sparse quadrature algorithm employing Gauss-Kronrod-Patterson rules.

+ +
+
+ +

◆ getSpgSize()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int getSpgSize (int  getOrderint,
int dim,
int lev 
)
+
+ +

Initial estimate for sparse grid size.

+ +
+
+ +

◆ getTensorProd()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getTensorProd (int dim,
double * qpts,
double * w,
int * spgSize,
int * n1D,
double ** x1D,
double ** w1D,
double qfac 
)
+
+ +

compute dim-dimensional tensor grid based a series of 1D rules

+ +
+
+ +

◆ sortSpg()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void sortSpg (int dim,
int spgSize,
double * qpts,
double * w 
)
+
+ +

Sort sparse grid in lexicographical order.

+ +
+
+

Variable Documentation

+ +

◆ w1

+ +
+
+ + + + + +
+ + + + +
double w1[] = {2.0000000}
+
+static
+
+ +
+
+ +

◆ w15

+ +
+
+ + + + + +
+ + + + +
double w15[]
+
+static
+
+Initial value:
= {0.0170017196299402603390,0.0516032829970797396969,0.0929271953151245376859,
0.134415255243784220360, 0.171511909136391380787, 0.200628529376989021034,
0.219156858401587496404, 0.225510499798206687386, 0.219156858401587496404,
0.200628529376989021034, 0.171511909136391380787, 0.134415255243784220360,
0.0929271953151245376859,0.0516032829970797396969, 0.0170017196299402603390}
+
+
+ +

◆ w3

+ +
+
+ + + + + +
+ + + + +
double w3[] = {0.555555555555555555556,0.888888888888888888889,0.555555555555555555556}
+
+static
+
+ +
+
+ +

◆ w31

+ +
+
+ + + + + +
+ + + + +
double w31[]
+
+static
+
+Initial value:
= {0.00254478079156187441540,0.00843456573932110624631,0.0164460498543878109338,
0.0258075980961766535646, 0.0359571033071293220968, 0.0464628932617579865414,
0.0569795094941233574122, 0.0672077542959907035404, 0.0768796204990035310427,
0.0857559200499903511542, 0.0936271099812644736167, 0.100314278611795578771,
0.105669893580234809744, 0.109578421055924638237, 0.111956873020953456880,
0.112755256720768691607,
0.111956873020953456880, 0.109578421055924638237, 0.105669893580234809744,
0.100314278611795578771, 0.0936271099812644736167, 0.0857559200499903511542,
0.0768796204990035310427, 0.0672077542959907035404, 0.0569795094941233574122,
0.0464628932617579865414, 0.0359571033071293220968, 0.0258075980961766535646,
0.0164460498543878109338, 0.00843456573932110624631,0.00254478079156187441540 }
+
+
+ +

◆ w63

+ +
+
+ + + + + +
+ + + + +
double w63[]
+
+static
+
+Initial value:
= {0.000363221481845530659694,0.00126515655623006801137,0.00257904979468568827243,
0.00421763044155885483908, 0.00611550682211724633968,0.00822300795723592966926,
0.0104982469096213218983, 0.0129038001003512656260, 0.0154067504665594978021,
0.0179785515681282703329, 0.0205942339159127111492, 0.0232314466399102694433,
0.0258696793272147469108, 0.0284897547458335486125, 0.0310735511116879648799,
0.0336038771482077305417, 0.0360644327807825726401, 0.0384398102494555320386,
0.0407155101169443189339, 0.0428779600250077344929, 0.0449145316536321974143,
0.0468135549906280124026, 0.0485643304066731987159, 0.0501571393058995374137,
0.0515832539520484587768, 0.0528349467901165198621, 0.0539054993352660639269,
0.0547892105279628650322, 0.0554814043565593639878, 0.0559784365104763194076,
0.0562776998312543012726, 0.0563776283603847173877, 0.0562776998312543012726,
0.0559784365104763194076, 0.0554814043565593639878, 0.0547892105279628650322,
0.0539054993352660639269, 0.0528349467901165198621, 0.0515832539520484587768,
0.0501571393058995374137, 0.0485643304066731987159, 0.0468135549906280124026,
0.0449145316536321974143, 0.0428779600250077344929, 0.0407155101169443189339,
0.0384398102494555320386, 0.0360644327807825726401, 0.0336038771482077305417,
0.0310735511116879648799, 0.0284897547458335486125, 0.0258696793272147469108,
0.0232314466399102694433, 0.0205942339159127111492, 0.0179785515681282703329,
0.0154067504665594978021, 0.0129038001003512656260, 0.0104982469096213218983,
0.00822300795723592966926, 0.00611550682211724633968,0.00421763044155885483908,
0.00257904979468568827243, 0.00126515655623006801137,0.000363221481845530659694 }
+
+
+ +

◆ w7

+ +
+
+ + + + + +
+ + + + +
double w7[]
+
+static
+
+Initial value:
= { 0.104656226026467265194,0.268488089868333440729,0.401397414775962222905,
0.450916538658474142345,
0.401397414775962222905,0.268488089868333440729,0.104656226026467265194}
+
+
+ +

◆ wn1

+ +
+
+ + + + + +
+ + + + +
double wn1[] = {1.0000000000000000}
+
+static
+
+ +
+
+ +

◆ wn19

+ +
+
+ + + + + +
+ + + + +
double wn19[]
+
+static
+
+Initial value:
= { 8.62968460222986318E-10, 6.09480873146898402E-07, 6.01233694598479965E-05,
0.00288488043650675591, -0.00633722479337375712, 0.0180852342547984622,
0.0640960546868076103, 0.0611517301252477163, 0.208324991649608771,
0.303467199854206227,
0.208324991649608771, 0.0611517301252477163, 0.0640960546868076103,
0.0180852342547984622, -0.00633722479337375712, 0.00288488043650675591,
6.01233694598479965E-05, 6.09480873146898402E-07,8.62968460222986318E-10 }
+
+
+ +

◆ wn3

+ +
+
+ + + + + +
+ + + + +
double wn3[] = {0.166666666666666657, 0.66666666666666663, 0.166666666666666657}
+
+static
+
+ +
+
+ +

◆ wn35

+ +
+
+ + + + + +
+ + + + +
double wn35[]
+
+static
+
+Initial value:
= { 1.05413265823340136E-18, 5.45004126506381281E-15, 3.09722235760629949E-12,
4.60117603486559168E-10, 2.13941944795610622E-08, 2.46764213457981401E-07,
2.73422068011878881E-06, 3.57293481989753322E-05, 0.000275242141167851312,
0.000818953927502267349, 0.00231134524035220713, 0.00315544626918755127,
0.015673473751851151, 0.0452736854651503914, 0.0923647267169863534,
0.148070831155215854, 0.191760115888044341,
0.000514894508069213769,
0.191760115888044341, 0.148070831155215854,
0.0923647267169863534, 0.0452736854651503914, 0.015673473751851151,
0.00315544626918755127, 0.00231134524035220713, 0.000818953927502267349,
0.000275242141167851312, 3.57293481989753322E-05, 2.73422068011878881E-06,
2.46764213457981401E-07, 2.13941944795610622E-08, 4.60117603486559168E-10,
3.09722235760629949E-12, 5.45004126506381281E-15, 1.05413265823340136E-18 }
+
+
+ +

◆ wn9

+ +
+
+ + + + + +
+ + + + +
double wn9[]
+
+static
+
+Initial value:
= { 9.42694575565174701E-05, 0.00799632547089352934, 0.0948509485094851251,
0.270074329577937755, 0.253968253968254065, 0.270074329577937755,
0.0948509485094851251,0.00799632547089352934,9.42694575565174701E-05 }
+
+
+ +

◆ x1

+ +
+
+ + + + + +
+ + + + +
double x1[] = {0.0000000}
+
+static
+
+ +
+
+ +

◆ x15

+ +
+
+ + + + + +
+ + + + +
double x15[]
+
+static
+
+Initial value:
= {-0.99383196321275502221,-0.96049126870802028342,-0.88845923287225699889,
-0.77459666924148337704,-0.62110294673722640294,-0.43424374934680255800,
-0.22338668642896688163, 0.0, 0.22338668642896688163,
0.43424374934680255800, 0.62110294673722640294, 0.77459666924148337704,
0.88845923287225699889, 0.96049126870802028342, 0.99383196321275502221 }
+
+
+ +

◆ x3

+ +
+
+ + + + + +
+ + + + +
double x3[] = {-0.77459666924148337704,0.0, 0.77459666924148337704 }
+
+static
+
+ +
+
+ +

◆ x31

+ +
+
+ + + + + +
+ + + + +
double x31[]
+
+static
+
+Initial value:
= {-0.99909812496766759766,-0.99383196321275502221,-0.98153114955374010687,
-0.96049126870802028342,-0.92965485742974005667,-0.88845923287225699889,
-0.83672593816886873550,-0.77459666924148337704,-0.70249620649152707861,
-0.62110294673722640294,-0.53131974364437562397,-0.43424374934680255800,
-0.33113539325797683309,-0.22338668642896688163,-0.11248894313318662575,
0.0,
0.11248894313318662575, 0.22338668642896688163, 0.33113539325797683309,
0.43424374934680255800, 0.53131974364437562397, 0.62110294673722640294,
0.70249620649152707861, 0.77459666924148337704, 0.83672593816886873550,
0.88845923287225699889, 0.92965485742974005667, 0.96049126870802028342,
0.98153114955374010687, 0.99383196321275502221, 0.99909812496766759766 }
+
+
+ +

◆ x63

+ +
+
+ + + + + +
+ + + + +
double x63[]
+
+static
+
+Initial value:
= {-0.99987288812035761194,-0.99909812496766759766,-0.99720625937222195908,
-0.99383196321275502221,-0.98868475754742947994,-0.98153114955374010687,
-0.97218287474858179658,-0.96049126870802028342,-0.94634285837340290515,
-0.92965485742974005667,-0.91037115695700429250,-0.88845923287225699889,
-0.86390793819369047715,-0.83672593816886873550,-0.80694053195021761186,
-0.77459666924148337704,-0.73975604435269475868,-0.70249620649152707861,
-0.66290966002478059546,-0.62110294673722640294,-0.57719571005204581484,
-0.53131974364437562397,-0.48361802694584102756,-0.43424374934680255800,
-0.38335932419873034692,-0.33113539325797683309,-0.27774982202182431507,
-0.22338668642896688163,-0.16823525155220746498,-0.11248894313318662575,
-0.056344313046592789972,0.0, 0.056344313046592789972,
0.11248894313318662575, 0.16823525155220746498, 0.22338668642896688163,
0.27774982202182431507, 0.33113539325797683309, 0.38335932419873034692,
0.43424374934680255800, 0.48361802694584102756, 0.53131974364437562397,
0.57719571005204581484, 0.62110294673722640294, 0.66290966002478059546,
0.70249620649152707861, 0.73975604435269475868, 0.77459666924148337704,
0.80694053195021761186, 0.83672593816886873550, 0.86390793819369047715,
0.88845923287225699889, 0.91037115695700429250, 0.92965485742974005667,
0.94634285837340290515, 0.96049126870802028342, 0.97218287474858179658,
0.98153114955374010687, 0.98868475754742947994, 0.99383196321275502221,
0.99720625937222195908, 0.99909812496766759766, 0.99987288812035761194 }
+
+
+ +

◆ x7

+ +
+
+ + + + + +
+ + + + +
double x7[]
+
+static
+
+Initial value:
= {-0.96049126870802028342,-0.77459666924148337704,-0.43424374934680255800,
0.0,
0.43424374934680255800, 0.77459666924148337704, 0.96049126870802028342}
+
+
+ +

◆ xn1

+ +
+
+ + + + + +
+ + + + +
double xn1[] = {0.0000000000000000}
+
+static
+
+ +
+
+ +

◆ xn19

+ +
+
+ + + + + +
+ + + + +
double xn19[]
+
+static
+
+Initial value:
= {-6.36339449433636961, -5.18701603991365623, -4.18495601767273229,
-3.20533379449919442, -2.86127957605705818, -2.59608311504920231,
-1.73205080756887719, -1.23042363402730603, -0.741095349994540853,
0.0000000000000000,
0.741095349994540853, 1.23042363402730603, 1.73205080756887719,
2.59608311504920231, 2.86127957605705818, 3.20533379449919442,
4.18495601767273229, 5.18701603991365623, 6.36339449433636961 }
+
+
+ +

◆ xn3

+ +
+
+ + + + + +
+ + + + +
double xn3[] = {-1.73205080756887719, 0.000000000000000000, 1.73205080756887719}
+
+static
+
+ +
+
+ +

◆ xn35

+ +
+
+ + + + + +
+ + + + +
double xn35[]
+
+static
+
+Initial value:
= {-9.0169397898903032, -7.98077179859056063, -7.12210670080461661,
-6.36339449433636961, -5.69817776848810986, -5.18701603991365623,
-4.73643308595229673, -4.18495601767273229, -3.63531851903727832,
-3.20533379449919442, -2.86127957605705818, -2.59608311504920231,
-2.23362606167694189, -1.73205080756887719, -1.23042363402730603,
-0.741095349994540853, -0.248992297579960609,
0.00000000000000000,
0.248992297579960609, 0.741095349994540853,
1.23042363402730603, 1.73205080756887719, 2.23362606167694189,
2.59608311504920231, 2.86127957605705818, 3.20533379449919442,
3.63531851903727832, 4.18495601767273229, 4.73643308595229673,
5.18701603991365623, 5.69817776848810986, 6.36339449433636961,
7.12210670080461661, 7.98077179859056063, 9.0169397898903032 }
+
+
+ +

◆ xn9

+ +
+
+ + + + + +
+ + + + +
double xn9[]
+
+static
+
+Initial value:
= {-4.18495601767273229, -2.86127957605705818, -1.73205080756887719,
-0.741095349994540853, 0.00000000000000000, 0.741095349994540853,
1.73205080756887719, 2.86127957605705818, 4.18495601767273229 }
+
+
+
+ + + + diff --git a/doc/doxygen/html/gkplib_8h.html b/doc/doxygen/html/gkplib_8h.html new file mode 100644 index 00000000..0d130067 --- /dev/null +++ b/doc/doxygen/html/gkplib_8h.html @@ -0,0 +1,642 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gkplib.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gkplib.h File Reference
+
+
+ +

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

void getCC (int n, int *nq, double **x, double **w)
 retrieve pointers to 1D Clenshaw-Curtis rules More...
 
int getOrderCC (int lev)
 get order of Clenshaw-Curtis rules based on level More...
 
void getGKPunif (int n, int *nq, double **x, double **w)
 retrieve pointers to 1D Gauss-Kronrod-Patterson rules for uniform pdf based on the quadrature level More...
 
void getGKPnorm (int n, int *nq, double **x, double **w)
 retrieve pointers to 1D Kronrod-Patterson rules for normal pdf based on the quadrature level More...
 
int getOrderGKPunif (int lev)
 get order of uniform Gauss-Kronrod-Patterson rules based on level More...
 
int getOrderGKPnorm (int lev)
 get order of normal Gauss-Kronrod-Patterson rules based on level More...
 
void getCompNintoDim (int n, int dim, int *nelem, int **plist)
 List of decompositions of 'n' into 'dim' parts. The implementation is based on Algorithm 5 of Combinatorial Algorithms by Albert Nijenhuis, Herbert Wilf. More...
 
int getSpgSize (int getOrder(int), int dim, int lev)
 Initial estimate for sparse grid size. More...
 
void sortSpg (int dim, int spgSize, double *qpts, double *w)
 Sort sparse grid in lexicographical order. More...
 
void getTensorProd (int dim, double *qpts, double *w, int *spgSize, int *n1D, double **x1D, double **w1D, double qfac)
 compute dim-dimensional tensor grid based a series of 1D rules More...
 
void getSpgQW (void get1DQW(int, int *, double **, double **), int getOrder(int), int dim, int lev, int *nqpts, double **qpts, double **w)
 Main function that connects the user setup for pdftype, dimensionality, and quadrature level and various pieces of the sparse quadrature algorithm employing Gauss-Kronrod-Patterson rules. More...
 
void getSpgAnisQW (void get1DQW(int, int *, double **, double **), int getOrder(int), int dim, int *levList, int *nqpts, double **qpts, double **w)
 
void heap_ext_ (const int *, const int *, int *, int *, int *)
 
+

Detailed Description

+

Functions related to Gauss-Kronrod-Patterson sparse quadrature construction

+

Function Documentation

+ +

◆ getCC()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getCC (int n,
int * nq,
double ** x,
double ** w 
)
+
+ +

retrieve pointers to 1D Clenshaw-Curtis rules

+ +
+
+ +

◆ getCompNintoDim()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getCompNintoDim (int n,
int dim,
int * nelem,
int ** plist 
)
+
+ +

List of decompositions of 'n' into 'dim' parts. The implementation is based on Algorithm 5 of Combinatorial Algorithms by Albert Nijenhuis, Herbert Wilf.

+ +
+
+ +

◆ getGKPnorm()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getGKPnorm (int n,
int * nq,
double ** x,
double ** w 
)
+
+ +

retrieve pointers to 1D Kronrod-Patterson rules for normal pdf based on the quadrature level

+ +
+
+ +

◆ getGKPunif()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getGKPunif (int n,
int * nq,
double ** x,
double ** w 
)
+
+ +

retrieve pointers to 1D Gauss-Kronrod-Patterson rules for uniform pdf based on the quadrature level

+ +
+
+ +

◆ getOrderCC()

+ +
+
+ + + + + + + + +
int getOrderCC (int lev)
+
+ +

get order of Clenshaw-Curtis rules based on level

+ +
+
+ +

◆ getOrderGKPnorm()

+ +
+
+ + + + + + + + +
int getOrderGKPnorm (int lev)
+
+ +

get order of normal Gauss-Kronrod-Patterson rules based on level

+ +
+
+ +

◆ getOrderGKPunif()

+ +
+
+ + + + + + + + +
int getOrderGKPunif (int lev)
+
+ +

get order of uniform Gauss-Kronrod-Patterson rules based on level

+ +
+
+ +

◆ getSpgAnisQW()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getSpgAnisQW (void  get1DQWint, int *, double **, double **,
int  getOrderint,
int dim,
int * levList,
int * nqpts,
double ** qpts,
double ** w 
)
+
+ +
+
+ +

◆ getSpgQW()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getSpgQW (void  get1DQWint, int *, double **, double **,
int  getOrderint,
int dim,
int lev,
int * nqpts,
double ** qpts,
double ** w 
)
+
+ +

Main function that connects the user setup for pdftype, dimensionality, and quadrature level and various pieces of the sparse quadrature algorithm employing Gauss-Kronrod-Patterson rules.

+ +
+
+ +

◆ getSpgSize()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int getSpgSize (int  getOrderint,
int dim,
int lev 
)
+
+ +

Initial estimate for sparse grid size.

+ +
+
+ +

◆ getTensorProd()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void getTensorProd (int dim,
double * qpts,
double * w,
int * spgSize,
int * n1D,
double ** x1D,
double ** w1D,
double qfac 
)
+
+ +

compute dim-dimensional tensor grid based a series of 1D rules

+ +
+
+ +

◆ heap_ext_()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void heap_ext_ (const int * ,
const int * ,
int * ,
int * ,
int *  
)
+
+

brief Fortran function for sorting an array of items. The array operations happen outside this function, based on a series of flags passed between the user code and this function. This implementation is based on Algorithm 15 of Combinatorial Algorithms by Albert Nijenhuis, Herbert Wilf

+ +
+
+ +

◆ sortSpg()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void sortSpg (int dim,
int spgSize,
double * qpts,
double * w 
)
+
+ +

Sort sparse grid in lexicographical order.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gkplib_8h_source.html b/doc/doxygen/html/gkplib_8h_source.html new file mode 100644 index 00000000..5e38a80e --- /dev/null +++ b/doc/doxygen/html/gkplib_8h_source.html @@ -0,0 +1,70 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gkplib.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gkplib.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 #ifndef GKPLIB
28 #define GKPLIB
29 
34 void getCC ( int n, int *nq, double **x, double **w );
36 
38 int getOrderCC ( int lev ) ;
39 
42 void getGKPunif ( int n, int *nq, double **x, double **w );
43 
46 void getGKPnorm ( int n, int *nq, double **x, double **w );
47 
49 int getOrderGKPunif ( int lev ) ;
50 
52 int getOrderGKPnorm ( int lev ) ;
53 
57 void getCompNintoDim(int n, int dim, int *nelem, int **plist) ;
58 
60 int getSpgSize ( int getOrder ( int ), int dim, int lev );
61 
63 void sortSpg ( int dim, int spgSize, double *qpts, double *w );
64 
66 void getTensorProd(int dim, double *qpts, double *w, int *spgSize, int *n1D,
67  double **x1D, double **w1D, double qfac);
68 
72 void getSpgQW ( void get1DQW ( int , int *, double **, double** ), int getOrder ( int ),
73  int dim, int lev, int *nqpts, double **qpts, double
74  **w );
75 
76 void getSpgAnisQW ( void get1DQW ( int , int *, double **, double** ), int getOrder ( int ),
77  int dim, int *levList, int *nqpts, double **qpts, double **w ) ;
78 
79 void getCC ( int n, int *nq, double **x, double **w );
80 int getOrderCC ( int lev );
81 
87 extern "C" void heap_ext_(const int *,const int *, int *, int *, int *);
88 
89 #endif
void getGKPunif(int n, int *nq, double **x, double **w)
retrieve pointers to 1D Gauss-Kronrod-Patterson rules for uniform pdf based on the quadrature level ...
Definition: gkpclib.cpp:234
+
void getCC(int n, int *nq, double **x, double **w)
retrieve pointers to 1D Clenshaw-Curtis rules
Definition: gkpclib.cpp:192
+
void sortSpg(int dim, int spgSize, double *qpts, double *w)
Sort sparse grid in lexicographical order.
Definition: gkpclib.cpp:611
+
int getSpgSize(int getOrder(int), int dim, int lev)
Initial estimate for sparse grid size.
Definition: gkpclib.cpp:360
+
void getSpgQW(void get1DQW(int, int *, double **, double **), int getOrder(int), int dim, int lev, int *nqpts, double **qpts, double **w)
Main function that connects the user setup for pdftype, dimensionality, and quadrature level and vari...
Definition: gkpclib.cpp:391
+
void getGKPnorm(int n, int *nq, double **x, double **w)
retrieve pointers to 1D Kronrod-Patterson rules for normal pdf based on the quadrature level ...
Definition: gkpclib.cpp:266
+
void heap_ext_(const int *, const int *, int *, int *, int *)
+
int getOrderGKPnorm(int lev)
get order of normal Gauss-Kronrod-Patterson rules based on level
Definition: gkpclib.cpp:317
+
void getCompNintoDim(int n, int dim, int *nelem, int **plist)
List of decompositions of &#39;n&#39; into &#39;dim&#39; parts. The implementation is based on Algorithm 5 of Combina...
Definition: gkpclib.cpp:330
+
void getSpgAnisQW(void get1DQW(int, int *, double **, double **), int getOrder(int), int dim, int *levList, int *nqpts, double **qpts, double **w)
Definition: gkpclib.cpp:494
+
int getOrderGKPunif(int lev)
get order of uniform Gauss-Kronrod-Patterson rules based on level
Definition: gkpclib.cpp:303
+
void getTensorProd(int dim, double *qpts, double *w, int *spgSize, int *n1D, double **x1D, double **w1D, double qfac)
compute dim-dimensional tensor grid based a series of 1D rules
Definition: gkpclib.cpp:653
+
int getOrderCC(int lev)
get order of Clenshaw-Curtis rules based on level
Definition: gkpclib.cpp:293
+
+ + + + diff --git a/doc/doxygen/html/globals.html b/doc/doxygen/html/globals.html new file mode 100644 index 00000000..e043468d --- /dev/null +++ b/doc/doxygen/html/globals.html @@ -0,0 +1,115 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- a -

+
+ + + + diff --git a/doc/doxygen/html/globals_b.html b/doc/doxygen/html/globals_b.html new file mode 100644 index 00000000..7bb0c9b6 --- /dev/null +++ b/doc/doxygen/html/globals_b.html @@ -0,0 +1,84 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- b -

+
+ + + + diff --git a/doc/doxygen/html/globals_c.html b/doc/doxygen/html/globals_c.html new file mode 100644 index 00000000..0bd27fce --- /dev/null +++ b/doc/doxygen/html/globals_c.html @@ -0,0 +1,116 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- c -

+
+ + + + diff --git a/doc/doxygen/html/globals_d.html b/doc/doxygen/html/globals_d.html new file mode 100644 index 00000000..d063d3c2 --- /dev/null +++ b/doc/doxygen/html/globals_d.html @@ -0,0 +1,133 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- d -

+
+ + + + diff --git a/doc/doxygen/html/globals_defs.html b/doc/doxygen/html/globals_defs.html new file mode 100644 index 00000000..6dc58795 --- /dev/null +++ b/doc/doxygen/html/globals_defs.html @@ -0,0 +1,381 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- a -

+ + +

- b -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- i -

+ + +

- l -

+ + +

- m -

+ + +

- n -

+ + +

- o -

+ + +

- p -

+ + +

- q -

+ + +

- r -

+ + +

- s -

+ + +

- v -

+ + +

- x -

+ + +

- y -

+
+ + + + diff --git a/doc/doxygen/html/globals_e.html b/doc/doxygen/html/globals_e.html new file mode 100644 index 00000000..3369c28d --- /dev/null +++ b/doc/doxygen/html/globals_e.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- e -

+
+ + + + diff --git a/doc/doxygen/html/globals_enum.html b/doc/doxygen/html/globals_enum.html new file mode 100644 index 00000000..b3af4528 --- /dev/null +++ b/doc/doxygen/html/globals_enum.html @@ -0,0 +1,54 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+ + + + diff --git a/doc/doxygen/html/globals_eval.html b/doc/doxygen/html/globals_eval.html new file mode 100644 index 00000000..95167d37 --- /dev/null +++ b/doc/doxygen/html/globals_eval.html @@ -0,0 +1,57 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+ + + + diff --git a/doc/doxygen/html/globals_f.html b/doc/doxygen/html/globals_f.html new file mode 100644 index 00000000..a69de9e7 --- /dev/null +++ b/doc/doxygen/html/globals_f.html @@ -0,0 +1,164 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- f -

+
+ + + + diff --git a/doc/doxygen/html/globals_func.html b/doc/doxygen/html/globals_func.html new file mode 100644 index 00000000..04d3a9f3 --- /dev/null +++ b/doc/doxygen/html/globals_func.html @@ -0,0 +1,113 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- a -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_b.html b/doc/doxygen/html/globals_func_b.html new file mode 100644 index 00000000..4b4b680b --- /dev/null +++ b/doc/doxygen/html/globals_func_b.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- b -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_c.html b/doc/doxygen/html/globals_func_c.html new file mode 100644 index 00000000..1e6eb917 --- /dev/null +++ b/doc/doxygen/html/globals_func_c.html @@ -0,0 +1,106 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- c -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_d.html b/doc/doxygen/html/globals_func_d.html new file mode 100644 index 00000000..9a5884ab --- /dev/null +++ b/doc/doxygen/html/globals_func_d.html @@ -0,0 +1,108 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- d -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_e.html b/doc/doxygen/html/globals_func_e.html new file mode 100644 index 00000000..3631d6b4 --- /dev/null +++ b/doc/doxygen/html/globals_func_e.html @@ -0,0 +1,61 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- e -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_f.html b/doc/doxygen/html/globals_func_f.html new file mode 100644 index 00000000..317bb9d9 --- /dev/null +++ b/doc/doxygen/html/globals_func_f.html @@ -0,0 +1,150 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- f -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_g.html b/doc/doxygen/html/globals_func_g.html new file mode 100644 index 00000000..a47fea5e --- /dev/null +++ b/doc/doxygen/html/globals_func_g.html @@ -0,0 +1,201 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- g -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_h.html b/doc/doxygen/html/globals_func_h.html new file mode 100644 index 00000000..f172ea5a --- /dev/null +++ b/doc/doxygen/html/globals_func_h.html @@ -0,0 +1,63 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- h -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_i.html b/doc/doxygen/html/globals_func_i.html new file mode 100644 index 00000000..900480ae --- /dev/null +++ b/doc/doxygen/html/globals_func_i.html @@ -0,0 +1,103 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- i -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_j.html b/doc/doxygen/html/globals_func_j.html new file mode 100644 index 00000000..da9756d7 --- /dev/null +++ b/doc/doxygen/html/globals_func_j.html @@ -0,0 +1,59 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- j -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_l.html b/doc/doxygen/html/globals_func_l.html new file mode 100644 index 00000000..3a77a6f4 --- /dev/null +++ b/doc/doxygen/html/globals_func_l.html @@ -0,0 +1,86 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- l -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_m.html b/doc/doxygen/html/globals_func_m.html new file mode 100644 index 00000000..b1c375c6 --- /dev/null +++ b/doc/doxygen/html/globals_func_m.html @@ -0,0 +1,123 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- m -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_n.html b/doc/doxygen/html/globals_func_n.html new file mode 100644 index 00000000..d353e8d9 --- /dev/null +++ b/doc/doxygen/html/globals_func_n.html @@ -0,0 +1,74 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- n -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_p.html b/doc/doxygen/html/globals_func_p.html new file mode 100644 index 00000000..9f8bfe8b --- /dev/null +++ b/doc/doxygen/html/globals_func_p.html @@ -0,0 +1,101 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- p -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_q.html b/doc/doxygen/html/globals_func_q.html new file mode 100644 index 00000000..2ac0bc4f --- /dev/null +++ b/doc/doxygen/html/globals_func_q.html @@ -0,0 +1,62 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- q -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_r.html b/doc/doxygen/html/globals_func_r.html new file mode 100644 index 00000000..16c9c750 --- /dev/null +++ b/doc/doxygen/html/globals_func_r.html @@ -0,0 +1,83 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- r -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_s.html b/doc/doxygen/html/globals_func_s.html new file mode 100644 index 00000000..c66efb21 --- /dev/null +++ b/doc/doxygen/html/globals_func_s.html @@ -0,0 +1,131 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- s -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_t.html b/doc/doxygen/html/globals_func_t.html new file mode 100644 index 00000000..b30c9e81 --- /dev/null +++ b/doc/doxygen/html/globals_func_t.html @@ -0,0 +1,77 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- t -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_u.html b/doc/doxygen/html/globals_func_u.html new file mode 100644 index 00000000..2b6cf2f4 --- /dev/null +++ b/doc/doxygen/html/globals_func_u.html @@ -0,0 +1,72 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ + + + + diff --git a/doc/doxygen/html/globals_func_v.html b/doc/doxygen/html/globals_func_v.html new file mode 100644 index 00000000..d8de442a --- /dev/null +++ b/doc/doxygen/html/globals_func_v.html @@ -0,0 +1,61 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- v -

+
+ + + + diff --git a/doc/doxygen/html/globals_func_w.html b/doc/doxygen/html/globals_func_w.html new file mode 100644 index 00000000..5235efc7 --- /dev/null +++ b/doc/doxygen/html/globals_func_w.html @@ -0,0 +1,73 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+  + +

- w -

+
+ + + + diff --git a/doc/doxygen/html/globals_g.html b/doc/doxygen/html/globals_g.html new file mode 100644 index 00000000..f1416833 --- /dev/null +++ b/doc/doxygen/html/globals_g.html @@ -0,0 +1,207 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- g -

+
+ + + + diff --git a/doc/doxygen/html/globals_h.html b/doc/doxygen/html/globals_h.html new file mode 100644 index 00000000..96322b01 --- /dev/null +++ b/doc/doxygen/html/globals_h.html @@ -0,0 +1,63 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- h -

+
+ + + + diff --git a/doc/doxygen/html/globals_i.html b/doc/doxygen/html/globals_i.html new file mode 100644 index 00000000..8baff5ba --- /dev/null +++ b/doc/doxygen/html/globals_i.html @@ -0,0 +1,109 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- i -

+
+ + + + diff --git a/doc/doxygen/html/globals_j.html b/doc/doxygen/html/globals_j.html new file mode 100644 index 00000000..9bd50f4d --- /dev/null +++ b/doc/doxygen/html/globals_j.html @@ -0,0 +1,59 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- j -

+
+ + + + diff --git a/doc/doxygen/html/globals_l.html b/doc/doxygen/html/globals_l.html new file mode 100644 index 00000000..d363a4f1 --- /dev/null +++ b/doc/doxygen/html/globals_l.html @@ -0,0 +1,98 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- l -

+
+ + + + diff --git a/doc/doxygen/html/globals_m.html b/doc/doxygen/html/globals_m.html new file mode 100644 index 00000000..21625e4f --- /dev/null +++ b/doc/doxygen/html/globals_m.html @@ -0,0 +1,157 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- m -

+
+ + + + diff --git a/doc/doxygen/html/globals_n.html b/doc/doxygen/html/globals_n.html new file mode 100644 index 00000000..129b504d --- /dev/null +++ b/doc/doxygen/html/globals_n.html @@ -0,0 +1,95 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- n -

+
+ + + + diff --git a/doc/doxygen/html/globals_o.html b/doc/doxygen/html/globals_o.html new file mode 100644 index 00000000..0d8a4df0 --- /dev/null +++ b/doc/doxygen/html/globals_o.html @@ -0,0 +1,61 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- o -

+
+ + + + diff --git a/doc/doxygen/html/globals_p.html b/doc/doxygen/html/globals_p.html new file mode 100644 index 00000000..cf25a996 --- /dev/null +++ b/doc/doxygen/html/globals_p.html @@ -0,0 +1,139 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- p -

+
+ + + + diff --git a/doc/doxygen/html/globals_q.html b/doc/doxygen/html/globals_q.html new file mode 100644 index 00000000..6e8a6dde --- /dev/null +++ b/doc/doxygen/html/globals_q.html @@ -0,0 +1,67 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- q -

+
+ + + + diff --git a/doc/doxygen/html/globals_r.html b/doc/doxygen/html/globals_r.html new file mode 100644 index 00000000..10f6f4f0 --- /dev/null +++ b/doc/doxygen/html/globals_r.html @@ -0,0 +1,84 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- r -

+
+ + + + diff --git a/doc/doxygen/html/globals_s.html b/doc/doxygen/html/globals_s.html new file mode 100644 index 00000000..376abb1f --- /dev/null +++ b/doc/doxygen/html/globals_s.html @@ -0,0 +1,154 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- s -

+
+ + + + diff --git a/doc/doxygen/html/globals_t.html b/doc/doxygen/html/globals_t.html new file mode 100644 index 00000000..8c2e960a --- /dev/null +++ b/doc/doxygen/html/globals_t.html @@ -0,0 +1,79 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- t -

+
+ + + + diff --git a/doc/doxygen/html/globals_u.html b/doc/doxygen/html/globals_u.html new file mode 100644 index 00000000..be207bc1 --- /dev/null +++ b/doc/doxygen/html/globals_u.html @@ -0,0 +1,72 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- u -

+
+ + + + diff --git a/doc/doxygen/html/globals_v.html b/doc/doxygen/html/globals_v.html new file mode 100644 index 00000000..0853b24a --- /dev/null +++ b/doc/doxygen/html/globals_v.html @@ -0,0 +1,69 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- v -

+
+ + + + diff --git a/doc/doxygen/html/globals_vars.html b/doc/doxygen/html/globals_vars.html new file mode 100644 index 00000000..d69b5967 --- /dev/null +++ b/doc/doxygen/html/globals_vars.html @@ -0,0 +1,117 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+ + + + diff --git a/doc/doxygen/html/globals_w.html b/doc/doxygen/html/globals_w.html new file mode 100644 index 00000000..1f837ea0 --- /dev/null +++ b/doc/doxygen/html/globals_w.html @@ -0,0 +1,106 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- w -

+
+ + + + diff --git a/doc/doxygen/html/globals_x.html b/doc/doxygen/html/globals_x.html new file mode 100644 index 00000000..144999e5 --- /dev/null +++ b/doc/doxygen/html/globals_x.html @@ -0,0 +1,91 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- x -

+
+ + + + diff --git a/doc/doxygen/html/globals_y.html b/doc/doxygen/html/globals_y.html new file mode 100644 index 00000000..5d1ab45b --- /dev/null +++ b/doc/doxygen/html/globals_y.html @@ -0,0 +1,58 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: File Members + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
Here is a list of all file members with links to the files they belong to:
+ +

- y -

+
+ + + + diff --git a/doc/doxygen/html/gp__regr_8cpp.html b/doc/doxygen/html/gp__regr_8cpp.html new file mode 100644 index 00000000..0f407628 --- /dev/null +++ b/doc/doxygen/html/gp__regr_8cpp.html @@ -0,0 +1,243 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gp_regr.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gp_regr.cpp File Reference
+
+
+ +

Command-line utility for Gaussian Process regression. +More...

+
#include <iostream>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+#include <string>
+#include "Array1D.h"
+#include "Array2D.h"
+#include "PCSet.h"
+#include "error_handlers.h"
+#include "ftndefs.h"
+#include "gen_defs.h"
+#include "assert.h"
+#include "quad.h"
+#include "gproc.h"
+#include "arrayio.h"
+#include "tools.h"
+#include "arraytools.h"
+#include "dsfmt_add.h"
+
+ + + + + + + + + + + + + +

+Macros

#define XFILE   "xdata.dat"
 default x-file More...
 
#define YFILE   "ydata.dat"
 default y-file More...
 
#define MSC   "ms"
 default flag to output mean (m), mean+std (ms) or mean+std+cov (msc) More...
 
#define ORD   3
 default PC order More...
 
+ + + + + + + +

+Functions

int usage ()
 Displays information about this program. More...
 
int main (int argc, char *argv[])
 Main program of building Gaussian Process response surface. More...
 
+

Detailed Description

+

Command-line utility for Gaussian Process regression.

+
Author
K. Sargsyan 2015 -
+

Macro Definition Documentation

+ +

◆ MSC

+ +
+
+ + + + +
#define MSC   "ms"
+
+ +

default flag to output mean (m), mean+std (ms) or mean+std+cov (msc)

+ +
+
+ +

◆ ORD

+ +
+
+ + + + +
#define ORD   3
+
+ +

default PC order

+ +
+
+ +

◆ XFILE

+ +
+
+ + + + +
#define XFILE   "xdata.dat"
+
+ +

default x-file

+ +
+
+ +

◆ YFILE

+ +
+
+ + + + +
#define YFILE   "ydata.dat"
+
+ +

default y-file

+ +
+
+

Function Documentation

+ +

◆ main()

+ +
+
+ + + + + + + + + + + + + + + + + + +
int main (int argc,
char * argv[] 
)
+
+ +

Main program of building Gaussian Process response surface.

+

Set the default values

+

Read the user input

+

Sanity checks

+

Print the input information on screen

+

Read data

+

Set or read data variance

+

Read validation check data, if any

+

Set the correlation parameters

+

Set the PC trend

+

Initialize a GP object

+

Print out the roughness param

+

Sanity check to ensure the regression is well-defined

+

Build the GP

+

Evaluate the GP (actually, a Student-t process, see the UQTk Manual)

+

Write the mean

+

If asked, compute and write standard deviation and covariance of the Student-t process

+

Print out output information

+ +
+
+ +

◆ usage()

+ +
+
+ + + + + + + +
int usage ()
+
+ +

Displays information about this program.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gproc_8cpp.html b/doc/doxygen/html/gproc_8cpp.html new file mode 100644 index 00000000..c26af0ce --- /dev/null +++ b/doc/doxygen/html/gproc_8cpp.html @@ -0,0 +1,118 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gproc.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gproc.cpp File Reference
+
+
+ +

Gaussian Process class. +More...

+
#include <math.h>
+#include <cfloat>
+#include <iostream>
+#include "gproc.h"
+#include "error_handlers.h"
+#include "gen_defs.h"
+#include "arraytools.h"
+#include "arrayio.h"
+#include "tools.h"
+#include "lbfgs_routines.h"
+#include <assert.h>
+
+ + + +

+Functions

double neglogPostParam (int ndim, double *m, void *classpointer)
 
+

Detailed Description

+

Gaussian Process class.

+
Author
K. Sargsyan 2014 -
+

Function Documentation

+ +

◆ neglogPostParam()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double neglogPostParam (int ndim,
double * m,
void * classpointer 
)
+
+

Function to compute negative log posterior (needed to maximize with respect to roughness parameter)

Todo:
Find a more elegant way to do this within the class
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gproc_8h.html b/doc/doxygen/html/gproc_8h.html new file mode 100644 index 00000000..a126c5f5 --- /dev/null +++ b/doc/doxygen/html/gproc_8h.html @@ -0,0 +1,77 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gproc.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gproc.h File Reference
+
+
+ +

Header file for Gaussian Process class. +More...

+
#include "Array1D.h"
+#include "Array2D.h"
+#include "PCSet.h"
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  Gproc
 Class for Gaussian processes. More...
 
+

Detailed Description

+

Header file for Gaussian Process class.

+
Author
K. Sargsyan 2014 -
+
+ + + + diff --git a/doc/doxygen/html/gproc_8h_source.html b/doc/doxygen/html/gproc_8h_source.html new file mode 100644 index 00000000..14d8e5f9 --- /dev/null +++ b/doc/doxygen/html/gproc_8h_source.html @@ -0,0 +1,122 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gproc.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gproc.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
30 
31 #ifndef GPROC_H_SEEN
32 #define GPROC_H_SEEN
33 
34 #include "Array1D.h"
35 #include "Array2D.h"
36 #include "PCSet.h"
37 
40 class Gproc {
41 public:
42 
45  Gproc(const string covtype, PCSet *PCModel, Array1D<double>& param);
47  ~Gproc() {};
48 
50  void SetupPrior();
52  void SetupData(Array2D<double>& xdata, Array1D<double>& ydata,Array1D<double>& datavar);
54  void setCorrParam(Array1D<double> param){param_=param; return;}
55 
58  void BuildGP();
63  void BuildGP_inv();
66  void EvalGP(Array2D<double>& xgrid, string msc, Array1D<double>& mst);
71  void EvalGP_inv(Array2D<double>& xgrid, string msc, Array1D<double>& mst);
73  int getNpt() const {return npt_;}
75  int getNdim() const {return ndim_;}
77  int getNPC() const {return npc_;}
79  double getAl() const {return al_;}
81  double getBe() const {return be_;}
83  double getSig2hat() const {return sig2hat_;}
85  void getVst(Array2D<double>& vst) {vst=Vst_; return;}
87  void getA(Array2D<double>& acor) {acor=A_; return;}
89  void getParam(Array1D<double>& param) {param=param_; return;}
91  void getCov(Array2D<double>& cov) {cov=cov_;}
93  void getVar(Array1D<double>& var) {var=var_;}
95  void getXYCov(Array2D<double>& xgrid,Array2D<double>& xycov);
97  void getSttPars(Array1D<double>& sttmat);
99  void findBestCorrParam();
100 
101 
102  private:
103 
108 
115 
117  int npc_;
122  //double sig2f_;
124  double al_;
126  double be_;
128  double sig2hat_;
129 
131  int npt_;
133  int ndim_;
135  string covType_;
138 
147 
164 
165 
166 };
167 #endif /* GPROC_H_SEEN */
Array1D< double > dataVar_
Data noise &#39;nugget&#39;.
Definition: gproc.h:114
+
Array2D< double > A_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:151
+
string covType_
Covariance type, only &#39;SqExp&#39; implemented so far.
Definition: gproc.h:135
+
Array1D< double > mst_
Mean of the Student-t posterior.
Definition: gproc.h:140
+
Array1D< double > bhat_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:158
+
Defines and initializes PC basis function set and provides functions to manipulate PC expansions defi...
Definition: PCSet.h:67
+
Header file for the Multivariate PC class.
+
Array2D< double > Ht_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:150
+
Array2D< double > AinvH_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:155
+
void SetupPrior()
Setup the prior.
Definition: gproc.cpp:67
+
Array1D< double > Vinvz_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:153
+
void getSttPars(Array1D< double > &sttmat)
Get the Student-t parameters.
Definition: gproc.cpp:417
+
void computeDataCov_(Array2D< double > &xdata, Array1D< double > &param, Array2D< double > &A)
Compute the data covariance .
Definition: gproc.cpp:488
+
double getBe() const
Get beta parameter.
Definition: gproc.h:81
+
Gproc(const string covtype, PCSet *PCModel, Array1D< double > &param)
Constructor: initialize with covariance type, trend function basis and roughness parameter vector...
Definition: gproc.cpp:51
+
Array1D< double > HtAinvd_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:154
+
void EvalGP_inv(Array2D< double > &xgrid, string msc, Array1D< double > &mst)
Evaluate the Gaussian Process at a given grid msc controls whether only mean will be computed...
Definition: gproc.cpp:327
+
int getNpt() const
Get the number of data points.
Definition: gproc.h:73
+
void findBestCorrParam()
Function to find the best values for roughness parameters.
Definition: gproc.cpp:510
+
void BuildGP_inv()
Build Gaussian Process regressor, i.e. compute internally all necessary matrices and vectors that des...
Definition: gproc.cpp:154
+
Array1D< double > ydata_
ydata array
Definition: gproc.h:112
+
void SetupData(Array2D< double > &xdata, Array1D< double > &ydata, Array1D< double > &datavar)
Setup the data.
Definition: gproc.cpp:86
+
int getNdim() const
Get the dimensionality.
Definition: gproc.h:75
+
Array2D< double > xdata_
xdata array
Definition: gproc.h:110
+
Definition: Array1D.h:471
+
Array1D< double > var_
Variance of the Student-t posterior.
Definition: gproc.h:142
+
Array1D< double > z_
Prior mean of the mean trend.
Definition: gproc.h:121
+
Array2D< double > Ainv_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:151
+
double sig2hat_
Posterior variance factor.
Definition: gproc.h:128
+
int npt_
Number of data points.
Definition: gproc.h:131
+
Array2D< double > cov_
Covariance of the Student-t posterior.
Definition: gproc.h:144
+ +
double be_
Prior parameter .
Definition: gproc.h:126
+
2D Array class for any type T
+
PCSet * PCModel_
Basis set for the trend function.
Definition: gproc.h:137
+
void EvalGP(Array2D< double > &xgrid, string msc, Array1D< double > &mst)
Evaluate the Gaussian Process at a given grid msc controls whether only mean will be computed...
Definition: gproc.cpp:204
+
~Gproc()
Destructor: cleans up all memory and destroys object.
Definition: gproc.h:47
+
static double x1[]
Definition: gkpclib.cpp:35
+
double al_
Prior parameter .
Definition: gproc.h:124
+
Array1D< double > param_
Roughness parameter vector.
Definition: gproc.h:146
+
int getNPC() const
Get the number of basis terms in the trend.
Definition: gproc.h:77
+
int npc_
Number of bases in the mean trend.
Definition: gproc.h:117
+
void getXYCov(Array2D< double > &xgrid, Array2D< double > &xycov)
Get the covariance in a different format, with the x,x&#39; values.
Definition: gproc.cpp:434
+
double covariance(Array1D< double > &x1, Array1D< double > &x2, Array1D< double > &param)
Prior covariance function.
Definition: gproc.cpp:459
+
void getA(Array2D< double > &acor)
Get the correlation matrix .
Definition: gproc.h:87
+
void getParam(Array1D< double > &param)
Get the roughness parameters.
Definition: gproc.h:89
+
Class for Gaussian processes.
Definition: gproc.h:40
+
Array1D< double > Hbhat_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:159
+
Array1D< double > yHbhat_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:160
+
void getVar(Array1D< double > &var)
Get the posterior variance vector.
Definition: gproc.h:93
+
void getVst(Array2D< double > &vst)
Get , an auxiliary matrix.
Definition: gproc.h:85
+
void getCov(Array2D< double > &cov)
Get the posterior covariance matrix.
Definition: gproc.h:91
+
void setCorrParam(Array1D< double > param)
Set the roughness parameter vector.
Definition: gproc.h:54
+
int ndim_
Dimensionality.
Definition: gproc.h:133
+
Array2D< double > Vinv_
Inverse of the mean trend coefficient prior covariance.
Definition: gproc.h:119
+
Array1D< double > Ainvd_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:152
+
Array2D< double > Vst_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:157
+
void BuildGP()
Build Gaussian Process regressor, i.e. compute internally all necessary matrices and vectors that des...
Definition: gproc.cpp:98
+
Array1D< double > AinvyHbhat_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:161
+
Array2D< double > HtAinvH_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:156
+
Array2D< double > Vstinv_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:162
+
1D Array class for any type T
+
double getSig2hat() const
Get Sigma-hat-squared, i.e. the posterior variance factor.
Definition: gproc.h:83
+
double getAl() const
Get alpha parameter.
Definition: gproc.h:79
+
Array2D< double > H_
Auxiliary matrices or vectors, see the UQTk Manual.
Definition: gproc.h:150
+
+ + + + diff --git a/doc/doxygen/html/gq_8cpp.html b/doc/doxygen/html/gq_8cpp.html new file mode 100644 index 00000000..14dcb4b5 --- /dev/null +++ b/doc/doxygen/html/gq_8cpp.html @@ -0,0 +1,620 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gq.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gq.cpp File Reference
+
+
+ +

Utilities to generate quadrature rules. +More...

+
#include "stdio.h"
+#include "stdlib.h"
+#include <iostream>
+#include <cmath>
+#include "Array1D.h"
+#include "Array2D.h"
+#include "deplapack.h"
+#include "gq.h"
+#include "combin.h"
+
+ + + +

+Macros

#define DPI   3.14159265358979323846
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

double lpol_gq (int n, double x)
 
double hpol_gq (int n, double x)
 
double hpol_phys_gq (int n, double x)
 
double jpol_gq (int n, double a, double b, double x)
 
double jpolp_gq (int n, double a, double b, double x)
 
double lgpol_gq (int n, double a, double x)
 
double fact_gq (int n)
 
void gq (const int kind, const double a, const double b, Array1D< double > &x, Array1D< double > &w)
 Computes abscissas and weights for several quadrature rules. More...
 
void gq (const int kind, const int n, const double a, const double b, double *x, double *w)
 Computes abscissas and weights for several quadrature rules. More...
 
void gchb (const int kind, const int n, double *x, double *w)
 Computes abscissas and weights for Chebyshev quadrature rules. More...
 
void gq_gen (Array1D< double > &a, Array1D< double > &b, const double amu0, Array1D< double > &x, Array1D< double > &w)
 Computes abscissas and weights for a generic orthogonal polynomial recursion using the Golub-Welsch algorithm. More...
 
void vandermonde_gq (Array1D< double > &x, Array1D< double > &w, Array1D< double > &q)
 Computes abscissas and weights for Newton-Cotes rules through the solution of a Vandermonde matrix. This function was tested as an internal function only, called by the quadrature class. More...
 
+

Detailed Description

+

Utilities to generate quadrature rules.

+

Macro Definition Documentation

+ +

◆ DPI

+ +
+
+ + + + +
#define DPI   3.14159265358979323846
+
+ +
+
+

Function Documentation

+ +

◆ fact_gq()

+ +
+
+ + + + + + + + +
double fact_gq (int n)
+
+ +
+
+ +

◆ gchb()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gchb (const int kind,
const int n,
double * x,
double * w 
)
+
+ +

Computes abscissas and weights for Chebyshev quadrature rules.

+
Parameters
+ + + + + +
kind: defines quadrature type (1) Gauss-Chebyshev 1st kind (2) Gauss-Chebyshev 2nd kind
n: quadrature order
x: on return it holds quadrature abscissas.
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ gq() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gq (const int kind,
const double a,
const double b,
Array1D< double > & x,
Array1D< double > & w 
)
+
+ +

Computes abscissas and weights for several quadrature rules.

+
Parameters
+ + + + + + +
kind: defines quadrature type (1) Gauss-Legendre, (2) Gauss-Chebyshev 1st kind (3) Gauss-Chebyshev 2nd kind, (4) Gauss-Hermite, (5) Gauss-Jacobi (6) Gauss-Laguerre
a: optional parameter needed by Gauss-Jacobi and Gauss-Laguerre rules
b: optional parameter needed by Gauss-Jacobi rule
x: on return it holds quadrature abscissas. Its initial size determines the quadrature order
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ gq() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gq (const int kind,
const int n,
const double a,
const double b,
double * x,
double * w 
)
+
+ +

Computes abscissas and weights for several quadrature rules.

+
Parameters
+ + + + + + + +
kind: defines quadrature type (1) Gauss-Legendre, (2) Gauss-Chebyshev 1st kind (3) Gauss-Chebyshev 2nd kind, (4) Gauss-Hermite, (5) Gauss-Jacobi (6) Gauss-Laguerre
n: quadrature order
a: optional parameter needed by Gauss-Jacobi and Gauss-Laguerre rules
b: optional parameter needed by Gauss-Jacobi rule
x: on return it holds quadrature abscissas.
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ gq_gen()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gq_gen (Array1D< double > & a,
Array1D< double > & b,
const double amu0,
Array1D< double > & x,
Array1D< double > & w 
)
+
+ +

Computes abscissas and weights for a generic orthogonal polynomial recursion using the Golub-Welsch algorithm.

+
Parameters
+ + + + + + +
a: array of parameters for the orthogonal polynomial recursion. Its initial size determines the quadrature order
b: array of parameters for the orthogonal polynomial recursion
amu0: parameter for custom scaling of quadrature weights
x: on return it holds quadrature abscissas
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ hpol_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double hpol_gq (int n,
double x 
)
+
+ +
+
+ +

◆ hpol_phys_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double hpol_phys_gq (int n,
double x 
)
+
+ +
+
+ +

◆ jpol_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
double jpol_gq (int n,
double a,
double b,
double x 
)
+
+ +
+
+ +

◆ jpolp_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
double jpolp_gq (int n,
double a,
double b,
double x 
)
+
+ +
+
+ +

◆ lgpol_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
double lgpol_gq (int n,
double a,
double x 
)
+
+ +
+
+ +

◆ lpol_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double lpol_gq (int n,
double x 
)
+
+ +
+
+ +

◆ vandermonde_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void vandermonde_gq (Array1D< double > & x,
Array1D< double > & w,
Array1D< double > & q 
)
+
+ +

Computes abscissas and weights for Newton-Cotes rules through the solution of a Vandermonde matrix. This function was tested as an internal function only, called by the quadrature class.

+
Parameters
+ + + + +
x: holds quadrature abscissas
w: on return it holds quadrature weights.
q: array of parameters needed to setup the Vandermonde matrix
+
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gq_8h.html b/doc/doxygen/html/gq_8h.html new file mode 100644 index 00000000..fb1fa0d6 --- /dev/null +++ b/doc/doxygen/html/gq_8h.html @@ -0,0 +1,362 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gq.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
gq.h File Reference
+
+
+ +

Header for quadrature generation utilities. +More...

+ +

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + +

+Functions

void gq (const int kind, const double a, const double b, Array1D< double > &x, Array1D< double > &w)
 Computes abscissas and weights for several quadrature rules. More...
 
void gq (const int kind, const int n, const double a, const double b, double *x, double *w)
 Computes abscissas and weights for several quadrature rules. More...
 
void gq_gen (Array1D< double > &a, Array1D< double > &b, const double amu0, Array1D< double > &x, Array1D< double > &w)
 Computes abscissas and weights for a generic orthogonal polynomial recursion using the Golub-Welsch algorithm. More...
 
void vandermonde_gq (Array1D< double > &x, Array1D< double > &w, Array1D< double > &q)
 Computes abscissas and weights for Newton-Cotes rules through the solution of a Vandermonde matrix. This function was tested as an internal function only, called by the quadrature class. More...
 
void gchb (const int kind, const int n, double *x, double *w)
 Computes abscissas and weights for Chebyshev quadrature rules. More...
 
+

Detailed Description

+

Header for quadrature generation utilities.

+

Function Documentation

+ +

◆ gchb()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gchb (const int kind,
const int n,
double * x,
double * w 
)
+
+ +

Computes abscissas and weights for Chebyshev quadrature rules.

+
Parameters
+ + + + + +
kind: defines quadrature type (1) Gauss-Chebyshev 1st kind (2) Gauss-Chebyshev 2nd kind
n: quadrature order
x: on return it holds quadrature abscissas.
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ gq() [1/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gq (const int kind,
const double a,
const double b,
Array1D< double > & x,
Array1D< double > & w 
)
+
+ +

Computes abscissas and weights for several quadrature rules.

+
Parameters
+ + + + + + +
kind: defines quadrature type (1) Gauss-Legendre, (2) Gauss-Chebyshev 1st kind (3) Gauss-Chebyshev 2nd kind, (4) Gauss-Hermite, (5) Gauss-Jacobi (6) Gauss-Laguerre
a: optional parameter needed by Gauss-Jacobi and Gauss-Laguerre rules
b: optional parameter needed by Gauss-Jacobi rule
x: on return it holds quadrature abscissas. Its initial size determines the quadrature order
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ gq() [2/2]

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gq (const int kind,
const int n,
const double a,
const double b,
double * x,
double * w 
)
+
+ +

Computes abscissas and weights for several quadrature rules.

+
Parameters
+ + + + + + + +
kind: defines quadrature type (1) Gauss-Legendre, (2) Gauss-Chebyshev 1st kind (3) Gauss-Chebyshev 2nd kind, (4) Gauss-Hermite, (5) Gauss-Jacobi (6) Gauss-Laguerre
n: quadrature order
a: optional parameter needed by Gauss-Jacobi and Gauss-Laguerre rules
b: optional parameter needed by Gauss-Jacobi rule
x: on return it holds quadrature abscissas.
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ gq_gen()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void gq_gen (Array1D< double > & a,
Array1D< double > & b,
const double amu0,
Array1D< double > & x,
Array1D< double > & w 
)
+
+ +

Computes abscissas and weights for a generic orthogonal polynomial recursion using the Golub-Welsch algorithm.

+
Parameters
+ + + + + + +
a: array of parameters for the orthogonal polynomial recursion. Its initial size determines the quadrature order
b: array of parameters for the orthogonal polynomial recursion
amu0: parameter for custom scaling of quadrature weights
x: on return it holds quadrature abscissas
w: on return it holds quadrature weights.
+
+
+ +
+
+ +

◆ vandermonde_gq()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void vandermonde_gq (Array1D< double > & x,
Array1D< double > & w,
Array1D< double > & q 
)
+
+ +

Computes abscissas and weights for Newton-Cotes rules through the solution of a Vandermonde matrix. This function was tested as an internal function only, called by the quadrature class.

+
Parameters
+ + + + +
x: holds quadrature abscissas
w: on return it holds quadrature weights.
q: array of parameters needed to setup the Vandermonde matrix
+
+
+ +
+
+
+ + + + diff --git a/doc/doxygen/html/gq_8h_source.html b/doc/doxygen/html/gq_8h_source.html new file mode 100644 index 00000000..ade85c97 --- /dev/null +++ b/doc/doxygen/html/gq_8h_source.html @@ -0,0 +1,62 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: gq.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
gq.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
27 #ifndef GQ_H
28 #define GQ_H
29 
47 void gq ( const int kind, const double a, const double b, Array1D<double> &x, Array1D<double> &w ) ;
48 
62 void gq ( const int kind, const int n, const double a, const double b, double *x, double *w ) ;
63 
76 void gq_gen(Array1D<double> &a, Array1D<double> &b, const double amu0,
78 
79 
91 
102 void gchb(const int kind, const int n, double *x, double *w ) ;
103 
104 #endif
void gq(const int kind, const double a, const double b, Array1D< double > &x, Array1D< double > &w)
Computes abscissas and weights for several quadrature rules.
Definition: gq.cpp:65
+
Definition: Array1D.h:471
+
void gchb(const int kind, const int n, double *x, double *w)
Computes abscissas and weights for Chebyshev quadrature rules.
Definition: gq.cpp:212
+
void vandermonde_gq(Array1D< double > &x, Array1D< double > &w, Array1D< double > &q)
Computes abscissas and weights for Newton-Cotes rules through the solution of a Vandermonde matrix...
Definition: gq.cpp:284
+
void gq_gen(Array1D< double > &a, Array1D< double > &b, const double amu0, Array1D< double > &x, Array1D< double > &w)
Computes abscissas and weights for a generic orthogonal polynomial recursion using the Golub-Welsch a...
Definition: gq.cpp:251
+
+ + + + diff --git a/doc/doxygen/html/hierarchy.html b/doc/doxygen/html/hierarchy.html new file mode 100644 index 00000000..8e01d301 --- /dev/null +++ b/doc/doxygen/html/hierarchy.html @@ -0,0 +1,108 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: Class Hierarchy + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+
+
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 123]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 CArray1D< T >Stores data of any type T in a 1D array
 CArray1D< Array1D< double > >
 CArray1D< Array1D< int > >
 CArray1D< double >
 CArray1D< int >
 CArray1D< MCMC::chainstate >
 CArray1D< string >
 CArray2D< T >Stores data of any type T in a 2D array
 CArray2D< double >
 CArray2D< int >
 CArray3D< T >Stores data of any type T in a 3D array
 CMCMC::chainstateStructure that holds the chain state information
 CDFISetupBase
 CDFISetup
 Cexception
 CMyException
 CGprocClass for Gaussian processes
 CKLDecompUniComputes the Karhunen-Loeve decomposition of a univariate stochastic process
 CLikelihoodBase
 CDFI
 CDFIInner
 CLregClass for linear parameteric regression
 CPCregDerived class for PC regression
 CPLregDerived class for polynomial regression
 CRBFregDerived class for RBF regression
 CMCMCMarkov Chain Monte Carlo class. Implemented single-site and adaptive MCMC algorithms
 CMCMC::methodparA structure to hold method-specific parameters
 CMrvMultivariate RV parameterized by PC expansions
 CObject
 CXMLAttributeList
 CXMLElement
 CXMLParser
 CXMLExpatParser
 CMCMC::outputparA structure to hold parameters of output specification
 CPCBasisContains all basis type specific definitions and operations needed to generate a PCSet
 CPCSetDefines and initializes PC basis function set and provides functions to manipulate PC expansions defined on this basis set
 CPostPosterior evaluation with various likelihood and prior options
 CLik_ABCDerived class for ABC likelihood
 CLik_ABCmDerived class for ABC-mean likelihood
 CLik_ClassicalDerived class for classical likelihood
 CLik_FullDerived class for full likelihood
 CLik_GausMargDerived class for gaussian-marginal likelihood
 CLik_GausMargDDerived class for gaussian-marginal likelihood with discrete parameter
 CLik_KohDerived class for Kennedy-O'Hagan likelihood
 CLik_MargDerived class for marginal likelihood
 CLik_MVNDerived class for mvn likelihood
 CQuadGenerates quadrature rules
 CQuad::QuadRuleRule structure that stores quadrature points, weights and indices
 CRefPtr< T >
 CRefPtr< XMLAttributeList >
 CRefPtr< XMLElement >
+
+
+ + + + diff --git a/doc/doxygen/html/index.html b/doc/doxygen/html/index.html new file mode 100644 index 00000000..71643390 --- /dev/null +++ b/doc/doxygen/html/index.html @@ -0,0 +1,53 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: <a href="http://www.sandia.gov/UQToolkit">The UQ Toolkit</a> + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + +
+ +
+
+ + + + diff --git a/doc/doxygen/html/inference_8cpp.html b/doc/doxygen/html/inference_8cpp.html new file mode 100644 index 00000000..31a27b9d --- /dev/null +++ b/doc/doxygen/html/inference_8cpp.html @@ -0,0 +1,447 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: inference.cpp File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
inference.cpp File Reference
+
+
+ +

Model inference tools. +More...

+
#include <unistd.h>
+#include <sstream>
+#include <map>
+#include <iostream>
+#include <string>
+#include <math.h>
+#include "func.h"
+#include "post.h"
+#include "mrv.h"
+#include "inference.h"
+#include "mcmc.h"
+#include "tools.h"
+#include "arrayio.h"
+#include "arraytools.h"
+
+ + + + + + + +

+Functions

void infer_model (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, void *funcInfo, string likType, string priorType, double priora, double priorb, Array2D< double > &xdata, Array2D< double > &ydata, Array2D< double > &xgrid, int dataNoiseInference, Array1D< double > &datanoise_array, int pdim, int order, Array1D< int > &rndInd, Array2D< double > &fixindnom, string pdfType, string pcType, int seed, int nmcmc, double mcmcgamma, bool optimflag, Array1D< double > &chstart, Array1D< double > &chsig, double likParam, int likParam_int, Array2D< double > &pgrid, Array2D< double > &pchain, int nburn, int nstep, Array1D< double > &mapparam, Array1D< double > &datavar_map, Array1D< double > &pmean_map, Array1D< double > &pvar_map, Array1D< double > &fmean_map, Array1D< double > &fvar_map, Array1D< double > &postave_datavar, Array1D< double > &p_postave_mean, Array1D< double > &p_postave_var, Array1D< double > &p_postvar_mean, Array2D< double > &f_postsam_mean, Array1D< double > &f_postave_mean, Array1D< double > &f_postave_var, Array1D< double > &f_postvar_mean, Array2D< double > &paramPCcfs)
 Main function for inferring model parameters. More...
 
double LogPosterior (Array1D< double > &m, void *mypost_void)
 Log-posterior function given a vector of parameters (chain state) and a void* set of auxiliary variables. More...
 
+

Detailed Description

+

Model inference tools.

+
Author
K. Sargsyan 2016 -
+

Function Documentation

+ +

◆ infer_model()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void infer_model (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs,
void * funcInfo,
string likType,
string priorType,
double priora,
double priorb,
Array2D< double > & xdata,
Array2D< double > & ydata,
Array2D< double > & xgrid,
int dataNoiseInference,
Array1D< double > & datanoise_array,
int pdim,
int order,
Array1D< int > & rndInd,
Array2D< double > & fixIndNom,
string pdfType,
string pcType,
int seed,
int nmcmc,
double mcmcgamma,
bool optimflag,
Array1D< double > & chstart,
Array1D< double > & chsig,
double likParam,
int likParam_int,
Array2D< double > & pgrid,
Array2D< double > & pchain,
int nburn,
int nstep,
Array1D< double > & mapparam,
Array1D< double > & datavar_map,
Array1D< double > & pmean_map,
Array1D< double > & pvar_map,
Array1D< double > & fmean_map,
Array1D< double > & fvar_map,
Array1D< double > & postave_datavar,
Array1D< double > & p_postave_mean,
Array1D< double > & p_postave_var,
Array1D< double > & p_postvar_mean,
Array2D< double > & f_postsam_mean,
Array1D< double > & f_postave_mean,
Array1D< double > & f_postave_var,
Array1D< double > & f_postvar_mean,
Array2D< double > & paramPCcfs 
)
+
+ +

Main function for inferring model parameters.

+
Note
This is written in a fortran style, i.e. some arguments are inputs, and the rest are output
+
Parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[in]*forwardFuncs: an array of y=f(p,x) functions that take np-by-pdim and nx-by-xdim input arrays and returns an np-by-nx output, see tools/func.h for several examples
[in]funcinfo: auxiliary function-specific information (can be 0)
[in]likType: likelihood type: options are 'full', 'marg', 'mvn', 'gausmarg', 'abc', 'abcm', 'classical', 'koh' (see UQTk Manual)
[in]priorType: prior type: options are 'uniform', 'normal', 'inverse', etc ... (see UQTk Manual)
[in]priora,priorb: prior parameters (todo: need to be made dimension-specific) for uniform, it is the range, for normal it is the moments
[in]xdata: x-values of data, nx-by-xdim
[in]ydata: y-values of data, nx-by-neach
[in]xgrid: x-values where predictive moments are computed after the inference : can be the same as xdata
[in]dataNoiseInference: indicator, data noise stdev is fixed(0), inferred (1), or log-inferred (2)
[in]datanoise_array: data noise stdev array, if fixed, otherwise merely an MCMC starting point
[in]pdim: model parameter dimensionality
[in]order: order of output PC that is computed via NISP in the likelihood
[in]rndInd: array of indices of parameters to be randomized
[in]fixIndNom: array of indices and nominal values of parameters to be fixed
[in]pdfType: type of PDF PC parameterization, options are 'pct','pci' and 'full' (see UQTk Manual)
[in]pcType: type of PC for the PDF parameterization, options are all common PC types, e.g. 'HG','LU'
[in]seed: integer seed for MCMC
[in]nmcmc: number of MCMC steps to follow optimization; if 0, then only optimization is performed if optimflag is True
[in]mcmcgamma: gamma (scaling) parameter for adaptive MCMC
[in]optimflag: indicates if optimization is prepended to MCMC
[in]chstart: initial chain state
[in]chsig: initial non-adaptive, dimensionwise proposal jump size
[in]likParam,likParam_int: likelihood parameters (currently, only needed for KDE-based likelihoods, 'full' and 'marg', to pass the KDE bandwidth and number of samples)
[in]pgrid: parameter grid, if requested, to compute exact posterior (can be empty)
[in]nburn: burn-in for MCMC to write to pchain
[in]nstep: thinning of MCMC to write to pchain
[in,out]pchain: thinned chain file with nburn and nstep applied, to be used for postprocessing : if given as non-empty array, the MCMC is skipped, and only postprocessing is performed
[out]mapparam: MAP parameters
[out]datavar_map: MAP value of data variances
[out]pmean_map,pvar_map: MAP values of parameter means and variances
[out]fmean_map,fvar_map: MAP values of function predition (at xgrid) means and variances
[out]postave_datavar: posterior average of data variances
[out]p_postave_mean: posterior average of parameter mean
[out]p_postave_var: posterior average of parameter variance
[out]p_postvar_mean: posterior variance of parameter mean
[out]f_postave_mean: posterior average of function prediction mean
[out]f_postave_var: posterior average of function prediction variance
[out]f_postvar_mean: posterior variance of function prediction mean
[out]paramPCcfs: each column is a vector of parameter PC coefficients corresponding to an MCMC sample from pchain the last column is the MAP value of parameter PC coefficients
+
+
+ +
+
+ +

◆ LogPosterior()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double LogPosterior (Array1D< double > & m,
void * mypost_void 
)
+
+ +

Log-posterior function given a vector of parameters (chain state) and a void* set of auxiliary variables.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/inference_8h.html b/doc/doxygen/html/inference_8h.html new file mode 100644 index 00000000..892669e1 --- /dev/null +++ b/doc/doxygen/html/inference_8h.html @@ -0,0 +1,438 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: inference.h File Reference + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+ +
+
inference.h File Reference
+
+
+ +

Header for the model inference tools. +More...

+
#include <string>
+#include "Array1D.h"
+#include "Array2D.h"
+
+

Go to the source code of this file.

+ + + + + + + + +

+Functions

void infer_model (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, void *funcInfo, string likType, string priorType, double priora, double priorb, Array2D< double > &xdata, Array2D< double > &ydata, Array2D< double > &xgrid, int dataNoiseInference, Array1D< double > &datanoise_array, int pdim, int order, Array1D< int > &rndInd, Array2D< double > &fixIndNom, string pdfType, string pcType, int seed, int nmcmc, double mcmcgamma, bool optimflag, Array1D< double > &chstart, Array1D< double > &chsig, double likParam, int likParam_int, Array2D< double > &pgrid, Array2D< double > &pchain, int nburn, int nstep, Array1D< double > &mapparam, Array1D< double > &datavar_map, Array1D< double > &pmean_map, Array1D< double > &pvar_map, Array1D< double > &fmean_map, Array1D< double > &fvar_map, Array1D< double > &postave_datavar, Array1D< double > &p_postave_mean, Array1D< double > &p_postave_var, Array1D< double > &p_postvar_mean, Array2D< double > &f_postsam_mean, Array1D< double > &f_postave_mean, Array1D< double > &f_postave_var, Array1D< double > &f_postvar_mean, Array2D< double > &paramPCcfs)
 Main function for inferring model parameters. More...
 
double LogPosterior (Array1D< double > &m, void *mypost_void)
 Log-posterior function given a vector of parameters (chain state) and a void* set of auxiliary variables. More...
 
+

Detailed Description

+

Header for the model inference tools.

+
Author
K. Sargsyan 2016 -
+

Function Documentation

+ +

◆ infer_model()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void infer_model (Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs,
void * funcInfo,
string likType,
string priorType,
double priora,
double priorb,
Array2D< double > & xdata,
Array2D< double > & ydata,
Array2D< double > & xgrid,
int dataNoiseInference,
Array1D< double > & datanoise_array,
int pdim,
int order,
Array1D< int > & rndInd,
Array2D< double > & fixIndNom,
string pdfType,
string pcType,
int seed,
int nmcmc,
double mcmcgamma,
bool optimflag,
Array1D< double > & chstart,
Array1D< double > & chsig,
double likParam,
int likParam_int,
Array2D< double > & pgrid,
Array2D< double > & pchain,
int nburn,
int nstep,
Array1D< double > & mapparam,
Array1D< double > & datavar_map,
Array1D< double > & pmean_map,
Array1D< double > & pvar_map,
Array1D< double > & fmean_map,
Array1D< double > & fvar_map,
Array1D< double > & postave_datavar,
Array1D< double > & p_postave_mean,
Array1D< double > & p_postave_var,
Array1D< double > & p_postvar_mean,
Array2D< double > & f_postsam_mean,
Array1D< double > & f_postave_mean,
Array1D< double > & f_postave_var,
Array1D< double > & f_postvar_mean,
Array2D< double > & paramPCcfs 
)
+
+ +

Main function for inferring model parameters.

+
Note
This is written in a fortran style, i.e. some arguments are inputs, and the rest are output
+
Parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[in]*forwardFuncs: an array of y=f(p,x) functions that take np-by-pdim and nx-by-xdim input arrays and returns an np-by-nx output, see tools/func.h for several examples
[in]funcinfo: auxiliary function-specific information (can be 0)
[in]likType: likelihood type: options are 'full', 'marg', 'mvn', 'gausmarg', 'abc', 'abcm', 'classical', 'koh' (see UQTk Manual)
[in]priorType: prior type: options are 'uniform', 'normal', 'inverse', etc ... (see UQTk Manual)
[in]priora,priorb: prior parameters (todo: need to be made dimension-specific) for uniform, it is the range, for normal it is the moments
[in]xdata: x-values of data, nx-by-xdim
[in]ydata: y-values of data, nx-by-neach
[in]xgrid: x-values where predictive moments are computed after the inference : can be the same as xdata
[in]dataNoiseInference: indicator, data noise stdev is fixed(0), inferred (1), or log-inferred (2)
[in]datanoise_array: data noise stdev array, if fixed, otherwise merely an MCMC starting point
[in]pdim: model parameter dimensionality
[in]order: order of output PC that is computed via NISP in the likelihood
[in]rndInd: array of indices of parameters to be randomized
[in]fixIndNom: array of indices and nominal values of parameters to be fixed
[in]pdfType: type of PDF PC parameterization, options are 'pct','pci' and 'full' (see UQTk Manual)
[in]pcType: type of PC for the PDF parameterization, options are all common PC types, e.g. 'HG','LU'
[in]seed: integer seed for MCMC
[in]nmcmc: number of MCMC steps to follow optimization; if 0, then only optimization is performed if optimflag is True
[in]mcmcgamma: gamma (scaling) parameter for adaptive MCMC
[in]optimflag: indicates if optimization is prepended to MCMC
[in]chstart: initial chain state
[in]chsig: initial non-adaptive, dimensionwise proposal jump size
[in]likParam,likParam_int: likelihood parameters (currently, only needed for KDE-based likelihoods, 'full' and 'marg', to pass the KDE bandwidth and number of samples)
[in]pgrid: parameter grid, if requested, to compute exact posterior (can be empty)
[in]nburn: burn-in for MCMC to write to pchain
[in]nstep: thinning of MCMC to write to pchain
[in,out]pchain: thinned chain file with nburn and nstep applied, to be used for postprocessing : if given as non-empty array, the MCMC is skipped, and only postprocessing is performed
[out]mapparam: MAP parameters
[out]datavar_map: MAP value of data variances
[out]pmean_map,pvar_map: MAP values of parameter means and variances
[out]fmean_map,fvar_map: MAP values of function predition (at xgrid) means and variances
[out]postave_datavar: posterior average of data variances
[out]p_postave_mean: posterior average of parameter mean
[out]p_postave_var: posterior average of parameter variance
[out]p_postvar_mean: posterior variance of parameter mean
[out]f_postave_mean: posterior average of function prediction mean
[out]f_postave_var: posterior average of function prediction variance
[out]f_postvar_mean: posterior variance of function prediction mean
[out]paramPCcfs: each column is a vector of parameter PC coefficients corresponding to an MCMC sample from pchain the last column is the MAP value of parameter PC coefficients
+
+
+ +
+
+ +

◆ LogPosterior()

+ +
+
+ + + + + + + + + + + + + + + + + + +
double LogPosterior (Array1D< double > & m,
void * mypost_void 
)
+
+ +

Log-posterior function given a vector of parameters (chain state) and a void* set of auxiliary variables.

+ +
+
+
+ + + + diff --git a/doc/doxygen/html/inference_8h_source.html b/doc/doxygen/html/inference_8h_source.html new file mode 100644 index 00000000..83d2030b --- /dev/null +++ b/doc/doxygen/html/inference_8h_source.html @@ -0,0 +1,65 @@ + + + + + + + +UQTk: Uncertainty Quantification Toolkit: inference.h Source File + + + + + + +
+
+ + + + + + +
+
UQTk: Uncertainty Quantification Toolkit +  3.0.4 +
+
+
+ + + + + + + +
+
+
+
inference.h
+
+
+Go to the documentation of this file.
1 /* =====================================================================================
2  The UQ Toolkit (UQTk) version @UQTKVERSION@
3  Copyright (@UQTKYEAR@) Sandia Corporation
4  http://www.sandia.gov/UQToolkit/
5 
6  Copyright (@UQTKYEAR@) Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000
7  with Sandia Corporation, the U.S. Government retains certain rights in this software.
8 
9  This file is part of The UQ Toolkit (UQTk)
10 
11  UQTk is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  UQTk is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with UQTk. If not, see <http://www.gnu.org/licenses/>.
23 
24  Questions? Contact Bert Debusschere <bjdebus@sandia.gov>
25  Sandia National Laboratories, Livermore, CA, USA
26 ===================================================================================== */
30 
31 #include <string>
32 
33 #include "Array1D.h"
34 #include "Array2D.h"
35 
36 
86 void infer_model(Array1D< Array2D<double> (*)(Array2D<double>&, Array2D<double>&, Array2D<double>&, void *) > forwardFuncs, void* funcInfo,
87  string likType,
88  string priorType, double priora, double priorb,
89  Array2D<double>& xdata,Array2D<double>& ydata, Array2D<double>& xgrid,
90  int dataNoiseInference, Array1D<double>& datanoise_array,
91  int pdim,int order,Array1D<int>& rndInd,Array2D<double>& fixIndNom,string pdfType,string pcType,
92  int seed, int nmcmc, double mcmcgamma, bool optimflag, Array1D<double>& chstart, Array1D<double>& chsig,
93  double likParam, int likParam_int,
94  Array2D<double>& pgrid,Array2D<double>& pchain, int nburn, int nstep,
95  Array1D<double>& mapparam, Array1D<double>& datavar_map,
96  Array1D<double>& pmean_map, Array1D<double>& pvar_map,
97  Array1D<double>& fmean_map, Array1D<double>& fvar_map,
98  Array1D<double>& postave_datavar,
99  Array1D<double>& p_postave_mean, Array1D<double>& p_postave_var, Array1D<double>& p_postvar_mean,
100  Array2D<double>& f_postsam_mean, Array1D<double>& f_postave_mean, Array1D<double>& f_postave_var, Array1D<double>& f_postvar_mean,
101  Array2D<double>& paramPCcfs);
102 
104 double LogPosterior(Array1D<double>& m, void* mypost_void);
105 
106 
Stores data of any type T in a 1D array.
Definition: Array1D.h:60
+
double LogPosterior(Array1D< double > &m, void *mypost_void)
Log-posterior function given a vector of parameters (chain state) and a void* set of auxiliary variab...
Definition: inference.cpp:309
+
void infer_model(Array1D< Array2D< double >(*)(Array2D< double > &, Array2D< double > &, Array2D< double > &, void *) > forwardFuncs, void *funcInfo, string likType, string priorType, double priora, double priorb, Array2D< double > &xdata, Array2D< double > &ydata, Array2D< double > &xgrid, int dataNoiseInference, Array1D< double > &datanoise_array, int pdim, int order, Array1D< int > &rndInd, Array2D< double > &fixIndNom, string pdfType, string pcType, int seed, int nmcmc, double mcmcgamma, bool optimflag, Array1D< double > &chstart, Array1D< double > &chsig, double likParam, int likParam_int, Array2D< double > &pgrid, Array2D< double > &pchain, int nburn, int nstep, Array1D< double > &mapparam, Array1D< double > &datavar_map, Array1D< double > &pmean_map, Array1D< double > &pvar_map, Array1D< double > &fmean_map, Array1D< double > &fvar_map, Array1D< double > &postave_datavar, Array1D< double > &p_postave_mean, Array1D< double > &p_postave_var, Array1D< double > &p_postvar_mean, Array2D< double > &f_postsam_mean, Array1D< double > &f_postave_mean, Array1D< double > &f_postave_var, Array1D< double > &f_postvar_mean, Array2D< double > &paramPCcfs)
Main function for inferring model parameters.
Definition: inference.cpp:50
+
Definition: Array1D.h:471
+ +
2D Array class for any type T
+
Definition: Array1D.h:261
+
1D Array class for any type T
+
+ + + + diff --git a/doc/doxygen/html/jquery.js b/doc/doxygen/html/jquery.js new file mode 100644 index 00000000..f5343eda --- /dev/null +++ b/doc/doxygen/html/jquery.js @@ -0,0 +1,87 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g
');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(hl.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*! + * jQuery hashchange event - v1.3 - 7/21/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('