fresnel.js (4349B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * 19 * ## Notice 20 * 21 * The original C code, long comment, copyright, license, and constants are from [Cephes]{@link http://www.netlib.org/cephes}. The implementation follows the original, but has been modified for JavaScript. 22 * 23 * ```text 24 * Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier 25 * 26 * Some software in this archive may be from the book _Methods and Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster International, 1989) or from the Cephes Mathematical Library, a commercial product. In either event, it is copyrighted by the author. What you see here may be used freely but it comes with no support or guarantee. 27 * 28 * Stephen L. Moshier 29 * moshier@na-net.ornl.gov 30 * ``` 31 */ 32 33 'use strict'; 34 35 // MODULES // 36 37 var sincos = require( './../../../../base/special/sincos' ); 38 var abs = require( './../../../../base/special/abs' ); 39 var HALF_PI = require( '@stdlib/constants/float64/half-pi' ); 40 var PI = require( '@stdlib/constants/float64/pi' ); 41 var polyS = require( './rational_psqs.js' ); 42 var polyC = require( './rational_pcqc.js' ); 43 var polyF = require( './rational_pfqf.js' ); 44 var polyG = require( './rational_pgqg.js' ); 45 46 47 // VARIABLES // 48 49 // Array for storing sincos evaluation: 50 var sc = [ 0.0, 0.0 ]; // WARNING: not thread safe 51 52 53 // MAIN // 54 55 /** 56 * Computes the Fresnel integrals S(x) and C(x). 57 * 58 * ## Method 59 * 60 * Evaluates the Fresnel integrals 61 * 62 * ```tex 63 * \begin{align*} 64 * \operatorname{S}(x) &= \int_0^x \sin\left(\frac{\pi}{2} t^2\right)\,\mathrm{d}t, \\ 65 * \operatorname{C}(x) &= \int_0^x \cos\left(\frac{\pi}{2} t^2\right)\,\mathrm{d}t. 66 * \end{align*} 67 * ``` 68 * 69 * The integrals are evaluated by a power series for \\( x < 1 \\). For \\( x >= 1 \\) auxiliary functions \\( f(x) \\) and \\( g(x) \\) are employed such that 70 * 71 * ```tex 72 * \begin{align*} 73 * \operatorname{C}(x) &= \frac{1}{2} + f(x) \sin\left( \frac{\pi}{2} x^2 \right) - g(x) \cos\left( \frac{\pi}{2} x^2 \right), \\ 74 * \operatorname{S}(x) &= \frac{1}{2} - f(x) \cos\left( \frac{\pi}{2} x^2 \right) - g(x) \sin\left( \frac{\pi}{2} x^2 \right). 75 * \end{align*} 76 * ``` 77 * 78 * ## Notes 79 * 80 * - Relative error on test interval \\( \[0,10\] \\): 81 * 82 * | arithmetic | function | # trials | peak | rms | 83 * |:----------:|:--------:|:--------:|:-------:|:-------:| 84 * | IEEE | S(x) | 10000 | 2.0e-15 | 3.2e-16 | 85 * | IEEE | C(x) | 10000 | 1.8e-15 | 3.3e-16 | 86 * 87 * @private 88 * @param {(Array|TypedArray|Object)} out - destination array 89 * @param {number} x - input value 90 * @returns {(Array|TypedArray|Object)} S(x) and C(x) 91 * 92 * @example 93 * var v = fresnel( [ 0.0, 0.0 ], 0.0 ); 94 * // returns [ 0.0, 0.0 ] 95 * 96 * @example 97 * var v = fresnel( [ 0.0, 0.0 ], 1.0 ); 98 * // returns [ ~0.438, ~0.780 ] 99 * 100 * @example 101 * var v = fresnel( [ 0.0, 0.0 ], Infinity ); 102 * // returns [ ~0.5, ~0.5 ] 103 * 104 * @example 105 * var v = fresnel( [ 0.0, 0.0 ], -Infinity ); 106 * // returns [ ~-0.5, ~-0.5 ] 107 * 108 * @example 109 * var v = fresnel( [ 0.0, 0.0 ], NaN ); 110 * // returns [ NaN, NaN ] 111 */ 112 function fresnel( out, x ) { 113 var x2; 114 var xa; 115 var f; 116 var g; 117 var t; 118 var u; 119 120 xa = abs( x ); 121 x2 = xa * xa; 122 if ( x2 < 2.5625 ) { 123 t = x2 * x2; 124 out[ 0 ] = xa * x2 * polyS( t ); 125 out[ 1 ] = xa * polyC( t ); 126 } else if ( xa > 36974.0 ) { 127 out[ 1 ] = 0.5; 128 out[ 0 ] = 0.5; 129 } else { 130 // Asymptotic power series auxiliary functions for large arguments... 131 x2 = xa * xa; 132 t = PI * x2; 133 u = 1.0 / (t * t); 134 t = 1.0 / t; 135 f = 1.0 - ( u * polyF( u ) ); 136 g = t * polyG( u ); 137 t = HALF_PI * x2; 138 sincos( sc, t ); 139 t = PI * xa; 140 out[ 1 ] = 0.5 + ( ( (f*sc[0]) - (g*sc[1]) ) / t ); 141 out[ 0 ] = 0.5 - ( ( (f*sc[1]) + (g*sc[0]) ) / t ); 142 } 143 if ( x < 0.0 ) { 144 out[ 1 ] = -out[ 1 ]; 145 out[ 0 ] = -out[ 0 ]; 146 } 147 return out; 148 } 149 150 151 // EXPORTS // 152 153 module.exports = fresnel;