Comparing version 0.9.2 to 0.9.3
@@ -0,3 +1,6 @@ | ||
## 0.9.3 (Dec 17, 2021) | ||
* Support setting radix for Float string operations (by Yuri Stuken) | ||
## 0.9.2 (Dec 5, 2021) | ||
* Add mini build without Float / MPFR functions | ||
* Add mini bundle without Float / MPFR functions | ||
@@ -4,0 +7,0 @@ ## 0.9.1 (Dec 4, 2021) |
@@ -27,2 +27,3 @@ import type { GMPFunctions } from './functions'; | ||
roundingMode?: FloatRoundingMode; | ||
radix?: number; | ||
} | ||
@@ -34,2 +35,3 @@ export declare function getFloatContext(gmp: GMPFunctions, ctx: any, ctxOptions?: FloatOptions): { | ||
rndMode: number; | ||
radix: number; | ||
type: string; | ||
@@ -150,4 +152,4 @@ readonly options: FloatOptions; | ||
exponent2(): number; | ||
toString(): string; | ||
toFixed(digits?: number): any; | ||
toString(radix?: number): string; | ||
toFixed(digits?: number, radix?: number): any; | ||
toInteger(): Integer; | ||
@@ -161,2 +163,3 @@ toRational(): Rational; | ||
rndMode: number; | ||
radix: number; | ||
type: string; | ||
@@ -277,4 +280,4 @@ readonly options: FloatOptions; | ||
exponent2(): number; | ||
toString(): string; | ||
toFixed(digits?: number): any; | ||
toString(radix?: number): string; | ||
toFixed(digits?: number, radix?: number): any; | ||
toInteger(): Integer; | ||
@@ -287,2 +290,3 @@ toRational(): Rational; | ||
rndMode: number; | ||
radix: number; | ||
type: string; | ||
@@ -403,4 +407,4 @@ readonly options: FloatOptions; | ||
exponent2(): number; | ||
toString(): string; | ||
toFixed(digits?: number): any; | ||
toString(radix?: number): string; | ||
toFixed(digits?: number, radix?: number): any; | ||
toInteger(): Integer; | ||
@@ -414,2 +418,3 @@ toRational(): Rational; | ||
rndMode: number; | ||
radix: number; | ||
type: string; | ||
@@ -530,4 +535,4 @@ readonly options: FloatOptions; | ||
exponent2(): number; | ||
toString(): string; | ||
toFixed(digits?: number): any; | ||
toString(radix?: number): string; | ||
toFixed(digits?: number, radix?: number): any; | ||
toInteger(): Integer; | ||
@@ -540,2 +545,3 @@ toRational(): Rational; | ||
rndMode: number; | ||
radix: number; | ||
type: string; | ||
@@ -656,4 +662,4 @@ readonly options: FloatOptions; | ||
exponent2(): number; | ||
toString(): string; | ||
toFixed(digits?: number): any; | ||
toString(radix?: number): string; | ||
toFixed(digits?: number, radix?: number): any; | ||
toInteger(): Integer; | ||
@@ -660,0 +666,0 @@ toRational(): Rational; |
@@ -6,1 +6,3 @@ export declare function isUint32(num: number): boolean; | ||
export declare function assertArray(arr: any[]): void; | ||
export declare function isValidRadix(radix: number): boolean; | ||
export declare function assertValidRadix(radix: number): void; |
{ | ||
"name": "gmp-wasm", | ||
"version": "0.9.2", | ||
"version": "0.9.3", | ||
"description": "Arbitrary-precision Integer, Rational and Float types based on the GMP and MPFR libraries", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.umd.js", |
@@ -81,3 +81,3 @@ # GMP-WASM | ||
```js | ||
const roundingMode = gmp.FloatRoundingMode.ROUND_TOWARD_NEG_INF; | ||
const roundingMode = gmp.FloatRoundingMode.ROUND_DOWN; | ||
const options = { precisionBits: 10, roundingMode }; | ||
@@ -84,0 +84,0 @@ |
import type { GMPFunctions, mpfr_rnd_t } from './functions'; | ||
import { Integer } from './integer'; | ||
import { Rational } from './rational'; | ||
import { assertInt32, assertUint32, isInt32 } from './util'; | ||
import {assertInt32, assertUint32, assertValidRadix, isInt32} from './util'; | ||
@@ -46,2 +46,3 @@ const decoder = new TextDecoder(); | ||
roundingMode?: FloatRoundingMode; | ||
radix?: number; | ||
}; | ||
@@ -110,3 +111,6 @@ | ||
const globalPrecisionBits = ctxOptions.precisionBits ?? 52; | ||
const globalRadix = ctxOptions.radix ?? 10; | ||
assertUint32(globalPrecisionBits); | ||
assertValidRadix(globalRadix); | ||
@@ -119,3 +123,3 @@ const compare = (mpfr_t: number, val: AllTypes): number => { | ||
if (typeof val === 'string') { | ||
const f = FloatFn(val); | ||
const f = FloatFn(val, ctxOptions); | ||
return gmp.mpfr_cmp(mpfr_t, f.mpfr_t); | ||
@@ -142,2 +146,3 @@ } | ||
roundingMode: options2?.roundingMode ?? options1.roundingMode ?? ctxOptions.roundingMode, | ||
radix: options2?.radix ?? options1.radix ?? ctxOptions.radix, | ||
}; | ||
@@ -150,2 +155,3 @@ }; | ||
rndMode: -1, | ||
radix: -1, | ||
type: 'float', | ||
@@ -157,2 +163,3 @@ | ||
roundingMode: this.rndMode ?? globalRndMode, | ||
radix: this.radix ?? globalRadix, | ||
}; | ||
@@ -165,2 +172,3 @@ }, | ||
roundingMode: this.rndMode, | ||
radix: this.radix, | ||
}; | ||
@@ -767,5 +775,8 @@ }, | ||
toString() { | ||
toString(radix?: number) { | ||
radix = radix ?? this.options.radix; | ||
assertValidRadix(radix); | ||
const mpfr_exp_t_ptr = gmp.malloc(4); | ||
const strptr = gmp.mpfr_get_str(0, mpfr_exp_t_ptr, 10, 0, this.mpfr_t, this.rndMode); | ||
const strptr = gmp.mpfr_get_str(0, mpfr_exp_t_ptr, radix, 0, this.mpfr_t, this.rndMode); | ||
const endptr = gmp.mem.indexOf(0, strptr); | ||
@@ -787,5 +798,8 @@ let ret = decoder.decode(gmp.mem.subarray(strptr, endptr)); | ||
toFixed(digits = 0) { | ||
toFixed(digits = 0, radix?: number) { | ||
assertUint32(digits); | ||
const str = this.toString(); | ||
radix = radix ?? this.options.radix; | ||
assertValidRadix(radix); | ||
const str = this.toString(radix); | ||
if (Object.values(SPECIAL_VALUES).includes(str)) { | ||
@@ -795,8 +809,17 @@ return str; | ||
if (digits === 0) { | ||
return ctx.intContext.Integer(this).toString(); | ||
return ctx.intContext.Integer(this).toString(radix); | ||
} | ||
const multiplied = this.mul(FloatFn(digits).exp10()); | ||
let multiplier = null; | ||
if (radix === 2) { | ||
multiplier = FloatFn(digits).exp2(); | ||
} else if (radix === 10) { | ||
multiplier = FloatFn(digits).exp10(); | ||
} else { | ||
multiplier = FloatFn(radix).pow(digits); | ||
} | ||
const multiplied = this.mul(multiplier); | ||
const int = ctx.intContext.Integer(multiplied); | ||
const isNegative = int.sign() === -1; | ||
let intStr = int.abs().toString(); | ||
let intStr = int.abs().toString(radix); | ||
if (intStr.length < digits + 1) { | ||
@@ -817,7 +840,10 @@ intStr = '0'.repeat(digits + 1 - intStr.length) + intStr; | ||
const setValue = (mpfr_t: number, rndMode: mpfr_rnd_t, val: string | number | Float | Rational | Integer) => { | ||
const setValue = (mpfr_t: number, rndMode: mpfr_rnd_t, radix: number, val: string | number | Float | Rational | Integer) => { | ||
if (typeof val === 'string') { | ||
const strPtr = gmp.malloc_cstr(val); | ||
gmp.mpfr_set_str(mpfr_t, strPtr, 10, rndMode); | ||
const res = gmp.mpfr_set_str(mpfr_t, strPtr, radix, rndMode); | ||
gmp.free(strPtr); | ||
if (res !== 0) { | ||
throw new Error('Invalid number provided!'); | ||
} | ||
return; | ||
@@ -854,2 +880,4 @@ } | ||
const precisionBits = options?.precisionBits ?? globalPrecisionBits; | ||
const radix = options?.radix ?? globalRadix; | ||
assertValidRadix(radix); | ||
@@ -859,2 +887,3 @@ const instance = Object.create(FloatPrototype) as typeof FloatPrototype; | ||
instance.precisionBits = precisionBits; | ||
instance.radix = radix; | ||
instance.mpfr_t = gmp.mpfr_t(); | ||
@@ -864,3 +893,3 @@ gmp.mpfr_init2(instance.mpfr_t, precisionBits); | ||
if (val !== undefined && val !== null) { | ||
setValue(instance.mpfr_t, rndMode, val); | ||
setValue(instance.mpfr_t, rndMode, radix, val); | ||
} | ||
@@ -867,0 +896,0 @@ |
import type { GMPFunctions } from './functions'; | ||
import { Float } from './float'; | ||
import { Rational } from './rational'; | ||
import { assertArray, assertInt32, assertUint32 } from './util'; | ||
import {assertArray, assertInt32, assertUint32, assertValidRadix} from './util'; | ||
@@ -572,5 +572,3 @@ const decoder = new TextDecoder(); | ||
} else if (typeof num === 'string') { | ||
if (!Number.isSafeInteger(radix) || radix < 2 || radix > 36) { | ||
throw new Error('radix must have a value between 2 and 36'); | ||
} | ||
assertValidRadix(radix); | ||
const strPtr = gmp.malloc_cstr(num); | ||
@@ -577,0 +575,0 @@ const res = gmp.mpz_init_set_str(instance.mpz_t, strPtr, radix); |
@@ -26,1 +26,11 @@ export function isUint32(num: number) { | ||
} | ||
export function isValidRadix(radix: number) { | ||
return Number.isSafeInteger(radix) && radix >= 2 && radix <= 36; | ||
} | ||
export function assertValidRadix(radix: number) { | ||
if (!isValidRadix(radix)) { | ||
throw new Error('radix must have a value between 2 and 36'); | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { CalculateTypeWithDestroy, FloatRoundingMode, init as initGMP } from '../src'; | ||
import {CalculateTypeWithDestroy, FloatRoundingMode, FloatType, init as initGMP, IntegerType, RationalType} from '../src'; | ||
/* global test, expect */ | ||
@@ -17,4 +17,4 @@ | ||
const compare = (int: ReturnType<typeof ctx.Float>, res: string) => { | ||
expect(int.toString()).toBe(res); | ||
const compare = (int: IntegerType | RationalType | FloatType, res: string, radix = 10) => { | ||
expect(int.toString(radix)).toBe(res); | ||
} | ||
@@ -32,2 +32,8 @@ | ||
compare(ctx.Float('10000.000'), '10000'); | ||
compare(ctx.Float('110', { radix: 2 }), '6') | ||
compare(ctx.Float('1a', { radix: 16 }), '26'); | ||
compare(ctx.Float('-1A', { radix: 16 }), '-26'); | ||
compare(ctx.Float('0.1', { radix: 2 }), '0.5'); | ||
compare(ctx.Float('-0.1', { radix: 2 }), '-0.5'); | ||
compare(ctx.Float('0.10000', { radix: 2 }), '0.5'); | ||
}); | ||
@@ -77,2 +83,4 @@ | ||
compare(ctx.Float(0.4).add(ctx.Rational(1, 2)), '0.899994'); | ||
compare(ctx.Float('1.01', { radix: 2 }).add('10.1'), '3.75'); | ||
compare(ctx.Float('1.01', { radix: 2 }).add(10.1), '11.3501'); | ||
}); | ||
@@ -88,2 +96,4 @@ | ||
compare(ctx.Float(0.4).sub(ctx.Rational(1, 2)), '-0.0999985'); | ||
compare(ctx.Float('1.01', { radix: 2 }).sub('10.1'), '-1.25'); | ||
compare(ctx.Float('1.01', { radix: 2 }).sub(10.1), '-8.8501'); | ||
}); | ||
@@ -99,2 +109,4 @@ | ||
compare(ctx.Float(0.4).mul(ctx.Rational(1, 2)), '0.200001'); | ||
compare(ctx.Float('1.01', { radix: 2 }).mul('10.1'), '3.125'); | ||
compare(ctx.Float('1.01', { radix: 2 }).mul(10.1), '12.625'); | ||
}); | ||
@@ -110,2 +122,4 @@ | ||
compare(ctx.Float(6).div(ctx.Rational(4, 2)), '3'); | ||
compare(ctx.Float('1.01', { radix: 2 }).div('10.1'), '0.5'); | ||
compare(ctx.Float('1.01', { radix: 2 }).div(10.1), '0.123762'); | ||
}); | ||
@@ -207,2 +221,5 @@ | ||
expect(ctx.Float(1).lessThan(ctx.Float(2))).toBe(true); | ||
const binaryCtx = gmp.getContext({ radix: 2 }); | ||
expect(binaryCtx.Float('101').lessThan(100)).toBe(true); | ||
expect(binaryCtx.Float('101').lessThan('100')).toBe(false); | ||
}); | ||
@@ -230,2 +247,5 @@ | ||
expect(ctx.Float(1).greaterThan(ctx.Float(2))).toBe(false); | ||
const binaryCtx = gmp.getContext({ radix: 2 }); | ||
expect(binaryCtx.Float('101').greaterThan(100)).toBe(false); | ||
expect(binaryCtx.Float('101').greaterThan('100')).toBe(true); | ||
}); | ||
@@ -436,2 +456,8 @@ | ||
expect(ctx.Float('0.1').mul(ctx.Float('0.2')).toFixed(2)).toBe('0.02'); | ||
expect(ctx.Float('123.5000').toFixed(0, 16)).toBe('7c'); | ||
expect(ctx.Float('123.5000').toFixed(1, 16)).toBe('7b.8'); | ||
expect(ctx.Float('0.1', { radix: 3 }).toFixed(3)).toBe('0.100'); | ||
expect(ctx.Float('0.1', { radix: 3 }).toFixed(3, 10)).toBe('0.333'); | ||
expect(ctx.Float('0.1', { radix: 3 }).toFixed(3, 4)).toBe('0.111'); | ||
expect(ctx.Float('10.110101', { radix: 2 }).toFixed(3)).toBe('10.111'); | ||
}); | ||
@@ -474,2 +500,6 @@ | ||
expect(gmp.calculate(g => g.Float(1).div(g.Float(3, { roundingMode: ROUND_UP })), options)).toBe('0.33301'); | ||
// merge radix | ||
expect(gmp.calculate(g => g.Float('3', { radix: 4 }).div('21'),{})).toBe('0.111111111111111111111111112'); | ||
expect(gmp.calculate(g => g.Float('3').div('21'),{ radix: 4 })).toBe('0.111111111111111111111111112'); | ||
expect(gmp.calculate(g => g.Float('3').div(g.Float('21', { radix: 4 })),{})).toBe('0.111111111111111111111111112'); | ||
}); | ||
@@ -476,0 +506,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3628595
28438