Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bigfixed

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bigfixed - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

src/BigFixed.js

2

package.json
{
"name": "bigfixed",
"version": "0.0.1",
"version": "0.0.2",
"description": "big fixed point number base on BigInt",

@@ -5,0 +5,0 @@ "keywords": [

@@ -15,2 +15,6 @@ # BigFixed

> NOTE: this lib is calculate by binary but not decimal number,
`BigFixed(0.1).add(0.2).toString() === "0.30000000000000004"`
## [Compare](https://github.com/GeekBerry/bigFixed/blob/master/example/compare.js)

@@ -20,14 +24,14 @@

Compare of big number lib
test number: 5073.876555537511,
test number: 3838.261003615915,
test count: 100000
Each duration in nano seconds (1e-9s):
Execution time in nano seconds(1e-9s):
Operate BigFixed BigNumber Big Decimal
new 3340 700 360 580
add 130 220 350 290
sub 120 240 510 460
mul 320 410 1120 680
div 920 3810 7620 3480
pow 480 1340 3990 2290
str 1060 210 430 260
new 580 750 410 690
add 90 210 240 270
sub 120 300 490 500
mul 210 420 1220 710
div 800 3760 6720 3360
pow 380 1360 3950 2330
str 530 220 410 250
```

@@ -34,0 +38,0 @@

@@ -1,265 +0,24 @@

/*
BigFixed 是基于 BigInt 实现的定点数, 小数部分保留 64 bit,
即类比于 fixed = float << 64
const Class = require('./BigFixed');
BigFixed range: ( -Inf, -(2**(-64)) ] & 0 & [ 2**(-64), +Inf )
BigFixed struct:
+--------------------------------+----------------------------------+
| signed N bits for integer part | signed 64 bits for fraction part |
+--------------------------------+----------------------------------+
*/
const {
abs,
slice,
fractionNumber,
compileBigInt,
compileBoolean,
compileNumber,
compileString,
} = require('./util');
const UINT64_HALF = BigInt(1) << BigInt(63);
const UINT64_TWOS = BigInt(1) << BigInt(64);
/**
* Cause javascript use float64 to implement `Number`,
* if value is number, `BigFixed` parse number binary data by **ieee-754**
* Function for both new and call can create instance.
* use `new Proxy(BigFixed, { apply: (Class, __, args) => new Class(...args) })` is too slow
*
* @param value {number|boolean|BigInt|string|BigFixed}
* @return {BigInt}
* @param args
* @return {BigFixed}
* @constructor
*
* @example
* > new BigFixed(1)
BigFixed { fixed: 18446744073709551616n }
* > BigFixed(1)
BigFixed { fixed: 18446744073709551616n }
*/
function toFixed(value) {
if (value === undefined || value === null) {
throw new Error(`unexpected type ${value}`);
}
if (value instanceof BigFixed) {
return value.fixed;
}
if (Number.isFinite(value)) {
return compileNumber(value);
}
if (value === false || value === true) {
return compileBoolean(value);
}
if (value.constructor === BigInt) {
return compileBigInt(value);
}
return compileString(`${value}`);
function BigFixed(...args) {
return new Class(...args);
}
// ============================================================================
class BigFixed {
constructor(value) {
this.fixed = toFixed(value);
}
BigFixed.prototype = Class.prototype;
Object.assign(BigFixed, Class);
clone() {
return new BigFixed(this);
}
// --------------------------------------------------------------------------
isZero() {
return this.fixed === BigInt(0);
}
isNegative() {
return this.fixed < BigInt(0);
}
isInteger() {
return slice(this.fixed, -64) === BigInt(0);
}
eq(value) {
return this.fixed === toFixed(value);
}
lt(value) {
return this.fixed < toFixed(value);
}
lte(value) {
return this.fixed <= toFixed(value);
}
gt(value) {
return this.fixed > toFixed(value);
}
gte(value) {
return this.fixed >= toFixed(value);
}
// ------------------------------- Arithmetic -----------------------------
neg() {
const bn = this.clone();
bn.fixed = -bn.fixed;
return bn;
}
abs() {
const bn = this.clone();
bn.fixed = abs(bn.fixed);
return bn;
}
add(value) {
const bn = this.clone();
bn.fixed += toFixed(value);
return bn;
}
sub(value) {
const bn = this.clone();
bn.fixed -= toFixed(value);
return bn;
}
mul(value) {
const bn = this.clone();
bn.fixed *= toFixed(value);
return bn.rShift(64);
}
div(value) {
const bn = this.lShift(64);
bn.fixed /= toFixed(value);
return bn;
}
mod(value) {
value = toFixed(value);
const bn = this.clone();
bn.fixed -= (bn.fixed / value) * value;
return bn;
}
pow(value) {
value = BigInt(value);
const bn = this.clone();
bn.fixed = (bn.fixed ** value) >> (BigInt(64) * value - BigInt(64));
return bn;
}
// -------------------------------- Logical -------------------------------
not() {
const bn = this.clone();
bn.fixed = ~bn.fixed;
return bn;
}
and(value) {
const bn = this.clone();
bn.fixed &= toFixed(value);
return bn;
}
or(value) {
const bn = this.clone();
bn.fixed |= toFixed(value);
return bn;
}
xor(value) {
const bn = this.clone();
bn.fixed ^= toFixed(value);
return bn;
}
lShift(count) {
const bn = this.clone();
bn.fixed <<= BigInt(count);
return bn;
}
rShift(count) {
const bn = this.clone();
if (bn.isNegative()) {
bn.fixed = -((-bn.fixed) >> BigInt(count));
} else {
bn.fixed >>= BigInt(count);
}
return bn;
}
// --------------------------------------------------------------------------
/**
* @param [mode=BigFixed.ROUND] {string} - Round mode, enum [BigFixed.CEIL, BigFixed.ROUND, BigFixed.FLOOR]
* @return {BigFixed}
*/
toInteger(mode = BigFixed.ROUND) {
const bn = this.clone();
const frac = slice(bn.fixed, -64);
bn.fixed ^= frac;
switch (mode) {
case BigFixed.CEIL:
if (frac) {
bn.fixed += UINT64_TWOS;
}
break;
case BigFixed.ROUND:
if (frac >= UINT64_HALF) {
bn.fixed += UINT64_TWOS;
}
break;
case BigFixed.FLOOR:
break;
default:
throw new Error(`unexpected round mode "${mode}"`);
}
return bn;
}
/**
* @return {number}
*/
toNumber() {
return Number(this.toString());
}
toJSON() {
return this.toString();
}
/**
* @param [base=10] {number}
* @return {string}
*/
toString(base = 10) {
const absFixed = abs(this.fixed);
const signString = this.isNegative() ? '-' : '';
const int = (absFixed >> BigInt(64));
const fracNumber = fractionNumber(slice(absFixed, -64));
return `${signString}${int.toString(base)}${fracNumber.toString(base).slice(1)}`; // slice 1 to skip '0'
}
}
BigFixed.CEIL = 'ceil';
BigFixed.ROUND = 'round';
BigFixed.FLOOR = 'floor';
// ============================================================================
function withoutNew(cls) {
return new Proxy(cls, { apply: (_, __, params) => new cls(...params) });
}
module.exports = withoutNew(BigFixed);
module.exports = BigFixed;

@@ -1,14 +0,15 @@

/*
[IEEE 754](https://en.wikipedia.org/wiki/IEEE_754)
const BIG_INT_0 = BigInt(0);
const BIG_INT_64 = BigInt(64);
float64: S EEEEEEEEEEE DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
1 11 52
*/
const UINT64_SIGN = BigInt(1) << BigInt(63);
const UINT64_TWOS = BigInt(1) << BigInt(64);
const UINT64_TWOS_NUMBER = Number(UINT64_TWOS);
const FLOAT64_FRAC_TOWS = BigInt(1) << BigInt(52);
const FLOAT64_EXP_OFFSET = BigInt(1023); // (2**11/2 - 1)
const FLOAT64_FRAC_TOWS = BigInt(1) << BigInt(52);
const UINT64_SIGN = BigInt(1) << BigInt(63);
const FLOAT64_FRAC_OFFSET = BigInt(64) - BigInt(52) - FLOAT64_EXP_OFFSET;
const VIEW64 = new DataView(new ArrayBuffer(8)); // 8=64/8
// ----------------------------------------------------------------------------
function float64ToUInt64(number) {

@@ -19,8 +20,6 @@ VIEW64.setFloat64(0, number);

function uInt64ToFloat64(bUInt64) {
VIEW64.setBigUint64(0, bUInt64);
return VIEW64.getFloat64(0);
function abs(bigInt) {
return bigInt < BIG_INT_0 ? -bigInt : bigInt;
}
// ----------------------------------------------------------------------------
function slice(uInt64, startBit = 0, stopBit = 64) {

@@ -32,42 +31,19 @@ startBit = startBit >= 0 ? startBit : 64 + startBit;

function abs(bigInt) {
return bigInt < BigInt(0) ? -bigInt : bigInt;
}
// ============================================================================
/**
* Get BigFixed fraction part as number (for toString).
*
* @param bUInt64 {BigInt}
* @return {number}
*/
function fractionNumber(bUInt64) {
let exp = FLOAT64_EXP_OFFSET;
if (bUInt64) {
while (!(bUInt64 & UINT64_SIGN)) {
bUInt64 <<= BigInt(1);
exp -= BigInt(1);
}
bUInt64 <<= BigInt(1);
exp -= BigInt(1);
} else {
exp = BigInt(0);
}
const fraction = slice(bUInt64, 0, 52);
return uInt64ToFloat64(exp << BigInt(52) | fraction);
}
// ----------------------------------------------------------------------------
function compileBigInt(bigInt) {
return bigInt << BigInt(64);
return bigInt << BIG_INT_64;
}
function compileBoolean(boolean) {
return boolean ? BigInt(1) << BigInt(64) : BigInt(0);
return boolean ? UINT64_TWOS : BIG_INT_0;
}
/**
* Compile IEEE 754 float64 to fixed64 BigInt
* Compile IEEE 754 float64 to fixed64 BigInt.
*
* [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754)
*
* float64: S EEEEEEEEEEE DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
* 1 11 52
*
* @param number {number}

@@ -87,3 +63,3 @@ * @return {BigInt}

return (sign ? -fraction : fraction) << (exp - FLOAT64_EXP_OFFSET + BigInt(12));
return (sign ? -fraction : fraction) << (exp + FLOAT64_FRAC_OFFSET);
}

@@ -99,3 +75,3 @@

if (/^\s*(0x[0-9a-f]+|0o[0-7]+|0b[01]+|[+-]?[0-9]+)\s*$/i.test(string)) {
return BigInt(string) << BigInt(64);
return BigInt(string) << BIG_INT_64;
}

@@ -109,5 +85,5 @@

const frac = compileNumber(Number(`0.${fracString}`));
const fixed = (abs(int) << BigInt(64)) | frac;
const fixed = (abs(int) << BIG_INT_64) | frac;
return int < BigInt(0) ? -fixed : fixed;
return int < BIG_INT_0 ? -fixed : fixed;
}

@@ -120,5 +96,10 @@

module.exports = {
BIG_INT_0,
BIG_INT_64,
UINT64_SIGN,
UINT64_TWOS,
UINT64_TWOS_NUMBER,
abs,
slice,
fractionNumber,
compileBoolean,

@@ -125,0 +106,0 @@ compileBigInt,

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc