All files main.js

100% Statements 213/213
100% Branches 29/29
100% Functions 1/1
100% Lines 213/213

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 2141x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7005x 7005x 7005x 7005x 7005x 7005x 7005x 7005x 7005x 7005x 7005x 7005x 1x 1x 7004x 7005x 1x 1x 7003x 7005x 1x 1x 7002x 7005x 2x 2x 7005x 3250x 3250x 7005x 3750x 3750x 3750x 7000x 7005x 2220x 1500x 1498x 1498x 1498x 2x 2x 720x 720x 720x 720x 720x 720x 4780x 7005x 906x 906x 906x 906x 453x 453x 453x 453x 3874x 7005x 2666x 1333x 1333x 1333x 1333x 1208x 1208x 1208x 7005x 802x 802x 802x 406x 406x 406x 406x 406x 1208x 1208x 7005x 604x 604x 604x 7005x 1x 1x 1x 1x 1x  
/**
* @license Apache-2.0
*
* Copyright (c) 2026 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.
*
*
* ## Notice
*
* The following copyright and license were part of the original implementation available as part of [FreeBSD][freebsd-src]. The implementation has been modified for JavaScript.
*
* ```text
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ```
*
* [freebsd-src]: https://svnweb.freebsd.org/base/release/12.2.0/lib/msun/src/s_erff.c
*/
 
'use strict';
 
// MODULES //
 
var float64ToFloat32 = require( '@stdlib/number/float64/base/to-float32' );
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
var exp = require( '@stdlib/math/base/special/exp' );
var PINF = require( '@stdlib/constants/float32/pinf' );
var NINF = require( '@stdlib/constants/float32/ninf' );
var polyvalPP = require( './polyval_pp.js' );
var polyvalQQ = require( './polyval_qq.js' );
var polyvalPA = require( './polyval_pa.js' );
var polyvalQA = require( './polyval_qa.js' );
var polyvalRA = require( './polyval_ra.js' );
var polyvalSA = require( './polyval_sa.js' );
var polyvalRB = require( './polyval_rb.js' );
var polyvalSB = require( './polyval_sb.js' );
 
 
// VARIABLES //
 
var TINY = float64ToFloat32( 1.0e-30 );
var ONE = float64ToFloat32( 1.0 );
 
var ERX = float64ToFloat32( 8.4506291151e-01 ); // 0x3f58560b
 
var EFX = float64ToFloat32( 1.2837916613e-01 ); // 0x3e0375d4
var EFX8 = float64ToFloat32( 1.0270333290e+00 ); // 0x3f8375d4
 
var PP0 = float64ToFloat32( 1.2837916613e-01 ); // 0x3e0375d4
 
var PA0 = float64ToFloat32( -2.3621185683e-03 ); // 0xbb1acdc6
 
var RA0 = float64ToFloat32( -9.8649440333e-03 ); // 0xbc21a093
 
var RB0 = float64ToFloat32( -9.86496918e-03 ); // 0xbc21a0ae
 
 
// MAIN //
 
