Oftentimes (for instance, when calculating the transient response, or using finite elements), it is required to reduce the integration interval in order to improve, or verify, convergence. On the other hand, using too small a time (or space) step will be a waste of time and not improve accuracy (at best).
This program will continually adjust the integration step automatically, until the accuracy specified is met. Only a single integral can be processed though, not a system of equations. The Runge- Kutta approximations for groups of equations are in the transient response section.
Both the trapezoidal and Simpson rules are used to evaluate the integral; if it contributes more than its fair share of error, it is split in two subintervals and its value calculated more carefully. Segmentation continues until the accuracy specified is achieved. Additional calculations are only carried out in subintervals where it will make a difference- that's the advantage of this method.
Javascript has been used to write this program, so that it will be accessible from any place; it is child's play to translate to any language which supports procedures, parameters and local variables.
The accuracy specified is a pessimistic value; This represents the maximum allowable error- the actual is almost certain to be much lower. Of course, improved accuracy requires a longer time, and the program will eventually fail, if the language does not support the precision requested. The number of subintervals employed is also shown, to indicate the computational load involved if seeking a smaller error.
In days gone by, you would strive to save precious stack space by minimising the number of parameters or local variables, even if this meant calculating the same result over and over again. If the integrand is a complicated function, there is also the option of passing its values already calculated as parameters. In times of Gigahertz and Megabytes (though not all of that will be available to your program), these concerns are increasigly irrelevant: Even complicated functions are unlikely to weary the incorporated numerical coprocessor too much.
The algorithm naturally lends itself to recursion, so you are either going to love it, or hate it. Here is the source code for this program snippet.