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