time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

format_double.js (3152B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2022 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 'use strict';
     20 
     21 // MODULES //
     22 
     23 var isNumber = require( './is_number.js' );
     24 
     25 // NOTE: for the following, we explicitly avoid using stdlib packages in this particular package in order to avoid circular dependencies.
     26 var abs = Math.abs; // eslint-disable-line stdlib/no-builtin-math
     27 var lowercase = String.prototype.toLowerCase;
     28 var uppercase = String.prototype.toUpperCase;
     29 var replace = String.prototype.replace;
     30 
     31 
     32 // VARIABLES //
     33 
     34 var RE_EXP_POS_DIGITS = /e\+(\d)$/;
     35 var RE_EXP_NEG_DIGITS = /e-(\d)$/;
     36 var RE_ONLY_DIGITS = /^(\d+)$/;
     37 var RE_DIGITS_BEFORE_EXP = /^(\d+)e/;
     38 var RE_TRAILING_PERIOD_ZERO = /\.0$/;
     39 var RE_PERIOD_ZERO_EXP = /\.0*e/;
     40 var RE_ZERO_BEFORE_EXP = /(\..*[^0])0*e/;
     41 
     42 
     43 // MAIN //
     44 
     45 /**
     46 * Formats a token object argument as a floating-point number.
     47 *
     48 * @private
     49 * @param {Object} token - token object
     50 * @throws {Error} must provide a valid floating-point number
     51 * @returns {string} formatted token argument
     52 */
     53 function formatDouble( token ) {
     54 	var digits;
     55 	var out;
     56 	var f = parseFloat( token.arg );
     57 	if ( !isFinite( f ) ) { // NOTE: We use the global `isFinite` function here instead of `@stdlib/math/base/assert/is-finite` in order to avoid circular dependencies.
     58 		if ( !isNumber( token.arg ) ) {
     59 			throw new Error( 'invalid floating-point number. Value: ' + out );
     60 		}
     61 		// Case: NaN, Infinity, or -Infinity
     62 		f = token.arg;
     63 	}
     64 	switch ( token.specifier ) {
     65 	case 'e':
     66 	case 'E':
     67 		out = f.toExponential( token.precision );
     68 		break;
     69 	case 'f':
     70 	case 'F':
     71 		out = f.toFixed( token.precision );
     72 		break;
     73 	case 'g':
     74 	case 'G':
     75 		if ( abs( f ) < 0.0001 ) {
     76 			digits = token.precision;
     77 			if ( digits > 0 ) {
     78 				digits -= 1;
     79 			}
     80 			out = f.toExponential( digits );
     81 		} else {
     82 			out = f.toPrecision( token.precision );
     83 		}
     84 		if ( !token.alternate ) {
     85 			out = replace.call( out, RE_ZERO_BEFORE_EXP, '$1e' );
     86 			out = replace.call( out, RE_PERIOD_ZERO_EXP, 'e');
     87 			out = replace.call( out, RE_TRAILING_PERIOD_ZERO, '' );
     88 		}
     89 		break;
     90 	default:
     91 		throw new Error( 'invalid double notation. Value: ' + token.specifier );
     92 	}
     93 	out = replace.call( out, RE_EXP_POS_DIGITS, 'e+0$1' );
     94 	out = replace.call( out, RE_EXP_NEG_DIGITS, 'e-0$1' );
     95 	if ( token.alternate ) {
     96 		out = replace.call( out, RE_ONLY_DIGITS, '$1.' );
     97 		out = replace.call( out, RE_DIGITS_BEFORE_EXP, '$1.e' );
     98 	}
     99 	if ( f >= 0 && token.sign ) {
    100 		out = token.sign + out;
    101 	}
    102 	out = ( token.specifier === uppercase.call( token.specifier ) ) ?
    103 		uppercase.call( out ) :
    104 		lowercase.call( out );
    105 	return out;
    106 }
    107 
    108 
    109 // EXPORTS //
    110 
    111 module.exports = formatDouble;