npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bit-manipulation

v1.0.0

Published

An ES module providing functions for setting and clearing bits (and doing any bitwise operations) in Numbers up to 53 bits and in BigInts of any bit-width. In addition there's also functions to manipulate the bits in JavaScript's 64-bit floats and represe

Downloads

6

Readme

bit-manipulation

Description

An ES module providing functions for setting and clearing bits (and doing any bitwise operations) in Numbers up to 53 bits and in BigInts of any bit-width. In addition there's also functions to manipulate the bits in JavaScript's 64-bit floats and representing integers (in two's complement format) in binary or hex. It also has functions to check if any bits are set or not.

If you're new to JavaScript it might sound strange to have a library for doing bitwise operations since JavaScript has operators for this inbuilt in the language. But the problem is that the inbuilt operators converts any operands into 32-bit signed integers, hence they can't return a result that is over 32 bits AND they treat bit 32 as the sign bit (although >>> 0 can be used to get an unsigned result).

Funding

If you find this useful then please consider helping me out (I'm jobless and sick). For more information visit my GitHub profile.

How to use

Install using NPM

npm i bit-manipulation

Import the ES module into Node.js

import * as bm from 'bit-manipulation'

Got problems using ES modules? This might help or read the documentation.

Import the ES module into the browser or Deno

import * as bm from '/node_modules/bit-manipulation/source/bitManipulation.js'

Example

import * as bm from 'bit-manipulation'
const log = console.log // yes, this is handy

// Classical use of (some of) the functions in this library
let v = 0b1000_0000
v = bm.set(v, 1,2,3,4) // set these bits in v and return the result
log(bm.numberToBinary(v))
v = bm.xor(v, 0xFF) // xor v with 0xFF
log(bm.numberToBinary(v))
log(bm.isSet(v, 1)) // check if the LSB is set
log(v) // the value in base 10

log() // Wrapping a value in bm.Serial allows us to do the same operations on it in series in a more convenient way
v = bm.serial(0b1000_0000)
.set(1,2,3,4).log('bin')
.xor(0xFF).log('bin')
log(v.isSet(1))
log(v.out()) // then .out() returns the result

log() // You can go mad with that
bm.serial(0).set(1,8).xor(0xFF).and(0b1111).or(0xF0).flip(1,8).not(8).log('bin')

log() // And then debug your madness for better clarity
bm.serial(0).set(1,8).log(2).xor(0xFF).log(2).and(0b1111).log(2).or(0xF0).log(2).flip(1,8).log(2).not(8).log(2)

log() // There's lots of fun to be had
log(bm.numberToHex(bm.reverseBitOrder(0xD00D, 16), 2)) 

log() // And yes, you can set bits higher than bit 32
log(bm.numberToBinary(bm.set(0, 33, 53), 64))
log(bm.numberToBinary(bm.set(0n, 33, 64))) // even higher than bit 53 if using BigInts
// And bitwise operations works fine on them
log(bm.numberToBinary(bm.or(bm.set(0, 33, 53), 1), 64))
log(bm.numberToBinary(bm.or(bm.set(0n, 33, 64), 1)))

log() // Did you ever want to mess around with the bits in a 64-bit float? Well, now you can!
let bits = bm.float.toBits(1.23456) // returns an overview of any set bits
log(bits)
log(bm.float.fromBits(bits)) // and can be used to create a float
let float = bm.float.set(1.23456, {signBit: true}) // set the sign bit
log(float)
float = bm.float.clear(float, {signBit: true}) // clear it
log(bm.float.set(float, {significand: [51]})) // and set bit 51 in the significand / mantissa
// you can even set bits using values
float = bm.float.fromBits({exponent: 0b1100_0001, significand: 0xF_FFFF_FFFF_FFFF})
log(bm.float.toBits(float)) // check that it worked correctly
log(float) // also let's check what that float looks like

log() // There's also an educational value in learning about two's complement format
log(bm.negativeIntegerFromBits(1)) // the bits to set to 0
log(bm.negativeIntegerFromValue(0b10)) // same as this (where the MSB is the sign bit)

log() // And I'm sure that you at least once wanted to know the bit length/width of a number
log(bm.bitLength(0xFFFF_FFFF))
log(bm.bitLength(0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFFn))

log('Please tell your mom and dad about this! 🙂')

Console output from example (for those without a computer):

0b10001111
0b01110000
false
112

0b10001111
0b01110000
false
112

0b10000000

0b10000001
0b01111110
0b00001110
0b11111110
0b01111111
0b10000000

0xB00B

0b00000000_00010000_00000000_00000001_00000000_00000000_00000000_00000000
0b10000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000n
0b00000000_00010000_00000000_00000001_00000000_00000000_00000000_00000001
0b10000000_00000000_00000000_00000001_00000000_00000000_00000000_00000001n

{
  signBit: false,
  exponent: [
    1, 2, 3, 4,  5,
    6, 7, 8, 9, 10
  ],
  significand: [
     4,  5,  6, 10, 13, 14, 17, 18,
    19, 20, 24, 27, 28, 29, 30, 31,
    32, 33, 39, 40, 47, 48, 49, 50
  ]
}
1.23456
-1.23456
1.48456
{
  signBit: false,
  exponent: [ 1, 7, 8 ],
  significand: [
     1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
    12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
    23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
    34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
    45, 46, 47, 48, 49, 50, 51, 52
  ]
}
2.793402995719818e-250

-2
-2

32
96

Auto-generated API documentation (from JSDoc)

Modules

Objects

bit-manipulation

bm.Serial

A class allowing multiple bitwise operations done in serial order on a value (for convenience). Call out() to return the result when done. This class actually has most of the functions in this library as its methods.

Kind: static class of bit-manipulation

new exports.Serial(value)

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | Enter the value to operate on, must be an integer. |

serial.x(func)

Manipulate or read the value using your own function, return nothing if no change is to be made or return the new value.

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | func | function | A function which will receive the value. |

serial.out([base]) ⇒ number | bigint | string

Returns the value operated on.

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | [base] | number | string | The base to use. Defaults to base 10, also supports base 2 and 16. |

serial.log([base])

A shortcut to logging the value using console.log. But with options for using a binary or hexadecimal representation.

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | [base] | number | string | The base to use. Defaults to base 10, also supports base 2 and 16. |

serial.not(bitLength)

Bitwise NOT (invert the bits). If not specifying a bitLength to operate within then inverting the bits using not will turn any positive number into a negative one because the sign bit (which is virtual when using this library by the way) will be inverted as well.

Kind: instance method of Serial

| Param | Type | | --- | --- | | bitLength | number |

serial.reverseBitOrder(bitLength)

Reverse the bit order up to the bitLength supplied, the result will be capped to this size.

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | bitLength | number | The wanted bit length of the result (the position of the most significant bit). |

serial.rShift(offset)

Shift the bits towards the right (the least significant side) offset amount of bits. Bits shifted in from the left will be set to 0.

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | offset | number | How far to shift the bits. |

serial.lShift(offset)

Shift the bits towards the left (the most significant side) offset amount of bits. Bits shifted in from the right will be set to 0.

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | offset | number | How far to shift the bits. |

serial.and()

Bitwise AND

Kind: instance method of Serial

serial.or()

Bitwise OR

Kind: instance method of Serial

serial.xor()

Bitwise XOR

Kind: instance method of Serial

serial.set(...bits)

Set (as in setting them to 1) these bits (others retain their state).

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to set, where 1 means the least significant bit. |

serial.clear(...bits)

Clear (as in setting them to 0) these bits (others retain their state).

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to clear, where 1 means the least significant bit. |

serial.flip(...bits)

Flip (or toggle) these bits (others retain their state).

Kind: instance method of Serial

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to flip, where 1 means the least significant bit. |

serial.isSet(...bits) ⇒ boolean

Check if all of these bits are set (as in having a state of 1).

Kind: instance method of Serial
Returns: boolean - True or false

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to check. |

serial.isAnySet(...bits) ⇒ boolean

Check if any of these bits are set (as in having a state of 1).

Kind: instance method of Serial
Returns: boolean - True or false

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to check. |

serial.isNotSet(...bits) ⇒ boolean

Check if all of these bits are not set (as in having a state of 0).

Kind: instance method of Serial
Returns: boolean - True or false

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to check. |

serial.bitLength() ⇒ number

Returns the number of bits needed to be able to represent the value. For negative numbers this does not include the sign bit.

Kind: instance method of Serial
Returns: number - The bit length of the value.

bm.set(value, ...bits) ⇒ number | bigint

Set (as in setting them to 1) these bits in the value (others retain their state).

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | ...bits | number | Which bits to set, where 1 means the least significant bit. |

bm.clear(value, ...bits) ⇒ number | bigint

Clear (as in setting them to 0) these bits in the value (others retain their state).

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | ...bits | number | Which bits to clear, where 1 means the least significant bit. |

bm.flip(value, ...bits) ⇒ number | bigint

Flip (or toggle) these bits in the value (others retain their state).

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | ...bits | number | Which bits to flip, where 1 means the least significant bit. |

bm.isAnySet(value, ...bits) ⇒ boolean

Check if any of these bits are set (as in having a state of 1) in the value.

Kind: static method of bit-manipulation
Returns: boolean - True or false

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to check. | | ...bits | number | Which bits to check. |

bm.isSet(value, ...bits) ⇒ boolean

Check if all of these bits are set (as in having a state of 1) in the value.

Kind: static method of bit-manipulation
Returns: boolean - True or false

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to check. | | ...bits | number | Which bits to check. |

bm.isNotSet(value, ...bits) ⇒ boolean

Check if all of these bits are not set (as in having a state of 0) in the value.

Kind: static method of bit-manipulation
Returns: boolean - True or false

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to check. | | ...bits | number | Which bits to check. |

bm.lShift(value, offset) ⇒ number | bigint

Shift the bits in the value towards the left (the most significant side) offset amount of bits. Bits shifted in from the right will be set to 0.

Kind: static method of bit-manipulation
Returns: number | bigint - The result.

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | offset | number | How far to shift the bits. |

bm.rShift(value, offset) ⇒ number | bigint

Shift the bits in the value towards the right (the least significant side) offset amount of bits. Bits shifted in from the left will be set to 0.

Kind: static method of bit-manipulation
Returns: number | bigint - The result.

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | offset | number | How far to shift the bits. |

bm.xor(value1, value2) ⇒ number | bigint

Bitwise XOR (exclusive or) value1 with value2 and return the result.

Kind: static method of bit-manipulation

| Param | Type | | --- | --- | | value1 | number | bigint | | value2 | number | bigint |

bm.or(value1, value2) ⇒ number | bigint

Bitwise OR value1 with value2 and return the result.

Kind: static method of bit-manipulation

| Param | Type | | --- | --- | | value1 | number | bigint | | value2 | number | bigint |

bm.and(value1, value2) ⇒ number | bigint

Bitwise AND value1 with value2 and return the result.

Kind: static method of bit-manipulation

| Param | Type | | --- | --- | | value1 | number | bigint | | value2 | number | bigint |

bm.not(value, [bitLength]) ⇒ number | bigint

Bitwise NOT value (invert the bits) and return the result. If not specifying a bitLength to operate within then inverting the bits using not will turn any positive number into a negative one because the sign bit (which is virtual when using this library by the way) will be inverted as well.

Kind: static method of bit-manipulation
Returns: number | bigint - The result.

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | [bitLength] | number | The bit length to operate within, set it to restrict the NOT operation to only the first bitLength bits of the value. Then you can not in any way invert the sign bit. |

bm.reverseBitOrder(value, bitLength) ⇒ number | bigint

Reverse the bit order of the value up to the bitLength supplied, the returned value will be capped to this size.

Kind: static method of bit-manipulation
Returns: number | bigint - The result.

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to operate on. | | bitLength | number | The wanted bit length of the returned value (the position of the most significant bit). |

bm.bitLength(value) ⇒ number

Returns the number of bits needed to be able to represent the value. For negative numbers this does not include the sign bit.

Kind: static method of bit-manipulation
Returns: number - The bit length of the value.

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value to measure the length in bits of. |

bm.bitmask(...bits) ⇒ number | bigint

Create a bitmask (which is a value with bits in these positions set). If setting bits over bit 32 then it returns a BigInt.

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | ...bits | number | The bit positions of any set (as in 1) bits. |

bm.bitmask_allSet(numBits) ⇒ number | bigint

Create a bitmask with a length of numBits where all the bits are set, if numBits is more than 53 then a BigInt will be returned.

Kind: static method of bit-manipulation
Returns: number | bigint - The bitmask.

| Param | Type | Description | | --- | --- | --- | | numBits | number | Defines how wide (in bits) the bitmask is. |

Example

bitmask_allSet(32) == 0xFFFF_FFFF

bm.integerFromBits(...bits) ⇒ number | bigint

Create a positive integer with only these bits set. If setting bits over bit 53 (> Number.MAX_SAFE_INTEGER) then a BigInt is returned.

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to set, where 1 means the least significant bit. |

bm.negativeIntegerFromBits(...bits) ⇒ number | bigint

Create a negative integer (two's complement) from which bit positions should be set to 0.

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | ...bits | number | Which bits to set to 0, where 1 means the least significant bit. |

bm.negativeIntegerFromValue(value) ⇒ number | bigint

Create a negative integer (two's complement) from the bits in a value. One use case could be that you read the bits into an unsigned integer, but you actually wanted those bits to be represented as a negative number. Or educational use.

Kind: static method of bit-manipulation

| Param | Type | Description | | --- | --- | --- | | value | number | bigint | The value with bits representing a negative number in two's complement format. |

bm.serial(value) ⇒ Serial

If you want to do multiple bitwise operations (in serial order) then this will wrap the value in a class which has most of the functions in this library as its methods. Call out() to return the result when done.

Kind: static method of bit-manipulation

| Param | Type | | --- | --- | | value | number | bigint |

Example

serial(value).rShift(32).and(0xFFFF_FFFF).out()

bm.numberToHex(number, [paddingByteSize], [grouping], [showPrefix]) ⇒ string

Converts any Number or BigInt into a hexadecimal representation.

Numbers with a fractional part will represented in the IEEE 754 double-precision binary format. Where the first bit is the sign bit, followed by the exponent (11 bits) and the significand / mantissa (52 bits).

Other numbers (integers) will be represented in the two's complement format. Where negative numbers are actually displayed correctly compared to when using (number).toString(16).

Kind: static method of bit-manipulation
Returns: string - The hexadecimal representation.

| Param | Type | Default | Description | | --- | --- | --- | --- | | number | number | | The number to convert to hex. | | [paddingByteSize] | number | 4 | How many bytes to align the output with. | | [grouping] | number | 4 | Group the output into chunks of this size. | | [showPrefix] | boolean | true | Whether to prefix the output with 0x or not. |

bm.numberToBinary(number, [paddingBits], [grouping], [showPrefix]) ⇒ string

Converts any Number or BigInt into a binary representation.

Numbers with a fractional part will represented in the IEEE 754 double-precision binary format. Where the first bit is the sign bit, followed by the exponent (11 bits) and the significand / mantissa (52 bits).

Other numbers (integers) will be represented in the two's complement format. Where negative numbers are actually displayed correctly compared to when using (number).toString(2).

Kind: static method of bit-manipulation
Returns: string - The binary representation.

| Param | Type | Default | Description | | --- | --- | --- | --- | | number | number | | The number to convert to binary. | | [paddingBits] | number | 8 | How many bits to align the output with. | | [grouping] | number | 4 | Group the output into chunks of this size. | | [showPrefix] | boolean | true | Whether to prefix the output with 0b or not. |

float : object

I failed finding any way for jsdoc-to-markdown to document the float namespace as being part of the bit-manipulation module, but it is...

Kind: global namespace

float.fromBits ⇒ number

Create a (64-bit double precision) floating point number by setting the bits in its exponent and significand (often called the mantissa). Set the signBit to turn the float into a negative number. For help see this: https://en.wikipedia.org/wiki/Double-precision_floating-point_format

Kind: static property of float
Returns: number - A 64-bit float.

| Param | Type | Description | | --- | --- | --- | | parts | object | The object holding information about which bits in the float is set. | | parts.exponent | number | Array.<number> | The exponent. | | parts.significand | number | bigint | Array.<number> | The fractional part. | | parts.signBit | boolean | Set it to make the float negative. |

float.toBits ⇒ object

Convert a (64-bit double precision) floating point number into an object with information about which bits are set. The exponent and significand (often called the mantissa) are returned as arrays containing the bit positions of any set bits (as in bits that are 1).

Kind: static property of float
Returns: object - {signBit, exponent, significand}

| Param | Type | | --- | --- | | float | number |

float.set ⇒ number

Set bits (as in setting them to 1) in the float supplied. This is done using an object with information about which bits to set in the exponent and the significand. Set the signBit to turn the float into a negative number.

Kind: static property of float
Returns: number - A 64-bit float.

| Param | Type | Description | | --- | --- | --- | | float | number | The float to manipulate. | | parts | object | The object holding information about which bits to set. | | parts.exponent | number | Array.<number> | The exponent. | | parts.significand | number | bigint | Array.<number> | The fractional part. | | parts.signBit | boolean | Set it to make the float negative. |

float.clear ⇒ number

Clear bits (as in setting them to 0) in the float supplied. This is done using an object with information about which bits to clear in the exponent and the significand.

Kind: static property of float
Returns: number - A 64-bit float.

| Param | Type | Description | | --- | --- | --- | | float | number | The float to manipulate. | | parts | object | The object holding information about which bits to clear. | | parts.exponent | number | Array.<number> | The exponent. | | parts.significand | number | bigint | Array.<number> | The fractional part. | | parts.signBit | boolean | Clear it to make a negative float positive. |

End of readme

Death is not the end of your consciousness, it's the expansion of it.