Perform a way to mark a number in JavaScript using its less significant bit?

Often for the implementation of programming languages, it is desirable to mark numbers using bitwise operators. In C, you can mark double with a union:

typedef union Tag_ { double d; long long i; } Tag; double tag(double x){ Tag tmp; tmp.d = x; tmp.i |= 1; return tmp.d; }; double isTagged(double x){ Tag tmp; tmp.d = x; return tmp&1; }; 

What is the way to simulate this behavior in JavaScript? The use of bitwise operators is excluded, since it converts doubles to Uint32s. I need a math solution.

+5
source share
1 answer

This did not receive an answer, maybe you found it? If not:

Let me start with a question in your comments, since it seems that solving this question ultimately solves the original question.

How to create separate representations of the same array?

This is essentially Bergi's suggestion from comments slightly modified. He answers How.

When creating an ArrayBuffer you can access the underlying byte array from several typed arrays by passing this array buffer as the initial parameter. I found JavaScripture - ArrayBuffer to be very useful in the past with TypedArrays. Thus, the next reserve 8 bytes in memory and access it as a 64-bit floating point methods, and 8 bytes.

 var myBuff = new ArrayBuffer(8); var myU8Arr = new Uint8Array(myBuff); var myFloat64Arr = new Float64Array(myBuff); 

so if you say that the first byte in the buffer is 1, and then access this value from the float, you will get floating insolently:

 myFloat64Arr[0] = 10000; console.log(myFloat64Arr[0])//prints 0; myU8Arr[7] |= 128;//sets sign bit of IEEE 754 Double-precision float. //setting the sign because it more straightforward than if another //bit was to be set. console.log(myFloat64Arr[0]);//prints -10000 ... all dependent on system endianess 

So now, when the question from the comments was answered:

How can I use the least significant bit to mark my numbers?

Direct appeal to the issue; I do not see a problem using Typed Arrays. We can use basic bytes in the Array base buffer in a bit-by-bit fashion without fear that the byte will be turned into a 64-bit float and mess.

Adhering to the "stack" of floats, you get extra performance. Just create an ArrayBuffer and then Uint8Array and Float64Array instead of an array of numbers (or an array of Tag s). Otherwise, you can make the Tag function with the ArrayBuffer , Uint8Array and Float64Array in it, and then create new instances for each number ... but that will not save you from anything larger than the javascript area. There may also be a polyfill in the Tag attribute / function for variables and the Number prototype if you are going to follow this path of creating structures similar to Tag. This will not give you storage performance, but at least keep the tag associated with each number.

Due to endianess and the lack of a 64-bit integer array, you will have to process the LSB index a bit. Check endianess and set the global variable, or in any other way that you consider most suitable. on a small system:

 var globalMyBuff = new ArrayBuffer(n);//n is your number of floats * 8 (8 bytes per float) var globalMyU8Arr = new Uint8Array(globalMyBuff); var globalMyFloat64Arr = new Float64Array(globalMyBuff); //Load your floats into globalMyFloat64Arr //tag a float at index when desired function tag(index){ //"index << 3 " is essentially the same as "index * 8", but faster //since it will get compiled into a shift op myU8Arr[index << 3] |= 1;//sets the LSB } //check tag at index when desired function isTagged(index){ //"index << 3 " is essentially the same as "index * 8", but faster //since it will get compiled into a shift op return (myU8Arr[index << 3] & 1) == 1;//checks LSB } 
+1
source

Source: https://habr.com/ru/post/1204814/


All Articles