time-to-botec

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

main.js (5305B)


      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 'use strict';
     20 
     21 // MODULES //
     22 
     23 var PINF = require( '@stdlib/constants/float64/pinf' );
     24 var NINF = require( '@stdlib/constants/float64/ninf' );
     25 var BIAS = require( '@stdlib/constants/float64/exponent-bias' );
     26 var isnan = require( '@stdlib/math/base/assert/is-nan' );
     27 var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' );
     28 var abs = require( '@stdlib/math/base/special/abs' );
     29 var floor = require( '@stdlib/math/base/special/floor' );
     30 var rpad = require( '@stdlib/string/right-pad' );
     31 var lpad = require( '@stdlib/string/left-pad' );
     32 var repeat = require( '@stdlib/string/repeat' );
     33 var div2 = require( './div2.js' );
     34 var mult2 = require( './mult2.js' );
     35 
     36 
     37 // VARIABLES //
     38 
     39 // TODO: consider moving to external constants
     40 var NUM_EXPONENT_BITS = 11;
     41 var NUM_SIGNIFICAND_BITS = 52;
     42 
     43 
     44 // MAIN //
     45 
     46 /**
     47 * Returns a string giving the literal bit representation of a double-precision floating-point number.
     48 *
     49 * @param {number} x - input value
     50 * @returns {BinaryString} bit representation
     51 *
     52 * @example
     53 * var str = toBinaryString( 4.0 );
     54 * // returns '0100000000010000000000000000000000000000000000000000000000000000'
     55 *
     56 * @example
     57 * var str = toBinaryString( 3.141592653589793 );
     58 * // returns '0100000000001001001000011111101101010100010001000010110100011000'
     59 *
     60 * @example
     61 * var str = toBinaryString( -1.0e308 );
     62 * // returns '1111111111100001110011001111001110000101111010111100100010100000'
     63 *
     64 * @example
     65 * var str = toBinaryString( -3.14e-320 );
     66 * // returns '1000000000000000000000000000000000000000000000000001100011010011'
     67 *
     68 * @example
     69 * var str = toBinaryString( 5.0e-324 );
     70 * // returns '0000000000000000000000000000000000000000000000000000000000000001'
     71 *
     72 * @example
     73 * var str = toBinaryString( 0.0 );
     74 * // returns '0000000000000000000000000000000000000000000000000000000000000000'
     75 *
     76 * @example
     77 * var str = toBinaryString( -0.0 );
     78 * // returns '1000000000000000000000000000000000000000000000000000000000000000'
     79 *
     80 * @example
     81 * var str = toBinaryString( NaN );
     82 * // returns '0111111111111000000000000000000000000000000000000000000000000000'
     83 *
     84 * @example
     85 * var str = toBinaryString( Infinity );
     86 * // returns '0111111111110000000000000000000000000000000000000000000000000000'
     87 *
     88 * @example
     89 * var str = toBinaryString( -Infinity );
     90 * // returns '1111111111110000000000000000000000000000000000000000000000000000'
     91 */
     92 function toBinaryString( x ) {
     93 	var nbits;
     94 	var sign;
     95 	var str;
     96 	var exp;
     97 	var n;
     98 	var f;
     99 	var i;
    100 
    101 	// Check for a negative value or negative zero...
    102 	if ( x < 0.0 || isNegativeZero( x ) ) {
    103 		sign = '1';
    104 	} else {
    105 		sign = '0';
    106 	}
    107 	// Special case: +-infinity
    108 	if ( x === PINF || x === NINF ) {
    109 		// Based on IEEE 754-1985...
    110 		exp = repeat( '1', NUM_EXPONENT_BITS ); // all 1s
    111 		str = repeat( '0', NUM_SIGNIFICAND_BITS ); // all 0s
    112 		return sign + exp + str;
    113 	}
    114 	// Special case: NaN
    115 	if ( isnan( x ) ) {
    116 		// Based on IEEE 754-1985...
    117 		exp = repeat( '1', NUM_EXPONENT_BITS ); // all 1s
    118 		str = '1' + repeat( '0', NUM_SIGNIFICAND_BITS-1 ); // can't be all 0s
    119 		return sign + exp + str;
    120 	}
    121 	// Special case: +-0
    122 	if ( x === 0 ) {
    123 		// Based on IEEE 754-1985...
    124 		exp = repeat( '0', NUM_EXPONENT_BITS ); // all 0s
    125 		str = repeat( '0', NUM_SIGNIFICAND_BITS ); // all 0s
    126 		return sign + exp + str;
    127 	}
    128 	x = abs( x );
    129 
    130 	// Isolate the integer part (digits before the decimal):
    131 	n = floor( x );
    132 
    133 	// Isolate the fractional part (digits after the decimal):
    134 	f = x - n;
    135 
    136 	// Convert the integer and fractional parts to bit strings:
    137 	n = div2( n );
    138 	f = mult2( f );
    139 
    140 	// Determine the exponent needed to normalize the integer+fractional parts...
    141 	if ( n ) {
    142 		// Move the decimal `d` digits to the left:
    143 		exp = n.length - 1;
    144 	} else {
    145 		// Find the first '1' bit...
    146 		for ( i = 0; i < f.length; i++ ) {
    147 			if ( f[ i ] === '1' ) {
    148 				nbits = i + 1;
    149 				break;
    150 			}
    151 		}
    152 		// Move the decimal `d` digits to the right:
    153 		exp = -nbits;
    154 	}
    155 	// Normalize the combined integer+fractional string...
    156 	str = n + f;
    157 	if ( exp < 0 ) {
    158 		// Handle subnormals...
    159 		if ( exp <= -BIAS ) {
    160 			// Cap the number of bits removed:
    161 			nbits = BIAS - 1;
    162 		}
    163 		// Remove all leading zeros and the first '1' for normal values, and, for subnormals, remove at most BIAS-1 leading bits:
    164 		str = str.substring( nbits );
    165 	} else {
    166 		// Remove the leading '1' (implicit/hidden bit):
    167 		str = str.substring( 1 );
    168 	}
    169 	// Convert the exponent to a bit string:
    170 	exp = div2( exp + BIAS );
    171 	exp = lpad( exp, NUM_EXPONENT_BITS, '0' );
    172 
    173 	// Fill in any trailing zeros and ensure we have only 52 fraction bits:
    174 	str = rpad( str, NUM_SIGNIFICAND_BITS, '0' ).substring( 0, NUM_SIGNIFICAND_BITS );
    175 
    176 	// Return a bit representation:
    177 	return sign + exp + str;
    178 }
    179 
    180 
    181 // EXPORTS //
    182 
    183 module.exports = toBinaryString;