/**
* Evaluates the error function for a single-precision floating-point number.
*
* ## Method
*
* 1.  For `|x|` in `[0, 0.84375]`
*
*     ```tex
*     \operatorname{erf}(x) = x + x \cdot R(x^2)
*     ```
*
*     For very small `x`, a linear approximation is used to avoid underflow.
*
* 2.  For `|x|` in `[0.84375,1.25]`
*
*     ```tex
*     \operatorname{erf}(x) = \operatorname{sign}(x) \cdot (erx + P(|x| - 1) / Q(|x| - 1))
*     ```
*
* 3.  For `x` in `[1.25,1/0.35 ~ 2.857143]`
*
*     ```tex
*     \operatorname{erf}(x) = 1 - (1/x) \cdot \exp(-x \cdot x - 0.5625 + R/S)
*     ```
*
* 4.  For `x >= 1/0.35 ~ 2.857143`
*
*     ```tex
*     \operatorname{erf}(x) = \operatorname{sign}(x) \cdot (1 - tiny)
*     ```
*
* @param {number} x - input value
* @returns {number} function value
*
* @example
* var y = erff( 2.0 );
* // returns ~0.9953
*
* @example
* var y = erff( -1.0 );
* // returns ~-0.8427
*
* @example
* var y = erff( 0.0 );
* // returns 0.0
*
* @example
* var y = erff( NaN );
* // returns NaN
*/
function erff( x ) {
	var sign;
	var ax;
	var z;
	var r;
	var s;
	var y;
	var p;
	var q;
 
	// Special case: NaN
	if ( isnanf( x ) ) {
		return NaN;
	}
	// Special case: +infinity
	if ( x === PINF ) {
		return ONE;
	}
	// Special case: -infinity
	if ( x === NINF ) {
		return -ONE;
	}
	// Special case: +-0
	if ( x === 0.0 ) {
		return x;
	}
	if ( x < 0.0 ) {
		sign = true;
		ax = float64ToFloat32( -x );
	} else {
		sign = false;
		ax = float64ToFloat32( x );
	}
	// |x| < 0.84375
	if ( ax < float64ToFloat32( 0.84375 ) ) {
		if ( ax < float64ToFloat32( 1.0e-4 ) ) {
			if ( ax < float64ToFloat32( 1.0e-30 ) ) {
				// Avoid underflow:
				return float64ToFloat32( float64ToFloat32( 0.125 * float64ToFloat32( float64ToFloat32( 8.0*x ) + float64ToFloat32( EFX8*x ) ) ) ); // eslint-disable-line max-len
			}
			return float64ToFloat32( x + float64ToFloat32( EFX * x ) );
		}
		z = float64ToFloat32( x * x );
		r = float64ToFloat32( PP0 + float64ToFloat32( z*polyvalPP( z ) ) );
		s = float64ToFloat32( ONE + float64ToFloat32( z*polyvalQQ( z ) ) );
		y = float64ToFloat32( r / s );
		return float64ToFloat32( x + float64ToFloat32( x*y ) );
	}
	// 0.84375 <= |x| < 1.25
	if ( ax < float64ToFloat32( 1.25 ) ) {
		s = float64ToFloat32( ax - ONE );
		p = float64ToFloat32( PA0 + float64ToFloat32( s * polyvalPA( s ) ) );
		q = float64ToFloat32( ONE + float64ToFloat32( s * polyvalQA( s ) ) );
		if (sign) {
			return float64ToFloat32( float64ToFloat32( -ERX ) - float64ToFloat32( p / q ) ); // eslint-disable-line max-len
		}
		return float64ToFloat32( ERX + float64ToFloat32( p / q ) );
	}
	// |x| >= 4
	if ( ax >= float64ToFloat32( 4.0 ) ) {
		if ( sign ) {
			return float64ToFloat32( TINY - ONE );
		}
		return float64ToFloat32( ONE - TINY );
	}
	s = float64ToFloat32( ONE / float64ToFloat32( ax * ax ) );
 
	// |x| < 1/0.35 ~ 2.857143
	if ( ax < float64ToFloat32( 2.857142857142857 ) ) {
		r = float64ToFloat32( RA0 + float64ToFloat32( s * polyvalRA( s ) ) );
		s = float64ToFloat32( ONE + float64ToFloat32( s * polyvalSA( s ) ) );
	}
	// |x| >= 1/0.35 ~ 2.857143
	else {
		r = float64ToFloat32( RB0 + float64ToFloat32( s * polyvalRB( s ) ) );
		s = float64ToFloat32( ONE + float64ToFloat32( s * polyvalSB( s ) ) );
	}
	z = ax;
	r = float64ToFloat32(float64ToFloat32(exp(float64ToFloat32(float64ToFloat32(-z * z) - float64ToFloat32(0.5625)))) * float64ToFloat32(exp(float64ToFloat32((float64ToFloat32((z-x))*float64ToFloat32((z+x)))+float64ToFloat32(r / s))))); // eslint-disable-line max-len
	if ( sign ) {
		return float64ToFloat32( float64ToFloat32( r / ax ) - ONE );
	}
	return float64ToFloat32( ONE - float64ToFloat32( r / ax ) );
}
 
 
// EXPORTS //
 
module.exports = erff;