frexp.js (3098B)
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 isnan = require( './../../../../base/assert/is-nan' ); 24 var isInfinite = require( './../../../../base/assert/is-infinite' ); 25 var normalize = require( '@stdlib/number/float64/base/normalize' ); 26 var floatExp = require( '@stdlib/number/float64/base/exponent' ); 27 var toWords = require( '@stdlib/number/float64/base/to-words' ); 28 var fromWords = require( '@stdlib/number/float64/base/from-words' ); 29 30 31 // VARIABLES // 32 33 // Exponent all 0s: 1 00000000000 11111111111111111111 => 2148532223 34 var CLEAR_EXP_MASK = 0x800fffff>>>0; // asm type annotation 35 36 // Exponent equal to 1022 (BIAS-1): 0 01111111110 00000000000000000000 => 1071644672 37 var SET_EXP_MASK = 0x3fe00000|0; // asm type annotation 38 39 // Normalization workspace: 40 var X = [ 0.0, 0.0 ]; // WARNING: not thread safe 41 42 // High/low words workspace: 43 var WORDS = [ 0, 0 ]; // WARNING: not thread safe 44 45 46 // MAIN // 47 48 /** 49 * Splits a double-precision floating-point number into a normalized fraction and an integer power of two. 50 * 51 * @private 52 * @param {(Array|TypedArray|Object)} out - output array 53 * @param {number} x - input value 54 * @returns {(Array|TypedArray|Object)} output array 55 * 56 * @example 57 * var out = frexp( new Array( 2 ), 4.0 ); 58 * // returns [ 0.5, 3 ] 59 * 60 * @example 61 * var out = frexp( new Array( 2 ), 0.0 ); 62 * // returns [ 0.0, 0 ] 63 * 64 * @example 65 * var out = frexp( new Array( 2 ), -0.0 ); 66 * // returns [ -0.0, 0 ] 67 * 68 * @example 69 * var out = frexp( new Array( 2 ), NaN ); 70 * // returns [ NaN, 0 ] 71 * 72 * @example 73 * var out = frexp( new Array( 2 ), Infinity ); 74 * // returns [ Infinity , 0 ] 75 * 76 * @example 77 * var out = frexp( new Array( 2 ), -Infinity ); 78 * // returns [ -Infinity , 0 ] 79 */ 80 function frexp( out, x ) { 81 var high; 82 var exp; 83 if ( 84 x === 0.0 || // handles -0 85 isnan( x ) || 86 isInfinite( x ) 87 ) { 88 out[ 0 ] = x; 89 out[ 1 ] = 0; 90 return out; 91 } 92 // If `x` is subnormal, normalize it... 93 normalize( X, x ); 94 95 // Extract the exponent from `x` and add the normalization exponent: 96 exp = floatExp( X[0] ) + X[ 1 ] + 1; 97 98 // Break `x` into two unsigned 32-bit integers (higher and lower order words): 99 toWords( WORDS, X[ 0 ] ); 100 high = WORDS[ 0 ]; 101 102 // Clear the exponent bits within the higher order word: 103 high &= CLEAR_EXP_MASK; 104 105 // Set the exponent bits within the higher order word to BIAS-1 (1023-1=1022): 106 high |= SET_EXP_MASK; 107 108 // Create a new floating-point number: 109 x = fromWords( high, WORDS[ 1 ] ); 110 111 out[ 0 ] = x; 112 out[ 1 ] = exp; 113 return out; 114 } 115 116 117 // EXPORTS // 118 119 module.exports = frexp;