├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── ComputeGaussKronrodNodesWeights.h ├── GaussKronrodNodesWeights.h ├── Integrator.h ├── LICENSE ├── LaurieGautschi.h ├── Monegato.h ├── NumericalIntegration.h ├── Piessens.h ├── README.md ├── cmake ├── FindEigen3.cmake ├── FindGMP.cmake ├── FindMPFR.cmake ├── FindMPFRCPP.cmake └── FindQuantLib.cmake ├── compile.sh ├── doc ├── CMakeLists.txt ├── Doxyfile.in ├── ImportantPapers.md └── Referenced and Topic Study Literature │ ├── AMMAR CALVETTI REICHEL Computation of Gauss-Kronrod Quadrature Rules with Non-Positive Weights.pdf │ ├── BOND A New Integration Method Providing the Accuracy of Gauss-Legendre with Error Estimation Capability.pdf │ ├── CALIO GAUTSCHI MARCHETTI On Computing Gauss Kronrod Quadrature Formulae.pdf │ ├── COMPUTATION OF GAUSS-KRONROD QUADRATURE RULES WITH NON-POSITIVE WEIGHTS.pdf │ ├── ELHAY KAUTSKI Generalized Kronrod Patterson type imbedded quadratures.pdf │ ├── GOLUB WELSCH Computation of Gauss Quadrature Rules.pdf │ ├── GONNET A Review of Error Estimation in Adaptive Quadrature.pdf │ ├── GONNET Adaptive Quadrature Re-Revisited.pdf │ ├── HERNANDEZ YSERN LOGOMACINO Generalized Stieltjes Polynomials and Rational Gauss-Kronrod Quadrature.pdf │ ├── LAURIE Calculation of Gauss-Kronrod Quadrature Rules.pdf │ ├── LI Kronrod Extension of Generalized Gauss Radau and Gauss Lobatto Formulae.pdf │ ├── LUCAS STONE Evaluating infinite integrals involving Bessel Functions of Arbitrary Order.pdf │ ├── NEWMAN Computational Physics AppendixC.pdf │ ├── NEWMAN Computational Physics Chapter 5.pdf │ ├── Piessens_Kronrod_Nodes_and_Weigths_1974_Comp_of_Mathematics.pdf │ ├── SMYTH Numerical Integration.pdf │ └── VLADISLAV Construction of Gauss-Kronrod-Hermite Quadrature and Cubature Formulas.pdf ├── examples ├── CMakeLists.txt └── Integration.cpp ├── gauss_quadrature.png ├── generateQK.sh ├── progress ├── comparison_with_QuantLib.md ├── ms_2014_dec_5.md ├── ms_2014_dec_9.md ├── ms_2014_nov_23.md ├── ms_2014_oct_04.md ├── ms_2014_sep_20.md ├── ms_2014_sep_22.md ├── nodes_weights_float.txt ├── stb_2014_nov_30.md ├── stb_2014_oct_01.md ├── stb_2014_sep_14.md └── stb_2014_sep_18.md └── test ├── CMakeLists.txt ├── generateGaussKronrodQuadrature.cpp ├── testComputeNodesWeights.cpp ├── testIntegrator_InfiniteInterval.cpp ├── testIntegrator_LogPow.cpp ├── testIntegrator_Peak.cpp ├── testIntegrator_Sine.cpp ├── testNodesAndWeightsByCompare.cpp └── testQuantLib.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # scripts 31 | *.sh 32 | 33 | build/ 34 | test/testOutput 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - gcc 5 | 6 | before_install: 7 | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 8 | - sudo apt-get -qq update 9 | - sudo apt-get -qq install g++-4.8 10 | - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 11 | - sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-4.8 90 12 | - sudo apt-get install libmpfr-dev 13 | - echo $LANG 14 | 15 | before_script: 16 | - hg clone https://bitbucket.org/advanpix/mpreal 17 | - cd mpreal 18 | - export MPREAL_INCLUDE_DIR=${PWD} 19 | - cd .. 20 | - hg clone https://bitbucket.org/eigen/eigen 21 | - cd eigen 22 | - export EIGEN_INCLUDE_DIR=${PWD} 23 | - cd .. 24 | 25 | script: 26 | - mkdir build 27 | - cd build 28 | - echo ${MPREAL_INCLUDE_DIR} 29 | - cmake -DMPFRCPP_ROOT=${MPREAL_INCLUDE_DIR} -DEIGEN3_INCLUDE_DIR=${EIGEN_INCLUDE_DIR} ../ 30 | - $CXX --version 31 | - make VERBOSE=1 32 | - gcov --version 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8) 2 | 3 | PROJECT(NumericalIntegration CXX) 4 | 5 | # Guard against in-source builds (got this from Eigen) 6 | IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) 7 | message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ") 8 | ENDIF() 9 | 10 | ################################################# 11 | # Compiler checks for Unix type systems. 12 | ################################################# 13 | #IF(UNIX) 14 | # IF(CMAKE_COMPILER_IS_GNUCXX) 15 | # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -pedantic -Wall -Wextra -Wfatal-errors -g") 16 | # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}") 17 | # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 -O3 -march=native") 18 | # ENDIF(CMAKE_COMPILER_IS_GNUCXX) 19 | # 20 | # #is the compiler clang? 21 | # IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 22 | # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -pedantic -Wall -Wextra -g") 23 | # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}") 24 | # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 -O3 -march=native") 25 | # ELSEIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") 26 | # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=gnu++11 -pedantic -w3 -g") 27 | # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}") 28 | # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=gnu++11 -O3 -march=native ") 29 | # ENDIF() 30 | # 31 | #ENDIF(UNIX) 32 | 33 | ################################################# 34 | # NEED CHECKS FOR WINDOWS 35 | ################################################# 36 | 37 | 38 | INCLUDE(ExternalProject) 39 | 40 | SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 41 | 42 | #Eigen3 headers 43 | FIND_PACKAGE(Eigen3 REQUIRED) 44 | FIND_PACKAGE(GMP REQUIRED) 45 | FIND_PACKAGE(MPFR REQUIRED) 46 | FIND_PACKAGE(MPFRCPP REQUIRED) 47 | 48 | INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR}) 49 | INCLUDE_DIRECTORIES(${GMP_INCLUDES}) 50 | INCLUDE_DIRECTORIES(${MPFR_INCLUDES}) 51 | INCLUDE_DIRECTORIES(${MPFRCPP_INCLUDES}) 52 | 53 | INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) 54 | 55 | # libraries 56 | SET(ALL_LIBS ${MPFR_LIBRARIES} ${GMP_LIBRARIES}) 57 | 58 | ADD_DEFINITIONS( 59 | -O3 60 | -DAPL=0 61 | -DIBM=0 62 | -DLIN=1 63 | -DNDEBUG 64 | -DCOMPUTE_NI_WEIGHTS_ON_THE_FLY 65 | 66 | -Wall 67 | -Wcast-align 68 | -Wchar-subscripts 69 | -Wconversion 70 | -Wdouble-promotion 71 | -Wextra 72 | -Wfatal-errors 73 | -Wformat-security 74 | -Wlogical-op 75 | -Wno-long-long 76 | -Wno-psabi 77 | -Wno-variadic-macros 78 | #-Wnon-virtual-dtor 79 | -Wpointer-arith 80 | #-Wundef 81 | -Wuninitialized 82 | -Wunused-local-typedefs 83 | -Wwrite-strings 84 | 85 | -fstrict-aliasing 86 | -fno-check-new 87 | -fno-common 88 | -fvisibility=hidden 89 | -fPIC 90 | 91 | -c 92 | -g 93 | -march=native 94 | -pedantic 95 | -pthread 96 | ) 97 | 98 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 99 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 100 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) 101 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 102 | 103 | SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LD_VERSION_SCRIPT_FLAG}") 104 | 105 | ENABLE_TESTING() 106 | ADD_SUBDIRECTORY(doc) 107 | ADD_SUBDIRECTORY(examples) 108 | ADD_SUBDIRECTORY(test) 109 | -------------------------------------------------------------------------------- /ComputeGaussKronrodNodesWeights.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \file ComputeGaussKronrodNodesWeights.h 3 | * The functions contained in this file calculate the Gauss-Kronrod nodes and weights 4 | * using the Laurie/Gautschi method. 5 | */ 6 | 7 | #ifndef EIGEN_COMPUTE_GAUSS_KRONROD_NODES_WEIGHTS_H 8 | #define EIGEN_COMPUTE_GAUSS_KRONROD_NODES_WEIGHTS_H 9 | 10 | #include "LaurieGautschi.h" // Stable, slow and requires c++11 tgamma and the latest mpreal.h. 11 | #include "Piessens.h" // Stable for most rules and precisions, faster than LaurieGautschi. 12 | #include "Monegato.h" // Fastest but unstable for rules above 80. 13 | 14 | #endif //EIGEN_COMPUTE_GAUSS_KRONROD_NODES_WEIGHTS_H 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License, version 2.0 2 | 3 | 1. Definitions 4 | 5 | 1.1. "Contributor" 6 | 7 | means each individual or legal entity that creates, contributes to the 8 | creation of, or owns Covered Software. 9 | 10 | 1.2. "Contributor Version" 11 | 12 | means the combination of the Contributions of others (if any) used by a 13 | Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | 17 | means Covered Software of a particular Contributor. 18 | 19 | 1.4. "Covered Software" 20 | 21 | means Source Code Form to which the initial Contributor has attached the 22 | notice in Exhibit A, the Executable Form of such Source Code Form, and 23 | Modifications of such Source Code Form, in each case including portions 24 | thereof. 25 | 26 | 1.5. "Incompatible With Secondary Licenses" 27 | means 28 | 29 | a. that the initial Contributor has attached the notice described in 30 | Exhibit B to the Covered Software; or 31 | 32 | b. that the Covered Software was made available under the terms of 33 | version 1.1 or earlier of the License, but not also under the terms of 34 | a Secondary License. 35 | 36 | 1.6. "Executable Form" 37 | 38 | means any form of the work other than Source Code Form. 39 | 40 | 1.7. "Larger Work" 41 | 42 | means a work that combines Covered Software with other material, in a 43 | separate file or files, that is not Covered Software. 44 | 45 | 1.8. "License" 46 | 47 | means this document. 48 | 49 | 1.9. "Licensable" 50 | 51 | means having the right to grant, to the maximum extent possible, whether 52 | at the time of the initial grant or subsequently, any and all of the 53 | rights conveyed by this License. 54 | 55 | 1.10. "Modifications" 56 | 57 | means any of the following: 58 | 59 | a. any file in Source Code Form that results from an addition to, 60 | deletion from, or modification of the contents of Covered Software; or 61 | 62 | b. any new file in Source Code Form that contains any Covered Software. 63 | 64 | 1.11. "Patent Claims" of a Contributor 65 | 66 | means any patent claim(s), including without limitation, method, 67 | process, and apparatus claims, in any patent Licensable by such 68 | Contributor that would be infringed, but for the grant of the License, 69 | by the making, using, selling, offering for sale, having made, import, 70 | or transfer of either its Contributions or its Contributor Version. 71 | 72 | 1.12. "Secondary License" 73 | 74 | means either the GNU General Public License, Version 2.0, the GNU Lesser 75 | General Public License, Version 2.1, the GNU Affero General Public 76 | License, Version 3.0, or any later versions of those licenses. 77 | 78 | 1.13. "Source Code Form" 79 | 80 | means the form of the work preferred for making modifications. 81 | 82 | 1.14. "You" (or "Your") 83 | 84 | means an individual or a legal entity exercising rights under this 85 | License. For legal entities, "You" includes any entity that controls, is 86 | controlled by, or is under common control with You. For purposes of this 87 | definition, "control" means (a) the power, direct or indirect, to cause 88 | the direction or management of such entity, whether by contract or 89 | otherwise, or (b) ownership of more than fifty percent (50%) of the 90 | outstanding shares or beneficial ownership of such entity. 91 | 92 | 93 | 2. License Grants and Conditions 94 | 95 | 2.1. Grants 96 | 97 | Each Contributor hereby grants You a world-wide, royalty-free, 98 | non-exclusive license: 99 | 100 | a. under intellectual property rights (other than patent or trademark) 101 | Licensable by such Contributor to use, reproduce, make available, 102 | modify, display, perform, distribute, and otherwise exploit its 103 | Contributions, either on an unmodified basis, with Modifications, or 104 | as part of a Larger Work; and 105 | 106 | b. under Patent Claims of such Contributor to make, use, sell, offer for 107 | sale, have made, import, and otherwise transfer either its 108 | Contributions or its Contributor Version. 109 | 110 | 2.2. Effective Date 111 | 112 | The licenses granted in Section 2.1 with respect to any Contribution 113 | become effective for each Contribution on the date the Contributor first 114 | distributes such Contribution. 115 | 116 | 2.3. Limitations on Grant Scope 117 | 118 | The licenses granted in this Section 2 are the only rights granted under 119 | this License. No additional rights or licenses will be implied from the 120 | distribution or licensing of Covered Software under this License. 121 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 122 | Contributor: 123 | 124 | a. for any code that a Contributor has removed from Covered Software; or 125 | 126 | b. for infringements caused by: (i) Your and any other third party's 127 | modifications of Covered Software, or (ii) the combination of its 128 | Contributions with other software (except as part of its Contributor 129 | Version); or 130 | 131 | c. under Patent Claims infringed by Covered Software in the absence of 132 | its Contributions. 133 | 134 | This License does not grant any rights in the trademarks, service marks, 135 | or logos of any Contributor (except as may be necessary to comply with 136 | the notice requirements in Section 3.4). 137 | 138 | 2.4. Subsequent Licenses 139 | 140 | No Contributor makes additional grants as a result of Your choice to 141 | distribute the Covered Software under a subsequent version of this 142 | License (see Section 10.2) or under the terms of a Secondary License (if 143 | permitted under the terms of Section 3.3). 144 | 145 | 2.5. Representation 146 | 147 | Each Contributor represents that the Contributor believes its 148 | Contributions are its original creation(s) or it has sufficient rights to 149 | grant the rights to its Contributions conveyed by this License. 150 | 151 | 2.6. Fair Use 152 | 153 | This License is not intended to limit any rights You have under 154 | applicable copyright doctrines of fair use, fair dealing, or other 155 | equivalents. 156 | 157 | 2.7. Conditions 158 | 159 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in 160 | Section 2.1. 161 | 162 | 163 | 3. Responsibilities 164 | 165 | 3.1. Distribution of Source Form 166 | 167 | All distribution of Covered Software in Source Code Form, including any 168 | Modifications that You create or to which You contribute, must be under 169 | the terms of this License. You must inform recipients that the Source 170 | Code Form of the Covered Software is governed by the terms of this 171 | License, and how they can obtain a copy of this License. You may not 172 | attempt to alter or restrict the recipients' rights in the Source Code 173 | Form. 174 | 175 | 3.2. Distribution of Executable Form 176 | 177 | If You distribute Covered Software in Executable Form then: 178 | 179 | a. such Covered Software must also be made available in Source Code Form, 180 | as described in Section 3.1, and You must inform recipients of the 181 | Executable Form how they can obtain a copy of such Source Code Form by 182 | reasonable means in a timely manner, at a charge no more than the cost 183 | of distribution to the recipient; and 184 | 185 | b. You may distribute such Executable Form under the terms of this 186 | License, or sublicense it under different terms, provided that the 187 | license for the Executable Form does not attempt to limit or alter the 188 | recipients' rights in the Source Code Form under this License. 189 | 190 | 3.3. Distribution of a Larger Work 191 | 192 | You may create and distribute a Larger Work under terms of Your choice, 193 | provided that You also comply with the requirements of this License for 194 | the Covered Software. If the Larger Work is a combination of Covered 195 | Software with a work governed by one or more Secondary Licenses, and the 196 | Covered Software is not Incompatible With Secondary Licenses, this 197 | License permits You to additionally distribute such Covered Software 198 | under the terms of such Secondary License(s), so that the recipient of 199 | the Larger Work may, at their option, further distribute the Covered 200 | Software under the terms of either this License or such Secondary 201 | License(s). 202 | 203 | 3.4. Notices 204 | 205 | You may not remove or alter the substance of any license notices 206 | (including copyright notices, patent notices, disclaimers of warranty, or 207 | limitations of liability) contained within the Source Code Form of the 208 | Covered Software, except that You may alter any license notices to the 209 | extent required to remedy known factual inaccuracies. 210 | 211 | 3.5. Application of Additional Terms 212 | 213 | You may choose to offer, and to charge a fee for, warranty, support, 214 | indemnity or liability obligations to one or more recipients of Covered 215 | Software. However, You may do so only on Your own behalf, and not on 216 | behalf of any Contributor. You must make it absolutely clear that any 217 | such warranty, support, indemnity, or liability obligation is offered by 218 | You alone, and You hereby agree to indemnify every Contributor for any 219 | liability incurred by such Contributor as a result of warranty, support, 220 | indemnity or liability terms You offer. You may include additional 221 | disclaimers of warranty and limitations of liability specific to any 222 | jurisdiction. 223 | 224 | 4. Inability to Comply Due to Statute or Regulation 225 | 226 | If it is impossible for You to comply with any of the terms of this License 227 | with respect to some or all of the Covered Software due to statute, 228 | judicial order, or regulation then You must: (a) comply with the terms of 229 | this License to the maximum extent possible; and (b) describe the 230 | limitations and the code they affect. Such description must be placed in a 231 | text file included with all distributions of the Covered Software under 232 | this License. Except to the extent prohibited by statute or regulation, 233 | such description must be sufficiently detailed for a recipient of ordinary 234 | skill to be able to understand it. 235 | 236 | 5. Termination 237 | 238 | 5.1. The rights granted under this License will terminate automatically if You 239 | fail to comply with any of its terms. However, if You become compliant, 240 | then the rights granted under this License from a particular Contributor 241 | are reinstated (a) provisionally, unless and until such Contributor 242 | explicitly and finally terminates Your grants, and (b) on an ongoing 243 | basis, if such Contributor fails to notify You of the non-compliance by 244 | some reasonable means prior to 60 days after You have come back into 245 | compliance. Moreover, Your grants from a particular Contributor are 246 | reinstated on an ongoing basis if such Contributor notifies You of the 247 | non-compliance by some reasonable means, this is the first time You have 248 | received notice of non-compliance with this License from such 249 | Contributor, and You become compliant prior to 30 days after Your receipt 250 | of the notice. 251 | 252 | 5.2. If You initiate litigation against any entity by asserting a patent 253 | infringement claim (excluding declaratory judgment actions, 254 | counter-claims, and cross-claims) alleging that a Contributor Version 255 | directly or indirectly infringes any patent, then the rights granted to 256 | You by any and all Contributors for the Covered Software under Section 257 | 2.1 of this License shall terminate. 258 | 259 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user 260 | license agreements (excluding distributors and resellers) which have been 261 | validly granted by You or Your distributors under this License prior to 262 | termination shall survive termination. 263 | 264 | 6. Disclaimer of Warranty 265 | 266 | Covered Software is provided under this License on an "as is" basis, 267 | without warranty of any kind, either expressed, implied, or statutory, 268 | including, without limitation, warranties that the Covered Software is free 269 | of defects, merchantable, fit for a particular purpose or non-infringing. 270 | The entire risk as to the quality and performance of the Covered Software 271 | is with You. Should any Covered Software prove defective in any respect, 272 | You (not any Contributor) assume the cost of any necessary servicing, 273 | repair, or correction. This disclaimer of warranty constitutes an essential 274 | part of this License. No use of any Covered Software is authorized under 275 | this License except under this disclaimer. 276 | 277 | 7. Limitation of Liability 278 | 279 | Under no circumstances and under no legal theory, whether tort (including 280 | negligence), contract, or otherwise, shall any Contributor, or anyone who 281 | distributes Covered Software as permitted above, be liable to You for any 282 | direct, indirect, special, incidental, or consequential damages of any 283 | character including, without limitation, damages for lost profits, loss of 284 | goodwill, work stoppage, computer failure or malfunction, or any and all 285 | other commercial damages or losses, even if such party shall have been 286 | informed of the possibility of such damages. This limitation of liability 287 | shall not apply to liability for death or personal injury resulting from 288 | such party's negligence to the extent applicable law prohibits such 289 | limitation. Some jurisdictions do not allow the exclusion or limitation of 290 | incidental or consequential damages, so this exclusion and limitation may 291 | not apply to You. 292 | 293 | 8. Litigation 294 | 295 | Any litigation relating to this License may be brought only in the courts 296 | of a jurisdiction where the defendant maintains its principal place of 297 | business and such litigation shall be governed by laws of that 298 | jurisdiction, without reference to its conflict-of-law provisions. Nothing 299 | in this Section shall prevent a party's ability to bring cross-claims or 300 | counter-claims. 301 | 302 | 9. Miscellaneous 303 | 304 | This License represents the complete agreement concerning the subject 305 | matter hereof. If any provision of this License is held to be 306 | unenforceable, such provision shall be reformed only to the extent 307 | necessary to make it enforceable. Any law or regulation which provides that 308 | the language of a contract shall be construed against the drafter shall not 309 | be used to construe this License against a Contributor. 310 | 311 | 312 | 10. Versions of the License 313 | 314 | 10.1. New Versions 315 | 316 | Mozilla Foundation is the license steward. Except as provided in Section 317 | 10.3, no one other than the license steward has the right to modify or 318 | publish new versions of this License. Each version will be given a 319 | distinguishing version number. 320 | 321 | 10.2. Effect of New Versions 322 | 323 | You may distribute the Covered Software under the terms of the version 324 | of the License under which You originally received the Covered Software, 325 | or under the terms of any subsequent version published by the license 326 | steward. 327 | 328 | 10.3. Modified Versions 329 | 330 | If you create software not governed by this License, and you want to 331 | create a new license for such software, you may create and use a 332 | modified version of this License if you rename the license and remove 333 | any references to the name of the license steward (except to note that 334 | such modified license differs from this License). 335 | 336 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 337 | Licenses If You choose to distribute Source Code Form that is 338 | Incompatible With Secondary Licenses under the terms of this version of 339 | the License, the notice described in Exhibit B of this License must be 340 | attached. 341 | 342 | Exhibit A - Source Code Form License Notice 343 | 344 | This Source Code Form is subject to the 345 | terms of the Mozilla Public License, v. 346 | 2.0. If a copy of the MPL was not 347 | distributed with this file, You can 348 | obtain one at 349 | http://mozilla.org/MPL/2.0/. 350 | 351 | If it is not possible or desirable to put the notice in a particular file, 352 | then You may include the notice in a location (such as a LICENSE file in a 353 | relevant directory) where a recipient would be likely to look for such a 354 | notice. 355 | 356 | You may add additional accurate notices of copyright ownership. 357 | 358 | Exhibit B - "Incompatible With Secondary Licenses" Notice 359 | 360 | This Source Code Form is "Incompatible 361 | With Secondary Licenses", as defined by 362 | the Mozilla Public License, v. 2.0. 363 | -------------------------------------------------------------------------------- /Monegato.h: -------------------------------------------------------------------------------- 1 | #ifndef EIGEN_MONEGATO_H 2 | #define EIGEN_MONEGATO_H 3 | 4 | namespace Eigen 5 | { 6 | 7 | /** 8 | * \ingroup NumericalIntegration_Module 9 | * 10 | * \class Monegato 11 | * 12 | * \brief A class for computing the Gauss/Kronrod weights. 13 | * 14 | * \tparam Scalar floating point type 15 | * 16 | * This class is based on "Some remarks on the construction of 17 | * extended Gaussian quadrature rules", Giovanni Monegato, 18 | * Math. Comp., Vol. 32 (1978) pp. 247-252. http://www.jstor.org/stable/2006272 . 19 | * 20 | * The code is based on quadpackcpp (http://quadpackpp.sourceforge.net/) 21 | * library written by Jerry Gagelman which is distributed under 22 | * GNU General Public License 23 | */ 24 | template 25 | class Monegato 26 | { 27 | public: 28 | 29 | /** 30 | * \brief Compute the absolute value of a scalar 31 | * \param[in] x inpute scalar value 32 | * \return absolute value of scalar input 33 | */ 34 | static Scalar abs(Scalar x) 35 | { 36 | return (x < Scalar(0)) ? -(x) : x; 37 | } 38 | 39 | /** 40 | * \brief Compute the Legendre polynomials and their error 41 | * \param[in] n degree 42 | * \param[in] x value of the variable 43 | * \param[out] err error to be returned 44 | * \return value of the Legendre polynomial 45 | * 46 | * This function is based on the routine gsl_sf_legendre_Pl_e 47 | * distributed with GSL 48 | */ 49 | static Scalar legendre_err(const int n, const Scalar x, Scalar& err) 50 | { 51 | if (n == 0) 52 | { 53 | err = Scalar(0); 54 | return Scalar(1); 55 | } 56 | else if (n == 1) 57 | { 58 | err = Scalar(0); 59 | return x; 60 | } 61 | 62 | // below Sree modified this to avoid -Wmaybe-uninitialized 63 | Scalar P0 = Scalar(1), P1 = x, P2=x; 64 | Scalar E0 = NumTraits::epsilon(); 65 | Scalar E1 = abs(x) * NumTraits::epsilon(); 66 | for (int k = 1; k < n; ++k) 67 | { 68 | P2 = ((2*k + 1) * x * P1 - k * P0) / (k + 1); 69 | err = ((2*k + 1) * abs(x) * E1 + k * E0) / (2*(k + 1)); 70 | P0 = P1; P1 = P2; 71 | E0 = E1; E1 = err; 72 | } 73 | return P2; 74 | } 75 | 76 | /** 77 | * \brief Three-term recursion identity for the Legendre derivatives 78 | * \param[in] n degree 79 | * \param[in] x value of the variable 80 | * \return value of the Legendre derivative 81 | */ 82 | static Scalar legendre_deriv(int const n, Scalar const x) 83 | { 84 | if (n == 0) 85 | { 86 | return Scalar(0); 87 | } 88 | else if (n == 1) 89 | { 90 | return Scalar(1); 91 | } 92 | 93 | Scalar P0 = Scalar(1); 94 | Scalar P1 = x; 95 | Scalar P2 = P1; 96 | Scalar dP0 = Scalar(0); 97 | Scalar dP1 = Scalar(1); 98 | Scalar dP2 = P1; 99 | 100 | for (int k = 1; k < n; ++k) 101 | { 102 | P2 = ((2*k + 1) * x * P1 - k * P0) / (k + Scalar(1)); 103 | dP2 = (2*k + 1) * P1 + dP0; 104 | P0 = P1; 105 | P1 = P2; 106 | dP0 = dP1; 107 | dP1 = dP2; 108 | } 109 | return dP2; 110 | } 111 | 112 | /** 113 | * \brief Compute derivatives of Chebyshev polynomials 114 | * \param[in] x variable 115 | * \param[in] n_ degree 116 | * \param[in] coefs Chebyshev coefficients 117 | * \return Derivative of Chebyshev polynomials 118 | */ 119 | static Scalar chebyshev_series_deriv(const Scalar x, 120 | const int n_, 121 | const Eigen::Array& coefs) 123 | { 124 | Scalar d1(0), d2(0); 125 | Scalar y2 = 2 * x; // linear term for Clenshaw recursion 126 | 127 | for (int k = n_; k >= 2; --k) 128 | { 129 | Scalar temp = d1; 130 | d1 = y2 * d1 - d2 + k * coefs(k); 131 | d2 = temp; 132 | } 133 | 134 | return y2 * d1 - d2 + coefs(1); 135 | } 136 | 137 | /** 138 | * \breif Evaluation of the Chebyshev polynomial using Clenshaw recursion 139 | * \param[in] x variable 140 | * \param[in] n_ degree 141 | * \param[in] coefs Chebyshev coefficients 142 | * \param[out] err error to be returned 143 | * \return value of Chebyshev polynomial 144 | */ 145 | static Scalar chebyshev_series(const Scalar x, 146 | const int n_, 147 | const Eigen::Array& coefs, 148 | Scalar& err) 149 | { 150 | Scalar d1(0), d2(0); 151 | Scalar absc = abs(coefs(0)); // final term for truncation error 152 | Scalar y2 = 2 * x; // linear term for Clenshaw recursion 153 | 154 | for (int k = n_; k >= 1; --k) 155 | { 156 | Scalar temp = d1; 157 | d1 = y2 * d1 - d2 + coefs(k); 158 | d2 = temp; 159 | absc += abs(coefs(k)); 160 | } 161 | 162 | err = absc * NumTraits::epsilon(); 163 | return x * d1 - d2 + coefs(0)/2.; 164 | } 165 | 166 | /** 167 | * \brief Computes the zeros of the Legendre polynomial 168 | * \param[in] m_ degree 169 | * \param[out] zeros the zeros of the Legendre polynomial 170 | */ 171 | static void legendre_zeros(const int m_, 172 | Eigen::Array& zeros) 173 | { 174 | Eigen::Array temp = Eigen::Array::Zero(m_+1); 175 | zeros(0) = Scalar(-1); 176 | zeros(1) = Scalar(1); 177 | Scalar delta, epsilon; 178 | 179 | for (int k = 1; k <= m_; ++k) 180 | { 181 | // Loop to locate zeros of P_k interlacing z_0,...,z_k 182 | for (int j = 0; j < k; ++j) 183 | { 184 | // Newton's method for P_k : 185 | // initialize solver at midpoint of (z_j, z_{j+1}) 186 | delta = 1; 187 | Scalar x_j = (zeros(j) + zeros(j+1)) / 2.; 188 | Scalar P_k = legendre_err(k, x_j, epsilon); 189 | 190 | while (abs(P_k) > epsilon && 191 | abs(delta) > NumTraits::epsilon()) 192 | { 193 | delta = P_k / legendre_deriv(k, x_j); 194 | x_j -= delta; 195 | P_k = legendre_err(k, x_j, epsilon); 196 | } 197 | temp(j) = x_j; 198 | } 199 | 200 | // Copy roots tmp_0,...,tmp_{k-1} to z_1,...z_k: 201 | zeros(k+1) = zeros(k); 202 | 203 | for (int j = 0; j < k; ++j) 204 | { 205 | zeros(j+1) = temp(j); 206 | } 207 | } 208 | } 209 | 210 | /** 211 | * \brief Computes coefficients of the Chebyshev polynomial. 212 | * \param[in] m_ degree of the Chebyshev polynomial. 213 | * \param[out] coefs coefficients of the Chebyshev polynomial. 214 | */ 215 | static void chebyshev_coefs(const int m_, 216 | Eigen::Array& coefs) 217 | { 218 | int ell = (m_ + 1)/2; 219 | Eigen::Array alpha = Eigen::Array::Zero(ell+1); 220 | Eigen::Array f = Eigen::Array::Zero(ell+1); 221 | 222 | // Care must be exercised in initalizing the constants in the definitions. 223 | // Compilers interpret expressions like "(2*k + 1.0)/(k + 2.0)" as floating 224 | // point precision, before casting to Real. 225 | 226 | f(1) = Scalar(m_+1) / Scalar(2*m_ + 3); 227 | alpha(0) = Scalar(1); // coefficient of T_{m+1} 228 | alpha(1) = -f(1); 229 | 230 | for (int k = 2; k <= ell; ++k) 231 | { 232 | f(k) = f(k-1) * (2*k - 1) * (m_ + k) / (k * (2*m_ + 2*k + 1)); 233 | alpha(k) = -f(k); 234 | 235 | for (int i = 1; i < k; ++i) 236 | { 237 | alpha(k) -= f(i) * alpha(k-i); 238 | } 239 | } 240 | 241 | for (int k = 0; k <= ell; ++k) 242 | { 243 | coefs(m_ + 1 - 2*k) = alpha(k); 244 | 245 | if (m_ >= 2*k) 246 | { 247 | coefs(m_ - 2*k) = Scalar(0); 248 | } 249 | } 250 | } 251 | 252 | /** 253 | * \brief Compute the Gauss/Kronrod abscissae 254 | * \param[in] n_ size of Gauss-Kronrod arrays 255 | * \param[in] Gauss-Legendre degree 256 | * \param[in] coefs Chebyshev coefficients 257 | * \param[out] xgk_ Gauss/Kronrod abscissae 258 | */ 259 | static void gauss_kronrod_abscissae(const int n_, 260 | const int m_, 261 | const Eigen::Array& zeros, 262 | const Eigen::Array& coefs, 263 | Eigen::Array& xgk_) 264 | { 265 | // Now from the function gauss_kronrod_abscissae 266 | Scalar delta, epsilon; 267 | 268 | for (int k = 0; k < n_ / 2; ++k) 269 | { 270 | delta = 1; 271 | 272 | // Newton's method for E_{n+1} : 273 | Scalar x_k = (zeros(m_-k) + zeros(m_+1-k))/Scalar(2); 274 | Scalar E = chebyshev_series(x_k,n_,coefs, epsilon); 275 | 276 | while (abs(E) > epsilon && 277 | abs(delta) > NumTraits::epsilon() ) 278 | { 279 | delta = E / chebyshev_series_deriv(x_k,n_,coefs); 280 | x_k -= delta; 281 | E = chebyshev_series(x_k,n_,coefs, epsilon); 282 | } 283 | 284 | xgk_(2*k) = x_k; 285 | 286 | // Copy adjacent Legendre-zero into the array: 287 | if (2*k+1 < n_) 288 | { 289 | xgk_(2*k+1) = zeros(m_-k); 290 | } 291 | } 292 | } 293 | 294 | /** 295 | * \brief Compute Gauss/Kronrod weights 296 | * \param[in] n_ size of Gauss-Kronrod arrays 297 | * \param[in] m_ Gauss-Legendre degree 298 | * \param[in] xgk_ Gauss/Kronrod abscissae 299 | * \param[out] wg_ Gauss weights 300 | * \param[out] wgk_ Kronrod weights 301 | */ 302 | static void gauss_kronrod_weights(const int& n_, 303 | const int m_, 304 | const Eigen::Array& coefs, 305 | const Eigen::Array& xgk_, 306 | Eigen::Array& wg_, 307 | Eigen::Array& wgk_) 308 | { 309 | Scalar err; 310 | 311 | // Gauss-Legendre weights: 312 | for(int k = 0; k < n_ / 2; ++k) 313 | { 314 | Scalar x = xgk_(2*k + 1); 315 | wg_(k) = (Scalar(-2) / ((m_ + 1) * legendre_deriv(m_, x) * legendre_err(m_+1, x, err))); 316 | } 317 | 318 | // The ratio of leading coefficients of P_n and T_{n+1} is computed 319 | // from the recursive formulae for the respective polynomials. 320 | Scalar F_m = Scalar(2) / Scalar(2*m_ + 1); 321 | 322 | for (int k = 1; k <= m_; ++k) 323 | { 324 | F_m *= (Scalar(2*k) / Scalar(2*k - 1)); 325 | } 326 | 327 | // Gauss-Kronrod weights: 328 | for (int k = 0; k < n_; ++k) 329 | { 330 | Scalar x = xgk_(k); 331 | 332 | if (k % 2 == 0) 333 | { 334 | wgk_(k) = F_m / (legendre_err(m_, x, err) * chebyshev_series_deriv(x,n_,coefs)); 335 | } 336 | else 337 | { 338 | wgk_(k) = (wg_(k/2) + F_m / (legendre_deriv(m_, x) * chebyshev_series(x,n_,coefs, err))); 339 | } 340 | } 341 | 342 | } 343 | 344 | /** 345 | * \brief A method ofr computing Gauss/Kronrod abscissae and weights 346 | * \param[in] m_ Gauss-Legendre degree 347 | * \param[out] xgk_ Gauss/Kronrod abscissae 348 | * \param[out] wgk_ Gauss/Kronrod weights 349 | * \param[out] xk_ Gauss abscissae 350 | * \param[out] wg_ Gauss weights 351 | * 352 | * Note that Gauss abscissae is not calculated here. 353 | */ 354 | static void computeAbscissaeAndWeights(unsigned int m_, 355 | Eigen::Array& xgk_, 356 | Eigen::Array& wgk_, 357 | Eigen::Array& xk_, 358 | Eigen::Array& wg_) 359 | { 360 | const unsigned int n_ = m_ + 1; 361 | 362 | xgk_ = Eigen::Array::Zero(n_); //2*nNodes+1 363 | wgk_ = Eigen::Array::Zero(n_); //2*nNodes+1 364 | xk_ = Eigen::Array::Zero(n_/2); //2*nNodes 365 | wg_ = Eigen::Array::Zero(n_/2); //2*nNodes 366 | 367 | // initialise the coefficients to zero 368 | Eigen::Array coefs = Eigen::Array::Zero(n_+1); 369 | Eigen::Array zeros = Eigen::Array::Zero(m_+2); 370 | 371 | legendre_zeros(m_, zeros); 372 | chebyshev_coefs(m_, coefs); 373 | gauss_kronrod_abscissae(n_, m_, zeros,coefs, xgk_); 374 | gauss_kronrod_weights(n_, m_,coefs, xgk_, wg_, wgk_ ); 375 | } 376 | }; 377 | 378 | } // namespace Eigen 379 | 380 | #endif // EIGEN_MONEGATO_H 381 | -------------------------------------------------------------------------------- /NumericalIntegration.h: -------------------------------------------------------------------------------- 1 | // This file is part of Eigen, a lightweight C++ template library 2 | // for linear algebra. 3 | // 4 | // Development work based on work from QUADPACK, Robert Piessens, et al, 5 | // and original work by Dirk Laurie, Walter Gautschi, with support by work 6 | // from John Burkardt. 7 | // 8 | // Multiprecision templating by Pavel Holoborodko and 9 | // code porting, multiprecision templating, and unit tests created by 10 | // Sreekumar Thaithara Balan, Mark Sauder, and Matt Beall 2014. 11 | // 12 | // This Source Code Form is subject to the terms of the Mozilla 13 | // Public License v. 2.0. If a copy of the MPL was not distributed 14 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 15 | 16 | #ifndef EIGEN_NUMERICAL_INTEGRATION_H 17 | #define EIGEN_NUMERICAL_INTEGRATION_H 18 | 19 | namespace Eigen 20 | { 21 | /** 22 | * \defgroup NumericalIntegration_Module 23 | * \brief This module provides an adaptive quadrature method of numerical integration. 24 | * 25 | * This module provides an adaptive quadrature method of numerical integration of the style 26 | * implemented in the QUADPACK library while offering functionality to calculate nodes/weights 27 | * for Gauss-Kronrod integration, unit tests, and support for multiprecision using mpreal 28 | * precision type. 29 | * 30 | * To use this module, add 31 | * \code 32 | * #include 33 | * \endcode 34 | * at the start of your source file. 35 | */ 36 | } 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include "ComputeGaussKronrodNodesWeights.h" 43 | #include "GaussKronrodNodesWeights.h" 44 | #include "Integrator.h" 45 | 46 | #endif // EIGEN_NUMERICAL_INTEGRATION_H 47 | -------------------------------------------------------------------------------- /Piessens.h: -------------------------------------------------------------------------------- 1 | #ifndef EIGEN_PIESSENS_H 2 | #define EIGEN_PIESSENS_H 3 | 4 | namespace Eigen 5 | { 6 | 7 | /** 8 | * \ingroup NumericalIntegration_Module 9 | * 10 | * \class Piessens 11 | * 12 | * \brief This class computes Kronrod abscissae & weights for arbitrary precision 13 | * 14 | * \tparam Scalar floating point type 15 | * 16 | * This class is based on the work by R. Piessens, et.al,published in the 17 | * journal Mathematics of Computation, Volume 28, Number 125, January, 1974. 18 | */ 19 | template 20 | class Piessens 21 | { 22 | public: 23 | 24 | /** 25 | * \brief kronrod adds n+1 points to an n-point Gaussian rule. 26 | * 27 | * This function is a C++ implementation of original work by R. Piessens, et.al, 28 | * published in the journal Mathematics of Computation, Volume 28, Number 125, 29 | * January, 1974. Where possible strucutre and variable naming convention 30 | * has been aligned to favor work of the QUADPACK Gaus-Kronrod integration 31 | * routines created by individuals of the same group. 32 | * 33 | * This function calculates the abscissas and weights of the (2n+1)-point 34 | * Gauss-Kronrod quadrature formula which is obtained from the n-point 35 | * Gauss quadrature formula with the optimal addition of (n+1)-points. 36 | * 37 | * The optimally added points are the Kronrod abscissae. The 38 | * abscissas and weights for both the Gauss and Gauss Kronrod rules 39 | * are calculated for integration over the interval (-1, +1). 40 | * 41 | * Because the quadrature formula is symmetric with respect to the origin, 42 | * only the positive abscissas are calculated. Weights corresponding to the 43 | * symetric abscissae are equal. Weights of weightGauss are calculated as well. 44 | * 45 | * Work by Dr. John Burkhardt made note that the code published in Mathematics of 46 | * Computation omitted the definition of the second Chebyshev coefficient (chebCoeff2), 47 | * and Dr. Burkhardt's contributions are reflected here with permission. 48 | * 49 | * The arrays abcsGaussKronrod, weightGaussKronrod and weightGauss contain the 50 | * positive abscissae in decreasing order, and the weights of each abscissa in 51 | * the Gauss-Kronrod and Gauss rules, respectively. 52 | * 53 | * Ported to C++/Eigen and templated for multiprecision by Mark Sauder, 54 | * Sreekumar Thaithara Balan, Matt Beall, and R. Jeff Jenkins - September 2014. 55 | * 56 | * Input Parameters: 57 | * \param[in] n, the order of the Gauss rule. 58 | * 59 | * Return Parameters: 60 | * \param[in,out] abscGaussKronrod[n+1] The Gauss-Kronrod abscissae. 61 | * \param[in,out] weightGaussKronrod[n+1] The weights for the Gauss-Kronrod rule. 62 | * \param[in,out] weightGauss[n+1] The weights for the Gauss rule. 63 | */ 64 | static void kronrod(unsigned int nNodes, 65 | Eigen::Array& abscGaussKronrod, 66 | Eigen::Array& weightGaussKronrod, 67 | Eigen::Array& weightGauss) 68 | { 69 | unsigned int arraySize = nNodes + 1; 70 | abscGaussKronrod = Eigen::Array::Zero(arraySize); 71 | weightGaussKronrod = Eigen::Array::Zero(arraySize); 72 | weightGauss = Eigen::Array::Zero(arraySize / 2); 73 | 74 | Scalar aN(0.0); 75 | Scalar d(2.0); 76 | 77 | for (size_t i = 0; i < nNodes; ++i) 78 | { 79 | aN += Scalar(1.0); 80 | d *= aN / (aN + Scalar(0.5)); 81 | } 82 | 83 | unsigned int m = (nNodes + 1) / 2; 84 | bool even = (nNodes == 2 * m); 85 | 86 | // aK is an index variable to account for calculating only the positive abscissae 87 | Scalar aK = aN; 88 | 89 | // Calculation of the Chebyshev coefficients of the orthogonal polynomial. 90 | Eigen::Array tau(m); 91 | tau(0) = (aN + Scalar(2.0)) / (Scalar(2) * aN + Scalar(3.0)); 92 | 93 | Eigen::Array betaCoeffs(m + 1); 94 | betaCoeffs(m - 1) = tau(0) - Scalar(1.0); 95 | 96 | for (size_t k = 1; k < m; ++k) 97 | { 98 | // This step accounts for both positive and negative abscissae 99 | aK += Scalar(2.0); 100 | 101 | tau(k) = ((aK - Scalar(1.0)) * aK - aN * (aN + Scalar(1.0) )) * (aK + Scalar(2.0) ) * tau(k-1) / 102 | (aK * ((aK + Scalar(3.0) ) * (aK + Scalar(2.0) ) - aN * (aN + Scalar(1.0) ))); 103 | 104 | betaCoeffs(m-k-1) = tau(k); 105 | 106 | for (size_t i = 1; i <= k; ++i) 107 | { 108 | betaCoeffs(m - k - 1) = betaCoeffs(m - k + i - 1) * tau(i - 1) + betaCoeffs(m - k - 1); 109 | } 110 | } 111 | 112 | betaCoeffs(m) = Scalar(1.); 113 | 114 | // Calculation of approximate values for the abscissae as inital values 115 | // for the Newton-Raphson iterative solution. These values are derived 116 | // from Pythagorean identities to the original code to more closely follow 117 | // the mathematics of the 1974 CoM paper. 118 | 119 | // @TODO The usage of constant Pi with fixed precision needs to be changed to the following for multiprecision 120 | //RealScalar pi = NumTraits::Pi(); 121 | 122 | Scalar s1 = sin((M_PI / Scalar(2) ) / (Scalar(2.) * aN + Scalar(1.0) )); 123 | Scalar c1 = cos((M_PI / Scalar(2) ) / (Scalar(2.) * aN + Scalar(1.0) )); 124 | 125 | Scalar s2 = sin((M_PI) / (Scalar(2.) * aN + Scalar(1.0) )); 126 | Scalar c2 = cos((M_PI) / (Scalar(2.) * aN + Scalar(1.0) )); 127 | 128 | // Coefficient for Gauss and Kronrod abscissae and weights 129 | Scalar chebCoeff1 = Scalar(1.0) - Scalar(1.0) / (Scalar(8.0) * aN * aN) + Scalar(1.0) / (Scalar(8.0) * aN * aN * aN); 130 | Scalar chebCoeff2 = Scalar(2.0) / (Scalar(2. * nNodes + 1)); 131 | 132 | for (size_t i = 1; i <= nNodes; ++i) 133 | { 134 | chebCoeff2 = Scalar(4.0) * chebCoeff2 * i / (nNodes + i); 135 | } 136 | 137 | Scalar abscK = chebCoeff1 * c1; 138 | Scalar temp(0.); 139 | 140 | // Calculation of the K-th (Kronrod) abscissa and the corresponding weight. 141 | for (size_t k = 0; k < nNodes; ++k) 142 | { 143 | abscWeightKronrod(nNodes, m, even, chebCoeff2, betaCoeffs, abscK, weightGaussKronrod(k)); 144 | abscGaussKronrod(k) = abscK; 145 | ++k; 146 | 147 | temp = c1; 148 | c1 = temp * c2 - s1 * s2; 149 | s1 = temp * s2 + s1 * c2; 150 | abscK = chebCoeff1 * c1; 151 | 152 | // Calculation of the k+1 (Gauss) abscissa and the corresponding weights. 153 | abscWeightGauss(nNodes, m, even, chebCoeff2, betaCoeffs, abscK, weightGaussKronrod(k), 154 | weightGauss(k/2)); 155 | abscGaussKronrod(k) = abscK; 156 | 157 | temp = c1; 158 | c1 = temp * c2 - s1 * s2; 159 | s1 = temp * s2 + s1 * c2; 160 | abscK = chebCoeff1 * c1; 161 | } 162 | 163 | // Add a Kronrod abscissa at the origin if n is even. 164 | if (even) 165 | { 166 | abscWeightKronrod(nNodes, m, even, chebCoeff2, betaCoeffs, abscK, weightGaussKronrod(nNodes)); 167 | } 168 | 169 | // Set the abscissa value at the origin to zero and exit the function. 170 | abscGaussKronrod(nNodes) = Scalar(0.0); 171 | return; 172 | } 173 | 174 | 175 | /** 176 | * \brief abscWeightKronrod calculates a Kronrod abscissa and weight. 177 | * 178 | * Input Parameters: 179 | * \param[in] betaCoeffs[m+1] The Chebyshev coefficients. 180 | * \param[in] chebCoeff A value needed to compute weights. 181 | * \param[in] even A boolean variable that is TRUE if n is even. 182 | * \param[in] n The order of the Gauss rule. 183 | * \param[in] m The value of ( n + 1 ) / 2. 184 | * 185 | * Input/output: 186 | * \param[in,out] abscGaussKronrod An estimate for the abscissa on input and the computed abscissa on output. 187 | * \param[in,out] weightGaussKronrod The Gauss-Kronrod weight. 188 | */ 189 | static void abscWeightKronrod(unsigned int nNodes, 190 | unsigned int m, 191 | bool even, 192 | Scalar chebCoeff, 193 | Eigen::Array betaCoeffs, 195 | Scalar& abscGaussKronrod, 196 | Scalar& weightGaussKronrod) 197 | { 198 | Scalar ai; 199 | 200 | Scalar b0(0.); 201 | Scalar b1(0.); 202 | Scalar b2(0.); 203 | 204 | Scalar d0(0.); 205 | Scalar d1(0.); 206 | Scalar d2(0.); 207 | 208 | Scalar delta(1.); 209 | Scalar dif(0.); 210 | 211 | Scalar f(0.); 212 | Scalar fd(0.); 213 | 214 | Scalar yy(0.); 215 | 216 | int i = 0; 217 | 218 | size_t iter = 0; 219 | size_t iterationLimit = 50; 220 | 221 | // Iterative process for the computation of a Kronrod abscissa. 222 | while (abs(delta) > machineEpsilon()) 223 | { 224 | ++iter; 225 | 226 | b1 = Scalar(0.0); 227 | b2 = betaCoeffs(m); 228 | 229 | yy = Scalar(4.0) * abscGaussKronrod * abscGaussKronrod - Scalar(2.0); 230 | d1 = Scalar(0.0); 231 | 232 | if (even) 233 | { 234 | ai = Scalar(m + m + 1); 235 | d2 = ai * betaCoeffs(m); 236 | dif = Scalar(2.0); 237 | } 238 | else 239 | { 240 | ai = Scalar(m + 1); 241 | d2 = Scalar(0.0); 242 | dif = Scalar(1.0); 243 | } 244 | 245 | for (size_t k = 0; k < m; ++k) 246 | { 247 | ai -= dif; 248 | i = m - (int)k - 1; 249 | b0 = b1; 250 | b1 = b2; 251 | d0 = d1; 252 | d1 = d2; 253 | b2 = yy * b1 - b0 + betaCoeffs(i); 254 | 255 | if (!even) 256 | { 257 | i += 1; 258 | } 259 | 260 | d2 = yy * d1 - d0 + ai * betaCoeffs(i); 261 | } 262 | 263 | if (even) 264 | { 265 | f = abscGaussKronrod * (b2 - b1); 266 | fd = d2 + d1; 267 | } 268 | else 269 | { 270 | f = Scalar(0.5) * (b2 - b0); 271 | fd = Scalar(4.0) * abscGaussKronrod * d2; 272 | } 273 | 274 | // Newton correction. 275 | delta = f / fd; 276 | abscGaussKronrod -= delta; 277 | 278 | if (abscGaussKronrod == Scalar(0.)) 279 | { 280 | break; 281 | } 282 | 283 | // Identify non-convergence of the iterative solver after 50 iterations 284 | if (iter > iterationLimit) 285 | { 286 | std::cout << "@abscWeightKronrod Newton-Raphson iterative abscissae solver failed."< betaCoeffs, 328 | Scalar& abscGaussKronrod, 329 | Scalar& weightGaussKronrod, 330 | Scalar& weightGauss) 331 | { 332 | Scalar ai(0.); 333 | Scalar delta(1.); 334 | 335 | Scalar p0(0.); 336 | Scalar p1(0.); 337 | Scalar p2(0.); 338 | 339 | Scalar pd0(0.); 340 | Scalar pd1(0.); 341 | Scalar pd2(0.); 342 | 343 | Scalar yy(0.); 344 | 345 | size_t iter = 0; 346 | size_t iterationLimit = 50; 347 | 348 | // Iterative process for the computation of a Gaussian abscissa. 349 | while (abs(delta) > machineEpsilon()) 350 | { 351 | ++iter; 352 | p0 = Scalar(1.); 353 | p1 = abscGaussKronrod; 354 | pd0 = Scalar(0.); 355 | pd1 = Scalar(1.); 356 | 357 | // If nNodes <= 1, initialize p2 and pd2 to avoid problems calculating delta. 358 | if (nNodes <= 1) 359 | { 360 | if (machineEpsilon() < abs(abscGaussKronrod)) 361 | { 362 | p2 = (Scalar(3.0) * (abscGaussKronrod) * (abscGaussKronrod) - Scalar(1.0)) / Scalar(2.0); 363 | pd2 = Scalar(3.0) * (abscGaussKronrod); 364 | } 365 | else 366 | { 367 | p2 = Scalar(3.0) * (abscGaussKronrod); 368 | pd2 = Scalar(3.0); 369 | } 370 | } 371 | 372 | ai = Scalar(0.0); 373 | 374 | for (size_t k = 0; k < nNodes - 1; ++k) 375 | { 376 | ai = ai + Scalar(1.0); 377 | p2 = ((ai + ai + Scalar(1.0) ) * abscGaussKronrod * p1 - ai * p0) / (ai + Scalar(1.0) ); 378 | pd2 = ((ai + ai + Scalar(1.0) ) * (p1 + abscGaussKronrod * pd1) - ai * pd0) / (ai + Scalar(1.0) ); 379 | p0 = p1; 380 | p1 = p2; 381 | pd0 = pd1; 382 | pd1 = pd2; 383 | } 384 | 385 | // Newton correction. 386 | delta = p2 / pd2; 387 | 388 | if (abscGaussKronrod == Scalar(0.0)) 389 | { 390 | abscGaussKronrod -= delta; 391 | break; 392 | } 393 | else 394 | { 395 | abscGaussKronrod -= delta; 396 | } 397 | 398 | // Identify non-convergence of the iterative solver after iteration limit. 399 | if (iter > iterationLimit) 400 | { 401 | std::cout << "@abscWeightGauss Newton-Raphson iterative abscissae solver failed."<::epsilon(); 448 | } 449 | 450 | /** 451 | * \brief A method ofr computing Gauss/Kronrod abscissae and weights 452 | * \param nNodes Gauss-Legendre degree 453 | * \param abscGaussKronrod Gauss/Kronrod abscissae 454 | * \param weightGaussKronrod Gauss/Kronrod weights 455 | * \param abscGauss Gauss abscissae 456 | * \param weightGauss Gauss weights 457 | */ 458 | static void computeAbscissaeAndWeights(unsigned int nNodes, 459 | Eigen::Array &abscGaussKronrod, 460 | Eigen::Array &weightGaussKronrod, 461 | Eigen::Array abscGauss, 462 | Eigen::Array &weightGauss) 463 | { 464 | Piessens::kronrod(nNodes,abscGaussKronrod,weightGaussKronrod,weightGauss); 465 | abscGauss = Eigen::Array::Zero(abscGauss.rows()); 466 | } 467 | }; 468 | 469 | }//namespace Eigen 470 | #endif //EIGEN_PIESSENS_H 471 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/tbs1980/NumericalIntegration.svg?branch=master)](https://travis-ci.org/tbs1980/NumericalIntegration) 2 | 3 | # C++ Numerical Integration 4 | 5 | #### A C++ header-only, precision-independent library for performing numerical integration. This project is intended to be easily utilized in conjunction with the [Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page) C++ library. (For a very simple way to incorporate this Numerical Integration capability as one of the unsupported submodules in your normal Eigen package, just clone our fork of the eigen library from this [Bitbucket Repository](https://bitbucket.org/tbs1980/eigen-numerical-integration-module) and use the normal commands install it!) 6 | 7 | $ hg clone ssh://hg@bitbucket.org/tbs1980/eigen-numerical-integration-module 8 | $ cd eigen-numerical-integration-module/ 9 | $ mkdir build 10 | $ cd build 11 | $ cmake .. 12 | $ make 13 | $ sudo make install 14 | 15 | ![Gaussian quadrature](./gauss_quadrature.png) 16 | 17 | Adaptive Quadrature Numerical Integration routine in the Gauss Kronrod method capable of multiprecision calculation of Gauss Kronrod nodes/weights utilizing Laurie/Gautschi and Piessens'/Patterson's methods for the desired number of nodes/ruleset for the quadrature calculations. Considerations have also been also paid in this effort to allow the future integration of the additional QUADPACK routines. 18 | 19 | The original QUADPACK FORTRAN77 code can be found here: 20 | (http://www.netlib.org/quadpack/) 21 | 22 | Note: The naming of functions and variable has been adapted to favor either the associated 23 | journal publications' naming or simply better descriptive names over the original 24 | QUADPCK FORTRAN77 source code. 25 | 26 | ## Gauss-Kronrod Node/Weight Calculations 27 | 28 | C++ functionality has been created for the calculation of Gauss-Kronrod Quadrature Weights and Abscissa based on previous work by Dirk Laurie, Walter Gautschi, and Robert Piessens', et. al. This work has also been templated/extended to allow multiple precision by Pavel Holoborodko, Sreekumar Thaitara Balan, Mark Sauder, and Matt Beall. Additional contribution to the Piessens' method for calculations of the nodes/weights was provided by John Burkardt. 29 | 30 | Laurie's (a.k.a. Golub-Welsch), algorithm as implemented is outlined in the following publication: 31 | 32 | Calculation of Gauss-Kronrod Quadrature Rules, Dirk P. Laurie 33 | Mathematics of Computation, Volume 66, Number 219, July 1997, Pages 1133-1145 34 | S 0025-5718(97)00861-2: 35 | 36 | Walter Gautschi's OPQ Matlab library and the work cited above can be found at: 37 | 38 | https://www.cs.purdue.edu/archives/2002/wxg/codes/OPQ.html, 39 | Orthogonal Polynomials, Quadrature, and Approximation: Computational Methods and Software (in Matlab), 40 | can be found at: https://www.cs.purdue.edu/homes/wxg/Madrid.pdf 41 | 42 | Monegato method used in [quadpackcpp](http://quadpackpp.sourceforge.net/) is under development 43 | 44 | Some remarks on the construction of extended Gaussian quadrature rules", Giovanni Monegato, 45 | Math. Comp., Vol. 32 (1978) pp. 247-252. http://www.jstor.org/stable/2006272 . 46 | 47 | The capabilities of this library have been greatly expanded through multiprecision templating via MPFRC++. The homepage of MPFRC++ can be found here: 48 | (http://www.holoborodko.com/pavel/mpfr/) 49 | 50 | 51 | ## Requirements 52 | 53 | * [Eigen library](http://eigen.tuxfamily.org/index.php?title=Main_Page) 54 | 55 | (If extended precision is needed, as will be the case for computing the Gauss-Kronrod nodes/weights or if desired for integration computations, MPFR C++ will also be required.) 56 | 57 | * [The GNU Multiple Precision Arithmetic Library](https://gmplib.org/) 58 | * [The GNU MPFR Library](http://www.mpfr.org/) 59 | * [MPFR C++](http://www.holoborodko.com/pavel/mpfr/) 60 | 61 | Debian-based linux users can install dependencies with aptitude package manager: 62 | 63 | $sudo apt-get install libeigen3-dev 64 | 65 | (and if your application requires extended precision) 66 | 67 | $sudo apt-get install libmpfrc++-dev 68 | 69 | ## Compilation 70 | 71 | A compile script has been added to the top level directory, from a terminal you may simply run: ./compile.sh 72 | 73 | 74 | (The following compilation flags must be passed) 75 | 76 | * -DEIGEN3_INCLUDE_DIR 77 | * -DGMP_ROOT 78 | * -DMPFR_ROOT 79 | * -DMPFRCPP_ROOT 80 | 81 | $ mkdir build 82 | $ cd build 83 | $ cmake -DEIGEN3_INCLUDE_DIR=path_to_Eigen3 -DGMP_ROOT=path_GMP_root_dir -DMPFR_ROOT=path_to_MPFR_root_dir -DMPFRCPP_ROOT=path_to_MPFRC++_root_dir path_to_GaussKronrod 84 | $ make 85 | 86 | For example, 87 | 88 | $ cmake ../ -DEIGEN3_INCLUDE_DIR=/arxiv/libraries/ubuntu/gcc/eigen-3.2.1/include/eigen3 -DGMP_ROOT=/arxiv/libraries/ubuntu/gcc/gmp-6.0.0 -DMPFR_ROOT=/arxiv/libraries/ubuntu/gcc/mpfr-3.1.2 -DMPFRCPP_ROOT=/arxiv/libraries/ubuntu/gcc/mpfrc++-3.5.9 89 | $ make 90 | 91 | ## Multiprecision Usage Note: 92 | 93 | When utilizing this library for precision higher than 53 bits, (double precision), the Gauss-Kronrod nodes must be computed at run-time by calling the QuadratureKronrod::computeNodesAndWeights() method. This is due to the default precision value of long double and mpreal types at the initialization of the static arrays used to store the Gauss-Kronrod nodes and weights. Two details are at play, 1) using long doubles requires the array initialization values to be appended with an "L" for the compiler to invoke higher than double precision during initialization, and 2) when initialized, the default precision of mpreal types is 53 bits, therefore the tabulated values are truncated to double precision and values at the arbitrary desired level of precision should be recomputed at the beginning of the runtime integration. 94 | 95 | The way to work around this is to call the computeNodesAndWeights() method once at the beginning of your program. 96 | 97 | ## Contributing to NumericalIntegration project 98 | 99 | Contributions are most welcome :smile: . Please submit a pull request or use the [issues](https://github.com/tbs1980/NumericalIntegration/issues) facility to raise any comments :+1: . 100 | 101 | (You can let people know that this Repository was useful to you by clicking the "Star" in the upper right of the repository home page!) 102 | 103 | ## Credits 104 | 105 | Here's an alphabetical list: (note to contributors: do add yourself!) 106 | 107 | name | contributions 108 | -----|-------------- 109 | Sreekumar T. Balan | Laurie-Gautschi and Monegato methods 110 | Matt Beall | Adaptive quadrature and Piessens method 111 | Mark Sauder | Adaptive quadrature, Piessens method, unit-tests 112 | -------------------------------------------------------------------------------- /cmake/FindEigen3.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Eigen3 lib 2 | # 3 | # This module supports requiring a minimum version, e.g. you can do 4 | # find_package(Eigen3 3.1.2) 5 | # to require version 3.1.2 or newer of Eigen3. 6 | # 7 | # Once done this will define 8 | # 9 | # EIGEN3_FOUND - system has eigen lib with correct version 10 | # EIGEN3_INCLUDE_DIR - the eigen include directory 11 | # EIGEN3_VERSION - eigen version 12 | 13 | # Copyright (c) 2006, 2007 Montel Laurent, 14 | # Copyright (c) 2008, 2009 Gael Guennebaud, 15 | # Copyright (c) 2009 Benoit Jacob 16 | # Redistribution and use is allowed according to the terms of the 2-clause BSD license. 17 | 18 | if(NOT Eigen3_FIND_VERSION) 19 | if(NOT Eigen3_FIND_VERSION_MAJOR) 20 | set(Eigen3_FIND_VERSION_MAJOR 2) 21 | endif(NOT Eigen3_FIND_VERSION_MAJOR) 22 | if(NOT Eigen3_FIND_VERSION_MINOR) 23 | set(Eigen3_FIND_VERSION_MINOR 91) 24 | endif(NOT Eigen3_FIND_VERSION_MINOR) 25 | if(NOT Eigen3_FIND_VERSION_PATCH) 26 | set(Eigen3_FIND_VERSION_PATCH 0) 27 | endif(NOT Eigen3_FIND_VERSION_PATCH) 28 | 29 | set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") 30 | endif(NOT Eigen3_FIND_VERSION) 31 | 32 | macro(_eigen3_check_version) 33 | file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) 34 | 35 | string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") 36 | set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") 37 | string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") 38 | set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") 39 | string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") 40 | set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") 41 | 42 | set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) 43 | if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) 44 | set(EIGEN3_VERSION_OK FALSE) 45 | else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) 46 | set(EIGEN3_VERSION_OK TRUE) 47 | endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) 48 | 49 | if(NOT EIGEN3_VERSION_OK) 50 | 51 | message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " 52 | "but at least version ${Eigen3_FIND_VERSION} is required") 53 | endif(NOT EIGEN3_VERSION_OK) 54 | endmacro(_eigen3_check_version) 55 | 56 | if (EIGEN3_INCLUDE_DIR) 57 | 58 | # in cache already 59 | _eigen3_check_version() 60 | set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) 61 | 62 | else (EIGEN3_INCLUDE_DIR) 63 | 64 | find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library 65 | PATHS 66 | ${CMAKE_INSTALL_PREFIX}/include 67 | ${KDE4_INCLUDE_DIR} 68 | PATH_SUFFIXES eigen3 eigen 69 | ) 70 | 71 | if(EIGEN3_INCLUDE_DIR) 72 | _eigen3_check_version() 73 | endif(EIGEN3_INCLUDE_DIR) 74 | 75 | include(FindPackageHandleStandardArgs) 76 | find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) 77 | 78 | mark_as_advanced(EIGEN3_INCLUDE_DIR) 79 | 80 | endif(EIGEN3_INCLUDE_DIR) 81 | 82 | -------------------------------------------------------------------------------- /cmake/FindGMP.cmake: -------------------------------------------------------------------------------- 1 | # Try to find the GNU Multiple Precision Arithmetic Library (GMP) 2 | # See http://gmplib.org/ 3 | 4 | if (GMP_INCLUDES AND GMP_LIBRARIES) 5 | set(GMP_FIND_QUIETLY TRUE) 6 | endif (GMP_INCLUDES AND GMP_LIBRARIES) 7 | 8 | find_path(GMP_INCLUDES 9 | NAMES 10 | gmp.h 11 | PATHS 12 | ${GMP_ROOT}/include 13 | ${INCLUDE_INSTALL_DIR} 14 | ) 15 | 16 | #message("GMP_INCLUDES ${GMP_INCLUDES}") 17 | 18 | find_library(GMP_LIBRARIES gmp PATHS $ENV{GMPDIR} ${GMP_ROOT}/lib ${LIB_INSTALL_DIR}) 19 | 20 | include(FindPackageHandleStandardArgs) 21 | find_package_handle_standard_args(GMP DEFAULT_MSG 22 | GMP_INCLUDES GMP_LIBRARIES) 23 | mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) 24 | -------------------------------------------------------------------------------- /cmake/FindMPFR.cmake: -------------------------------------------------------------------------------- 1 | # Try to find the MPFR library 2 | # See http://www.mpfr.org/ 3 | # 4 | # This module supports requiring a minimum version, e.g. you can do 5 | # find_package(MPFR 2.3.0) 6 | # to require version 2.3.0 to newer of MPFR. 7 | # 8 | # Once done this will define 9 | # 10 | # MPFR_FOUND - system has MPFR lib with correct version 11 | # MPFR_INCLUDES - the MPFR include directory 12 | # MPFR_LIBRARIES - the MPFR library 13 | # MPFR_VERSION - MPFR version 14 | 15 | # Copyright (c) 2006, 2007 Montel Laurent, 16 | # Copyright (c) 2008, 2009 Gael Guennebaud, 17 | # Copyright (c) 2010 Jitse Niesen, 18 | # Redistribution and use is allowed according to the terms of the BSD license. 19 | 20 | # Set MPFR_INCLUDES 21 | 22 | find_path(MPFR_INCLUDES 23 | NAMES 24 | mpfr.h 25 | PATHS 26 | $ENV{GMPDIR} 27 | ${MPFR_ROOT}/include 28 | ${INCLUDE_INSTALL_DIR} 29 | ) 30 | 31 | # Set MPFR_FIND_VERSION to 1.0.0 if no minimum version is specified 32 | 33 | if(NOT MPFR_FIND_VERSION) 34 | if(NOT MPFR_FIND_VERSION_MAJOR) 35 | set(MPFR_FIND_VERSION_MAJOR 1) 36 | endif(NOT MPFR_FIND_VERSION_MAJOR) 37 | if(NOT MPFR_FIND_VERSION_MINOR) 38 | set(MPFR_FIND_VERSION_MINOR 0) 39 | endif(NOT MPFR_FIND_VERSION_MINOR) 40 | if(NOT MPFR_FIND_VERSION_PATCH) 41 | set(MPFR_FIND_VERSION_PATCH 0) 42 | endif(NOT MPFR_FIND_VERSION_PATCH) 43 | 44 | set(MPFR_FIND_VERSION "${MPFR_FIND_VERSION_MAJOR}.${MPFR_FIND_VERSION_MINOR}.${MPFR_FIND_VERSION_PATCH}") 45 | endif(NOT MPFR_FIND_VERSION) 46 | 47 | 48 | if(MPFR_INCLUDES) 49 | 50 | # Set MPFR_VERSION 51 | 52 | file(READ "${MPFR_INCLUDES}/mpfr.h" _mpfr_version_header) 53 | 54 | string(REGEX MATCH "define[ \t]+MPFR_VERSION_MAJOR[ \t]+([0-9]+)" _mpfr_major_version_match "${_mpfr_version_header}") 55 | set(MPFR_MAJOR_VERSION "${CMAKE_MATCH_1}") 56 | string(REGEX MATCH "define[ \t]+MPFR_VERSION_MINOR[ \t]+([0-9]+)" _mpfr_minor_version_match "${_mpfr_version_header}") 57 | set(MPFR_MINOR_VERSION "${CMAKE_MATCH_1}") 58 | string(REGEX MATCH "define[ \t]+MPFR_VERSION_PATCHLEVEL[ \t]+([0-9]+)" _mpfr_patchlevel_version_match "${_mpfr_version_header}") 59 | set(MPFR_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") 60 | 61 | set(MPFR_VERSION ${MPFR_MAJOR_VERSION}.${MPFR_MINOR_VERSION}.${MPFR_PATCHLEVEL_VERSION}) 62 | 63 | # Check whether found version exceeds minimum version 64 | 65 | if(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) 66 | set(MPFR_VERSION_OK FALSE) 67 | message(STATUS "MPFR version ${MPFR_VERSION} found in ${MPFR_INCLUDES}, " 68 | "but at least version ${MPFR_FIND_VERSION} is required") 69 | else(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) 70 | set(MPFR_VERSION_OK TRUE) 71 | endif(${MPFR_VERSION} VERSION_LESS ${MPFR_FIND_VERSION}) 72 | 73 | endif(MPFR_INCLUDES) 74 | 75 | # Set MPFR_LIBRARIES 76 | 77 | find_library(MPFR_LIBRARIES mpfr PATHS $ENV{GMPDIR} ${MPFR_ROOT}/lib ${LIB_INSTALL_DIR}) 78 | 79 | # Epilogue 80 | 81 | include(FindPackageHandleStandardArgs) 82 | find_package_handle_standard_args(MPFR DEFAULT_MSG 83 | MPFR_INCLUDES MPFR_LIBRARIES MPFR_VERSION_OK) 84 | mark_as_advanced(MPFR_INCLUDES MPFR_LIBRARIES) 85 | -------------------------------------------------------------------------------- /cmake/FindMPFRCPP.cmake: -------------------------------------------------------------------------------- 1 | find_path(MPFRCPP_INCLUDES 2 | NAMES 3 | mpreal.h 4 | PATHS 5 | ${MPFRCPP_ROOT} 6 | ${INCLUDE_INSTALL_DIR} 7 | ) 8 | 9 | 10 | include(FindPackageHandleStandardArgs) 11 | find_package_handle_standard_args(MPFRCPP DEFAULT_MSG MPFRCPP_INCLUDES) 12 | mark_as_advanced(MPFRCPP_INCLUDES) 13 | -------------------------------------------------------------------------------- /cmake/FindQuantLib.cmake: -------------------------------------------------------------------------------- 1 | if (QuantLib_INCLUDES AND QuantLib_LIBRARIES) 2 | set(QuantLib_FIND_QUIETLY TRUE) 3 | endif (QuantLib_INCLUDES AND QuantLib_LIBRARIES) 4 | 5 | find_path(QuantLib_INCLUDES 6 | NAMES 7 | ql/version.hpp 8 | PATHS 9 | ${QuantLib_ROOT}/include 10 | ${INCLUDE_INSTALL_DIR} 11 | ) 12 | 13 | find_library(QuantLib_LIBRARIES QuantLib PATHS $ENV{QuantLibDIR} ${QuantLib_ROOT}/lib ${LIB_INSTALL_DIR}) 14 | 15 | include(FindPackageHandleStandardArgs) 16 | find_package_handle_standard_args(QuantLib DEFAULT_MSG 17 | QuantLib_INCLUDES QuantLib_LIBRARIES) 18 | mark_as_advanced(QuantLib_INCLUDES QuantLib_LIBRARIES) 19 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | cd test 2 | mkdir -p testOutput 3 | cd .. 4 | mkdir -p build 5 | cd build 6 | cmake .. 7 | cmake -G Sublime\ Text\ 2\ -\ Unix\ Makefiles .. 8 | cd .. 9 | make -j7 -C build 10 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | find_package(Doxygen) 4 | 5 | if(DOXYGEN_FOUND) 6 | set (doxygenConfigFileIn "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in") 7 | set (doxygenConfigFile "${CMAKE_CURRENT_BINARY_DIR}/NumericalIntegration.dox") 8 | configure_file(${doxygenConfigFileIn} ${doxygenConfigFile} @ONLY) 9 | add_custom_target (Docs 10 | ${DOXYGEN_EXECUTABLE} ${doxygenConfigFile} 11 | DEPENDS ${doxygenConfigFile} 12 | VERBATIM) 13 | endif(DOXYGEN_FOUND) 14 | -------------------------------------------------------------------------------- /doc/ImportantPapers.md: -------------------------------------------------------------------------------- 1 | # Numerical Integration 2 | 3 | ## Published articles 4 | 5 | Here is a collection of important works on numercal integration 6 | 7 | 1. A.S. Kronrod (1965). Nodes and weights of quadrature formulas. 8 | Sixteen-place tables. New York: Consultants Bureau 9 | (Authorized translation from the Russian) 10 | 11 | 2. D. P. Laurie (1997). Calculation of Gauss-Kronrod Quadrature Rules. 12 | Mathematics of Computation, 66(219), 1133-1145 13 | [link](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.192.3713) 14 | 15 | 3. R. Piessens, M. Branders (1974). A Note on the Optimal Addition of Abscissas 16 | to Quadrature Formulas of Gauss and Lobatto. 17 | Mathematics of Computation, 28(125), 135-139 18 | 19 | 4. G. Monegato (1978). Some remarks on the construction of extended Gaussian 20 | quadrature rules. Mathematics of Computation, 32(141), 247-252 21 | 22 | 5. W. Gautschi (2002). OPQ: a Matlab suite of programs for generating orthogonal 23 | polynomials and related quadrature rules. 24 | 25 | 6. W. Gautschi (2004). Orthogonal Polynomials: Computation and Approximation. 26 | USA: Oxford University Press. 27 | 28 | 7. R. Piessens, E. de Doncker–Kapenga, C. Uberhuber, D. Kahaner (1983). QUADPACK, 29 | A Subroutine Package for Automatic Integration Springer-Verlag. 30 | 31 | 8. F. Calio, W. Gautschi, E. Marchetti (1986). On Computing Gauss-Kronrod Quadrature Formulae. Mathematics of Computation 47(176), 639-650. 32 | 33 | 9. S. Elhay, J. Kautsky, (1992). Generalized Kronrod Patterson Type Imbedded Quadratures. Applications of Mathematics, 37(2), 81-103. 34 | 35 | 10. G. H. Golub, J. H. Welsch (1969). Calculation of Gauss Quadrature Rules. Mathematics of Computation, 23(106), 221-230 +s1-s10 36 | 37 | 11. W. Gautschi, (1970), On the Construction of Gaussian Quadrature Rules from Modified Moments. Mathematics of Computation, 24(110), 245-260 38 | 39 | 12. F. Calió, W. Gautschi, E. Marchetti (1986). On Computing Gauss-Kronrod Quadrature Formulae. Mathematics of Computation, 47 (176), 639-650 40 | 41 | 42 | 43 | ## Misc links on the internet 44 | 45 | Here are some very useful links. 46 | 47 | 1. [Pavel's blog on Gauss-Kronrod Quadrature Nodes and Weights](http://www.advanpix.com/2011/11/07/gauss-kronrod-quadrature-nodes-weights/) 48 | 49 | 2. [Pavel's blog on Numerical Integration](http://www.holoborodko.com/pavel/numerical-methods/numerical-integration/) 50 | 51 | 3. [QUADPACK](http://www.netlib.org/quadpack/) 52 | 53 | 4. [quadpack++](http://quadpackpp.sourceforge.net/) 54 | 55 | 56 | 57 | ______________________________________________________________________________________________ 58 | 59 | Below is additional literature that is interesting and useful but is not as directly related to the Laurie-Gautschi or Piessens-Patterson comparison. 60 | 61 | 1. Shikang Li (1996). Kronrod Extension of Generalized Gauss-Radau and Gauss Lobatto Formulae. Rocky Mountain Journal of Mathematics, Volume 26, Number 4, Fall 1996, pages 1455-1472 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/AMMAR CALVETTI REICHEL Computation of Gauss-Kronrod Quadrature Rules with Non-Positive Weights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/AMMAR CALVETTI REICHEL Computation of Gauss-Kronrod Quadrature Rules with Non-Positive Weights.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/BOND A New Integration Method Providing the Accuracy of Gauss-Legendre with Error Estimation Capability.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/BOND A New Integration Method Providing the Accuracy of Gauss-Legendre with Error Estimation Capability.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/CALIO GAUTSCHI MARCHETTI On Computing Gauss Kronrod Quadrature Formulae.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/CALIO GAUTSCHI MARCHETTI On Computing Gauss Kronrod Quadrature Formulae.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/COMPUTATION OF GAUSS-KRONROD QUADRATURE RULES WITH NON-POSITIVE WEIGHTS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/COMPUTATION OF GAUSS-KRONROD QUADRATURE RULES WITH NON-POSITIVE WEIGHTS.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/ELHAY KAUTSKI Generalized Kronrod Patterson type imbedded quadratures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/ELHAY KAUTSKI Generalized Kronrod Patterson type imbedded quadratures.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/GOLUB WELSCH Computation of Gauss Quadrature Rules.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/GOLUB WELSCH Computation of Gauss Quadrature Rules.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/GONNET A Review of Error Estimation in Adaptive Quadrature.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/GONNET A Review of Error Estimation in Adaptive Quadrature.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/GONNET Adaptive Quadrature Re-Revisited.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/GONNET Adaptive Quadrature Re-Revisited.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/HERNANDEZ YSERN LOGOMACINO Generalized Stieltjes Polynomials and Rational Gauss-Kronrod Quadrature.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/HERNANDEZ YSERN LOGOMACINO Generalized Stieltjes Polynomials and Rational Gauss-Kronrod Quadrature.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/LAURIE Calculation of Gauss-Kronrod Quadrature Rules.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/LAURIE Calculation of Gauss-Kronrod Quadrature Rules.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/LI Kronrod Extension of Generalized Gauss Radau and Gauss Lobatto Formulae.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/LI Kronrod Extension of Generalized Gauss Radau and Gauss Lobatto Formulae.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/LUCAS STONE Evaluating infinite integrals involving Bessel Functions of Arbitrary Order.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/LUCAS STONE Evaluating infinite integrals involving Bessel Functions of Arbitrary Order.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/NEWMAN Computational Physics AppendixC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/NEWMAN Computational Physics AppendixC.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/NEWMAN Computational Physics Chapter 5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/NEWMAN Computational Physics Chapter 5.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/Piessens_Kronrod_Nodes_and_Weigths_1974_Comp_of_Mathematics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/Piessens_Kronrod_Nodes_and_Weigths_1974_Comp_of_Mathematics.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/SMYTH Numerical Integration.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/SMYTH Numerical Integration.pdf -------------------------------------------------------------------------------- /doc/Referenced and Topic Study Literature/VLADISLAV Construction of Gauss-Kronrod-Hermite Quadrature and Cubature Formulas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/doc/Referenced and Topic Study Literature/VLADISLAV Construction of Gauss-Kronrod-Hermite Quadrature and Cubature Formulas.pdf -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(Integration Integration.cpp) 2 | 3 | target_link_libraries(Integration ${ALL_LIBS}) 4 | -------------------------------------------------------------------------------- /examples/Integration.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | *\file Integration.cpp 3 | * An example illustrating the use of numerical integration module in Eigen. 4 | */ 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | /** 12 | * We consider the example from: 13 | * 14 | * http://www.gnu.org/software/gsl/manual/html_node/Numerical-integration-examples.html 15 | * 16 | * int_0^1 x^{-1/2} log(x) dx = -4 17 | * 18 | * The integrator expects the user to provide a functor as shown below. 19 | */ 20 | 21 | template 22 | class IntegrandExampleFunctor 23 | { 24 | public: 25 | IntegrandExampleFunctor(const Scalar alpha) 26 | : m_alpha(alpha) 27 | { 28 | assert(alpha>0); 29 | } 30 | 31 | Scalar operator()(const Scalar x) const 32 | { 33 | assert(x>0); 34 | return log(m_alpha*x) / sqrt(x); 35 | } 36 | 37 | void setAlpha(const Scalar alpha) 38 | { 39 | m_alpha = alpha; 40 | } 41 | 42 | private: 43 | Scalar m_alpha; 44 | }; 45 | 46 | int main(void) 47 | { 48 | // Define the scalar type. 49 | // typedef float Scalar; 50 | // typedef double Scalar; 51 | // typedef long double Scalar; 52 | typedef mpfr::mpreal Scalar; 53 | Scalar::set_default_prec(256); 54 | 55 | // Define the functor. 56 | Scalar alpha = Scalar(1.); 57 | IntegrandExampleFunctor inFctr(alpha); 58 | 59 | // Define the integrator. 60 | Eigen::Integrator eigIntgtor(200); 61 | 62 | // Define a quadrature rule. 63 | Eigen::Integrator::QuadratureRule quadratureRule = Eigen::Integrator::GaussKronrod61; 64 | 65 | // Define the desired absolute and relative errors. 66 | Scalar desAbsErr = Scalar(0.); 67 | Scalar desRelErr = Eigen::NumTraits::epsilon() * Scalar(50.); 68 | 69 | // Integrate. 70 | Scalar result = eigIntgtor.quadratureAdaptive(inFctr, Scalar(0.), Scalar(1.), desAbsErr, desRelErr, quadratureRule); 71 | 72 | // Expected result. 73 | Scalar expected = Scalar(-4.); 74 | 75 | // Print output. 76 | int outputPrecision = 18; 77 | std::cout << std::fixed; 78 | std::cout << "result = " << std::setprecision(outputPrecision) << result << std::endl; 79 | std::cout << "exact result = " << std::setprecision(outputPrecision) << expected << std::endl; 80 | std::cout << "actual error = " << std::setprecision(outputPrecision) << (expected-result) << std::endl; 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /gauss_quadrature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tbs1980/NumericalIntegration/b7947c91d5e2269f82152d497eccb3c469df4968/gauss_quadrature.png -------------------------------------------------------------------------------- /generateQK.sh: -------------------------------------------------------------------------------- 1 | cd build 2 | make generateGaussKronrodQuadrature 3 | cd .. 4 | ./build/bin/generateGaussKronrodQuadrature 5 | cp ./test/testOutput/GaussKronrodNodesWeights.h ./GaussKronrodNodesWeights.h 6 | 7 | -------------------------------------------------------------------------------- /progress/comparison_with_QuantLib.md: -------------------------------------------------------------------------------- 1 | I compared the [GaussKronrodNonAdaptive](https://github.com/lballabio/quantlib/blob/master/QuantLib/ql/math/integrals/kronrodintegral.hpp) with our implementation as a preliminary test. According the QuantLib documentation, the method uses 15 points Gauss-Kronrod integration rule. I compred the test functions in [QuantLib test suite](https://github.com/lballabio/quantlib/blob/master/QuantLib/test-suite/integrals.cpp) and the resutls are below. The values are | expected - calculated |. The ouput is done using the following statement in C++ 2 | 3 | std::cout<<"Normal Distribution, |calculated - expected| = " 4 | <