Nori
|
00001 /* 00002 This file is part of Mitsuba, a physically based rendering system. 00003 00004 Copyright (c) 2007-2011 by Wenzel Jakob and others. 00005 00006 Mitsuba is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License Version 3 00008 as published by the Free Software Foundation. 00009 00010 Mitsuba is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #if !defined(__QUADRATURE_H) 00020 #define __QUADRATURE_H 00021 00022 #include <nori/common.h> 00023 #include <boost/function.hpp> 00024 00025 NORI_NAMESPACE_BEGIN 00026 00027 /** 00028 * \brief Adaptively computes the integral of a multidimensional function using 00029 * either a Gauss-Kronod (1D) or a Genz-Malik (>1D) cubature rule. 00030 * 00031 * This class is a C++ wrapper around the \c cubature code by Steven G. Johnson 00032 * (http://ab-initio.mit.edu/wiki/index.php/Cubature) 00033 * 00034 * The original implementation is based on algorithms proposed in 00035 * 00036 * A. C. Genz and A. A. Malik, "An adaptive algorithm for numeric integration 00037 * over an N-dimensional rectangular region," J. Comput. Appl. Math. 6 (4), 00038 * 295–302 (1980). 00039 * 00040 * and 00041 * 00042 * J. Berntsen, T. O. Espelid, and A. Genz, "An adaptive algorithm for the 00043 * approximate calculation of multiple integrals," ACM Trans. Math. Soft. 17 00044 * (4), 437–451 (1991). 00045 * 00046 * \ingroup libcore 00047 */ 00048 class NDIntegrator { 00049 public: 00050 typedef boost::function<void (const double *, double *)> Integrand; 00051 typedef boost::function<void (size_t, const double *, double *)> VectorizedIntegrand; 00052 00053 enum EResult { 00054 ESuccess = 0, 00055 EFailure = 1 00056 }; 00057 00058 /** 00059 * Initialize the Cubature integration scheme 00060 * 00061 * \param fDim Number of integrands (i.e. dimensions of the image space) 00062 * \param nDim Number of integration dimensions (i.e. dimensions of the 00063 * function domain) 00064 * \param maxEvals Maximum number of function evaluationn (0 means no 00065 * limit). The error bounds will likely be exceeded when the 00066 * integration is forced to stop prematurely. Note: the actual 00067 * number of evaluations may somewhat exceed this value. 00068 * \param absError Absolute error requirement (0 to disable) 00069 * \param relError Relative error requirement (0 to disable) 00070 */ 00071 NDIntegrator(size_t fDim, size_t dim, 00072 size_t maxEvals, double absError = 0, double relError = 0); 00073 00074 /** 00075 * \brief Integrate the function \c f over the rectangular domain 00076 * bounded by \c min and \c max. 00077 * 00078 * The supplied function should have the interface 00079 * 00080 * <code> 00081 * void integrand(const double *in, double *out); 00082 * </code> 00083 * 00084 * The input array \c in consists of one set of input parameters 00085 * having \c dim entries. The function is expected to store the 00086 * results of the evaluation into the \c out array using \c fDim entries. 00087 */ 00088 EResult integrate(const Integrand &f, const double *min, const double *max, 00089 double *result, double *error, size_t *evals = NULL) const; 00090 00091 /** 00092 * \brief Integrate the function \c f over the rectangular domain 00093 * bounded by \c min and \c max. 00094 * 00095 * This function implements a vectorized version of the above 00096 * integration function, which is more efficient by evaluating 00097 * the integrant in `batches'. The supplied function should 00098 * have the interface 00099 * 00100 * <code> 00101 * void integrand(int numPoints, const double *in, double *out); 00102 * </code> 00103 * 00104 * Note that \c in in is not a single point, but an array of \c numPoints points 00105 * (length \c numPoints x \c dim), and upon return the values of all \c fDim 00106 * integrands at all \c numPoints points should be stored in \c out 00107 * (length \c fDim x \c numPoints). In particular, out[i*dim + j] is the j-th 00108 * coordinate of the i-th point, and the k-th function evaluation (k<fDim) 00109 * for the i-th point is returned in out[k*npt + i]. 00110 * The size of \c numPoints will vary with the dimensionality of the problem; 00111 * higher-dimensional problems will have (exponentially) larger numbers, 00112 * allowing for the possibility of more parallelism. Currently, \c numPoints 00113 * starts at 15 in 1d, 17 in 2d, and 33 in 3d, but as the integrator 00114 * calls your integrand more and more times the value will grow. e.g. if you end 00115 * up requiring several thousand points in total, \c numPoints may grow to 00116 * several hundred. 00117 */ 00118 EResult integrateVectorized(const VectorizedIntegrand &f, const double *min, 00119 const double *max, double *result, double *error, size_t *evals = NULL) const; 00120 protected: 00121 size_t m_fdim, m_dim, m_maxEvals; 00122 double m_absError, m_relError; 00123 }; 00124 00125 NORI_NAMESPACE_END 00126 00127 #endif /* __QUADRATURE_H */