All files main.js

100% Statements 223/223
100% Branches 14/14
100% Functions 1/1
100% Lines 223/223

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 214 215 216 217 218 219 220 221 222 223 2241x 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 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 10010x 10010x 10010x 10010x 10010x 10010x 10010x 10010x 10010x 10010x 10010x 2x 2x 10010x 1x 1x 10010x 2x 2x 10010x 2x 2x 10003x 10010x 6002x 10010x 2000x 2000x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 8003x 10010x 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, license, and long comment were part of the original implementation available as part of [FreeBSD]{@link https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/s_exp2f.c}. The implementation follows the original, but has been modified for JavaScript.
*
* ```text
* Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ```
*/
 
'use strict';
 
// MODULES //
 
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
var toWordf = require( '@stdlib/number/float32/base/to-word' );
var fromWords = require( '@stdlib/number/float64/base/from-words' );
var f32 = require( '@stdlib/number/float64/base/to-float32' );
var PINF = require( '@stdlib/constants/float32/pinf' );
var NINF = require( '@stdlib/constants/float32/ninf' );
 
 
// VARIABLES //
 
// Table size: 2^4 = 16
var TBLSIZE = 16;
 
// Number of bits used to index into the table:
var TBLBITS = 4;
 
// 2^(i/16) for i = -8, -7, ..., 7 (in double-precision, offset by 8):
var TBL = [
	0.7071067811865476,  // 0x1.6a09e667f3bcdp-1
	0.7384130729697497,  // 0x1.7a11473eb0187p-1
	0.7711054127039704,  // 0x1.8ace5422aa0dbp-1
	0.8052451659746271,  // 0x1.9c49182a3f090p-1
	0.8408964152537145,  // 0x1.ae89f995ad3adp-1
	0.8781260801866497,  // 0x1.c199bdd85529cp-1
	0.9170040432046712,  // 0x1.d5818dcfba487p-1
	0.9576032806985737,  // 0x1.ea4afa2a490dap-1
	1.0,                 // 0x1.0000000000000p+0
	1.0442737824274138,  // 0x1.0b5586cf9890fp+0
	1.0905077326652577,  // 0x1.172b83c7d517bp+0
	1.1387886347566916,  // 0x1.2387a6e756238p+0
	1.189207115002721,   // 0x1.306fe0a31b715p+0
	1.241857812073484,   // 0x1.3dea64c123422p+0
	1.2968395546510096,  // 0x1.4bfdad5362a27p+0
	1.3542555469368927   // 0x1.5ab07dd485429p+0
];
 
// Reduction constant: 1.5*2^23/16 = 786432 => 0 10010010 10000000000000000000000 => 0x49400000 = 1228931072
var REDUX = f32( 786432.0 );
 
// Polynomial coefficient: ~ln(2) => 0 01111110 01100010111001000011000 => 0x3f317218 = 1060205080
var P1 = 0.6931471824645996;
 
// Polynomial coefficient => 0 01111100 11101011111110111110000 => 0x3e75fdf0 = 1047920112
var P2 = 0.24022650718688965;
 
// Polynomial coefficient => 0 01111010 11000110101100110100100 => 0x3d6359a4 = 1029921188
var P3 = 0.055505409836769104;
 
// Polynomial coefficient => 0 01111000 00111011001011001001110 => 0x3c1d964e = 1008571982
var P4 = 0.009618354961276054;
 
// Overflow threshold: 2^x overflows for x >= 128
var OVERFLOW = 128.0;
 
// Underflow threshold: 2^x underflows to 0 for x <= -150
var UNDERFLOW = -150.0;
 
// Near-zero threshold: 2^-25 => 0 01100110 00000000000000000000000 => 0x33000000 = 855638016
var NEARZERO = f32( 1.0 / ( 1 << 25 ) );
var NEG_NEARZERO = f32( -NEARZERO );
 
// High word of 1.0 => 0 01111111111 0000000000000000000 => 0x3ff00000 = 1072693248
var ONE_HIGH_WORD = 0x3ff00000|0; // asm type annotation
 
 
// MAIN //
 
/**
* Evaluates the base `2` exponential function in single-precision floating-point format.
*
* ## Method
*
* (equally-spaced tables)
*
* -   Reduce \\( x \\):
*
*     ```tex
*     x = k + y
*     ```
*
*     for integer \\( k \\) and \\( |y| \leq 1/2 \\). Thus we have \\( \operatorname{exp2f}(x) = 2^k \cdot \operatorname{exp2}(y) \\).
*
* -   Reduce \\( y \\):
*
*     ```tex
*     y = i/\mathrm{TBLSIZE} + z
*     ```
*
*     for integer \\( i \\) near \\( y \cdot \mathrm{TBLSIZE} \\). Thus we have \\( \operatorname{exp2}(y) = \operatorname{exp2}(i/\mathrm{TBLSIZE}) \cdot \operatorname{exp2}(z) \\), with \\( |z| \leq 2^{-(\mathrm{TBLBITS}+1)} \\).
*
* -   We compute \\( \operatorname{exp2}(i/\mathrm{TBLSIZE}) \\) via table lookup and \\( \operatorname{exp2}(z) \\) via a degree-4 minimax polynomial with maximum error under \\( 1.4 \cdot 2^{-33} \\). Using double precision for everything except the reduction makes roundoff error insignificant and simplifies the scaling step.
*
* This method is due to Tang, but the implementation does not use his suggested parameters:
*
* > Tang, P. Table-driven Implementation of the Exponential Function in IEEE Floating-Point Arithmetic. TOMS 15(2), 144-157 (1989).
*
* ## Notes
*
* -   Accuracy: peak error < 0.501 ulp.
*
* @param {number} x - input value
* @returns {number} function value
*
* @example
* var v = exp2f( 3.0 );
* // returns 8.0
*
* @example
* var v = exp2f( -9.0 );
* // returns ~0.002
*
* @example
* var v = exp2f( 0.0 );
* // returns 1.0
*
* @example
* var v = exp2f( NaN );
* // returns NaN
*/
function exp2f( x ) {
	var twopk;
	var i0;
	var tv;
	var hi;
	var t;
	var u;
	var z;
 
	x = f32( x );
	if ( isnanf( x ) || x === PINF ) {
		return x;
	}
	if ( x === NINF ) {
		return 0.0;
	}
	if ( x >= OVERFLOW ) {
		return PINF;
	}
	if ( x <= UNDERFLOW ) {
		return 0.0;
	}
	if (
		x > NEG_NEARZERO &&
		x < NEARZERO
	) {
		return f32( 1.0 + x );
	}
	// Reduce `x`, computing `z`, `i0`, and `k` (the high word of 2^k)...
	t = f32( x + REDUX );
	i0 = toWordf( t ) >>> 0; // asm type annotation
	i0 += TBLSIZE / 2;
	hi = ( ONE_HIGH_WORD + ( ( i0 >>> TBLBITS ) << 20 ) ) >>> 0; // asm type annotation
	i0 &= TBLSIZE - 1;
	t = f32( t - REDUX );
	z = x - t;
	twopk = fromWords( hi, 0 );
 
	// Compute r = exp2(y) = TBL[ i0 ] * p(z)...
	tv = TBL[ i0 ];
	u = tv * z;
	tv = tv + ( u * ( P1 + ( z * P2 ) ) ) + ( u * ( z * z ) * ( P3 + ( z * P4 ) ) ); // eslint-disable-line max-len
 
	// Scale by 2^k:
	return f32( tv * twopk );
}
 
 
// EXPORTS //
 
module.exports = exp2f;