UNPKG

@stdlib/math-base-tools-sum-series

Version:

Compute the sum of an infinite series.

100 lines (85 loc) 2.58 kB
/** * @license Apache-2.0 * * Copyright (c) 2018 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 'use strict'; // MODULES // var abs = require( '@stdlib/math-base-special-abs' ); var EPS = require( '@stdlib/constants-float64-eps' ); // VARIABLES // var MAX_TERMS = 1000000; // MAIN // /** * Sum the elements of the series given by the supplied function. * * @param {Function} generator - series function * @param {Object} [options] - function options * @param {PositiveInteger} [options.maxTerms=1000000] - maximum number of terms to be added * @param {PositiveNumber} [options.tolerance=2.22e-16] - further terms are only added as long as the next term is greater than current term times the tolerance * @param {number} [options.initialValue=0] - initial value of the resulting sum * @returns {number} sum of all series terms * * @example * var gen = geometricSeriesGenerator( 0.9 ); * var out = sumSeries( gen ); * // returns 10.0 * * function* geometricSeriesGenerator( x ) { * var exponent = 0; * while ( true ) { * yield Math.pow( x, exponent ); * exponent += 1; * } * } */ function sumSeries( generator, options ) { var isgenerator; var tolerance; var nextTerm; var counter; var result; var opts; opts = {}; if ( arguments.length > 1 ) { opts = options; } tolerance = opts.tolerance || EPS; counter = opts.maxTerms || MAX_TERMS; result = opts.initialValue || 0; isgenerator = typeof generator.next === 'function'; if ( isgenerator === true ) { // Case A: Iterate over generator object created by a generator function... for ( nextTerm of generator ) { result += nextTerm; if ( abs(tolerance * result) >= abs(nextTerm) || --counter === 0 // eslint-disable-line no-plusplus ) { break; } } } else { // Case B: Repeatedly call function... do { nextTerm = generator(); result += nextTerm; } while ( ( abs(tolerance * result) < abs(nextTerm) ) && --counter ); // eslint-disable-line no-plusplus } return result; } // EXPORTS // module.exports = sumSeries;