2023-10-03 11:14:36 +08:00
'use strict' ;
var GetIntrinsic = require ( 'get-intrinsic' ) ;
var $floor = GetIntrinsic ( '%Math.floor%' ) ;
var $log = GetIntrinsic ( '%Math.log%' ) ;
var $log2E = GetIntrinsic ( '%Math.LOG2E%' ) ;
var $log2 = GetIntrinsic ( '%Math.log2%' , true ) || function log2 ( x ) {
return $log ( x ) * $log2E ;
} ;
var $parseInt = GetIntrinsic ( '%parseInt%' ) ;
var $pow = GetIntrinsic ( '%Math.pow%' ) ;
var $TypeError = GetIntrinsic ( '%TypeError%' ) ;
var callBound = require ( 'call-bind/callBound' ) ;
var $reverse = callBound ( 'Array.prototype.reverse' ) ;
var $numberToString = callBound ( 'Number.prototype.toString' ) ;
var $strSlice = callBound ( 'String.prototype.slice' ) ;
var abs = require ( './abs' ) ;
var hasOwnProperty = require ( './HasOwnProperty' ) ;
var ToInt16 = require ( './ToInt16' ) ;
var ToInt32 = require ( './ToInt32' ) ;
var ToInt8 = require ( './ToInt8' ) ;
var ToUint16 = require ( './ToUint16' ) ;
var ToUint32 = require ( './ToUint32' ) ;
var ToUint8 = require ( './ToUint8' ) ;
var ToUint8Clamp = require ( './ToUint8Clamp' ) ;
var Type = require ( './Type' ) ;
var isNaN = require ( '../helpers/isNaN' ) ;
var isFinite = require ( '../helpers/isFinite' ) ;
var keys = require ( 'object-keys' ) ;
// https://262.ecma-international.org/8.0/#table-50
var TypeToSizes = {
_ _proto _ _ : null ,
Int8 : 1 ,
Uint8 : 1 ,
Uint8C : 1 ,
Int16 : 2 ,
Uint16 : 2 ,
Int32 : 4 ,
Uint32 : 4 ,
Float32 : 4 ,
Float64 : 8
} ;
var TypeToAO = {
_ _proto _ _ : null ,
Int8 : ToInt8 ,
Uint8 : ToUint8 ,
Uint8C : ToUint8Clamp ,
Int16 : ToInt16 ,
Uint16 : ToUint16 ,
Int32 : ToInt32 ,
Uint32 : ToUint32
} ;
// https://262.ecma-international.org/8.0/#sec-numbertorawbytes
module . exports = function NumberToRawBytes ( type , value , isLittleEndian ) {
if ( typeof type !== 'string' || ! hasOwnProperty ( TypeToSizes , type ) ) {
throw new $TypeError ( 'Assertion failed: `type` must be a TypedArray element type: ' + keys ( TypeToSizes ) ) ;
}
if ( Type ( value ) !== 'Number' ) {
throw new $TypeError ( 'Assertion failed: `value` must be a Number' ) ;
}
if ( Type ( isLittleEndian ) !== 'Boolean' ) {
throw new $TypeError ( 'Assertion failed: `isLittleEndian` must be a Boolean' ) ;
}
var rawBytes = [ ] ;
var exponent ;
if ( type === 'Float32' ) { // step 1
if ( isNaN ( value ) ) {
return isLittleEndian ? [ 0 , 0 , 192 , 127 ] : [ 127 , 192 , 0 , 0 ] ; // hardcoded
}
var leastSig ;
if ( value === 0 ) {
leastSig = Object . is ( value , - 0 ) ? 0x80 : 0 ;
return isLittleEndian ? [ 0 , 0 , 0 , leastSig ] : [ leastSig , 0 , 0 , 0 ] ;
}
if ( ! isFinite ( value ) ) {
leastSig = value < 0 ? 255 : 127 ;
return isLittleEndian ? [ 0 , 0 , 128 , leastSig ] : [ leastSig , 128 , 0 , 0 ] ;
}
var sign = value < 0 ? 1 : 0 ;
value = abs ( value ) ; // eslint-disable-line no-param-reassign
exponent = 0 ;
while ( value >= 2 ) {
exponent += 1 ;
value /= 2 ; // eslint-disable-line no-param-reassign
}
while ( value < 1 ) {
exponent -= 1 ;
value *= 2 ; // eslint-disable-line no-param-reassign
}
var mantissa = value - 1 ;
mantissa *= $pow ( 2 , 23 ) ;
mantissa = $floor ( mantissa ) ;
exponent += 127 ;
exponent = exponent << 23 ;
var result = sign << 31 ;
result |= exponent ;
result |= mantissa ;
var byte0 = result & 255 ;
result = result >> 8 ;
var byte1 = result & 255 ;
result = result >> 8 ;
var byte2 = result & 255 ;
result = result >> 8 ;
var byte3 = result & 255 ;
if ( isLittleEndian ) {
return [ byte0 , byte1 , byte2 , byte3 ] ;
}
return [ byte3 , byte2 , byte1 , byte0 ] ;
} else if ( type === 'Float64' ) { // step 2
if ( value === 0 ) {
leastSig = Object . is ( value , - 0 ) ? 0x80 : 0 ;
return isLittleEndian ? [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , leastSig ] : [ leastSig , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
}
if ( isNaN ( value ) ) {
return isLittleEndian ? [ 0 , 0 , 0 , 0 , 0 , 0 , 248 , 127 ] : [ 127 , 248 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
}
if ( ! isFinite ( value ) ) {
var infBytes = value < 0 ? [ 0 , 0 , 0 , 0 , 0 , 0 , 240 , 255 ] : [ 0 , 0 , 0 , 0 , 0 , 0 , 240 , 127 ] ;
return isLittleEndian ? infBytes : $reverse ( infBytes ) ;
}
var isNegative = value < 0 ;
if ( isNegative ) { value = - value ; } // eslint-disable-line no-param-reassign
exponent = $floor ( $log2 ( value ) ) ;
var significand = ( value / $pow ( 2 , exponent ) ) - 1 ;
var bitString = '' ;
for ( var i = 0 ; i < 52 ; i ++ ) {
significand *= 2 ;
if ( significand >= 1 ) {
bitString += '1' ;
significand -= 1 ;
} else {
bitString += '0' ;
}
}
exponent += 1023 ;
var exponentBits = $numberToString ( exponent , 2 ) ;
while ( exponentBits . length < 11 ) { exponentBits = '0' + exponentBits ; }
var fullBitString = ( isNegative ? '1' : '0' ) + exponentBits + bitString ;
while ( fullBitString . length < 64 ) { fullBitString = '0' + fullBitString ; }
for ( i = 0 ; i < 8 ; i ++ ) {
rawBytes [ i ] = $parseInt ( $strSlice ( fullBitString , i * 8 , ( i + 1 ) * 8 ) , 2 ) ;
}
return isLittleEndian ? $reverse ( rawBytes ) : rawBytes ;
} // step 3
var n = TypeToSizes [ type ] ; // step 3.a
var convOp = TypeToAO [ type ] ; // step 3.b
var intValue = convOp ( value ) ; // step 3.c
/ *
if ( intValue >= 0 ) { // step 3.d
// Let rawBytes be a List containing the n-byte binary encoding of intValue. If isLittleEndian is false, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.
} else { // step 3.e
// Let rawBytes be a List containing the n-byte binary 2's complement encoding of intValue. If isLittleEndian is false, the bytes are ordered in big endian order. Otherwise, the bytes are ordered in little endian order.
}
* /
if ( intValue < 0 ) {
intValue = intValue >>> 0 ;
}
for ( i = 0 ; i < n ; i ++ ) {
rawBytes [ isLittleEndian ? i : n - 1 - i ] = intValue & 0xff ;
intValue = intValue >> 8 ;
}
return rawBytes ; // step 4
} ;