Remove BigDecimal (#29)
Part of https://github.com/quickjs-ng/quickjs/issues/17
This commit is contained in:
parent
558a2ac761
commit
5d5b3cc21f
11 changed files with 56 additions and 1835 deletions
2
Makefile
2
Makefile
|
@ -54,7 +54,7 @@ prefix=/usr/local
|
||||||
#CONFIG_MSAN=y
|
#CONFIG_MSAN=y
|
||||||
# use UB sanitizer
|
# use UB sanitizer
|
||||||
#CONFIG_UBSAN=y
|
#CONFIG_UBSAN=y
|
||||||
# include the code for BigInt/BigFloat/BigDecimal and math mode
|
# include the code for BigInt/BigFloat
|
||||||
CONFIG_BIGNUM=y
|
CONFIG_BIGNUM=y
|
||||||
|
|
||||||
OBJDIR=.obj
|
OBJDIR=.obj
|
||||||
|
|
|
@ -1,589 +0,0 @@
|
||||||
\input texinfo
|
|
||||||
|
|
||||||
@iftex
|
|
||||||
@afourpaper
|
|
||||||
@headings double
|
|
||||||
@end iftex
|
|
||||||
|
|
||||||
@titlepage
|
|
||||||
@afourpaper
|
|
||||||
@sp 7
|
|
||||||
@center @titlefont{Javascript Bignum Extensions}
|
|
||||||
@sp 3
|
|
||||||
@center Version 2020-01-11
|
|
||||||
@sp 3
|
|
||||||
@center Author: Fabrice Bellard
|
|
||||||
@end titlepage
|
|
||||||
|
|
||||||
@setfilename jsbignum.info
|
|
||||||
@settitle Javascript Bignum Extensions
|
|
||||||
|
|
||||||
@contents
|
|
||||||
|
|
||||||
@chapter Introduction
|
|
||||||
|
|
||||||
The Bignum extensions add the following features to the Javascript
|
|
||||||
language while being 100% backward compatible:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
|
|
||||||
@item Operator overloading with a dispatch logic inspired from the proposal available at @url{https://github.com/tc39/proposal-operator-overloading/}.
|
|
||||||
|
|
||||||
@item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics.
|
|
||||||
|
|
||||||
@item Arbitrarily large floating point numbers (@code{BigDecimal}) in base 10 based on the proposal available at
|
|
||||||
@url{https://github.com/littledan/proposal-bigdecimal}.
|
|
||||||
|
|
||||||
@item @code{math} mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (@code{%}) is defined as the Euclidian
|
|
||||||
remainder. @code{^} is an alias to the power operator
|
|
||||||
(@code{**}). @code{^^} is used as the exclusive or operator.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
The extensions are independent from each other except the @code{math}
|
|
||||||
mode which relies on BigFloat and operator overloading.
|
|
||||||
|
|
||||||
@chapter Operator overloading
|
|
||||||
|
|
||||||
Operator overloading is inspired from the proposal available at
|
|
||||||
@url{https://github.com/tc39/proposal-operator-overloading/}. It
|
|
||||||
implements the same dispatch logic but finds the operator sets by
|
|
||||||
looking at the @code{Symbol.operatorSet} property in the objects. The
|
|
||||||
changes were done in order to simplify the implementation.
|
|
||||||
|
|
||||||
More precisely, the following modifications were made:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
|
|
||||||
@item @code{with operators from} is not supported. Operator overloading is always enabled.
|
|
||||||
|
|
||||||
@item The dispatch is not based on a static @code{[[OperatorSet]]} field in all instances. Instead, a dynamic lookup of the @code{Symbol.operatorSet} property is done. This property is typically added in the prototype of each object.
|
|
||||||
|
|
||||||
@item @code{Operators.create(...dictionaries)} is used to create a new OperatorSet object. The @code{Operators} function is supported as an helper to be closer to the TC39 proposal.
|
|
||||||
|
|
||||||
@item @code{[]} cannot be overloaded.
|
|
||||||
|
|
||||||
@item In math mode, the BigInt division and power operators can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
@chapter BigInt extensions
|
|
||||||
|
|
||||||
A few properties are added to the BigInt object:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item tdiv(a, b)
|
|
||||||
Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError
|
|
||||||
exception.
|
|
||||||
|
|
||||||
@item fdiv(a, b)
|
|
||||||
Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError
|
|
||||||
exception.
|
|
||||||
|
|
||||||
@item cdiv(a, b)
|
|
||||||
Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError
|
|
||||||
exception.
|
|
||||||
|
|
||||||
@item ediv(a, b)
|
|
||||||
Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian
|
|
||||||
division). @code{b = 0} raises a RangeError exception.
|
|
||||||
|
|
||||||
@item tdivrem(a, b)
|
|
||||||
@item fdivrem(a, b)
|
|
||||||
@item cdivrem(a, b)
|
|
||||||
@item edivrem(a, b)
|
|
||||||
Return an array of two elements. The first element is the quotient,
|
|
||||||
the second is the remainder. The same rounding is done as the
|
|
||||||
corresponding division operation.
|
|
||||||
|
|
||||||
@item sqrt(a)
|
|
||||||
Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is
|
|
||||||
raised if @math{a < 0}.
|
|
||||||
|
|
||||||
@item sqrtrem(a)
|
|
||||||
Return an array of two elements. The first element is @math{\lfloor
|
|
||||||
\sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a}
|
|
||||||
\rfloor^2}. A RangeError exception is raised if @math{a < 0}.
|
|
||||||
|
|
||||||
@item floorLog2(a)
|
|
||||||
Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}.
|
|
||||||
|
|
||||||
@item ctz(a)
|
|
||||||
Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@chapter BigFloat
|
|
||||||
|
|
||||||
@section Introduction
|
|
||||||
|
|
||||||
This extension adds the @code{BigFloat} primitive type. The
|
|
||||||
@code{BigFloat} type represents floating point numbers in base 2
|
|
||||||
with the IEEE 754 semantics. A floating
|
|
||||||
point number is represented as a sign, mantissa and exponent. The
|
|
||||||
special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0}
|
|
||||||
are supported. The mantissa and exponent can have any bit length with
|
|
||||||
an implementation specific minimum and maximum.
|
|
||||||
|
|
||||||
@section Floating point rounding
|
|
||||||
|
|
||||||
Each floating point operation operates with infinite precision and
|
|
||||||
then rounds the result according to the specified floating point
|
|
||||||
environment (@code{BigFloatEnv} object). The status flags of the
|
|
||||||
environment are also set according to the result of the operation.
|
|
||||||
|
|
||||||
If no floating point environment is provided, the global floating
|
|
||||||
point environment is used.
|
|
||||||
|
|
||||||
The rounding mode of the global floating point environment is always
|
|
||||||
@code{RNDN} (``round to nearest with ties to even'')@footnote{The
|
|
||||||
rationale is that the rounding mode changes must always be
|
|
||||||
explicit.}. The status flags of the global environment cannot be
|
|
||||||
read@footnote{The rationale is to avoid side effects for the built-in
|
|
||||||
operators.}. The precision of the global environment is
|
|
||||||
@code{BigFloatEnv.prec}. The number of exponent bits of the global
|
|
||||||
environment is @code{BigFloatEnv.expBits}. The global environment
|
|
||||||
subnormal flag is set to @code{true}.
|
|
||||||
|
|
||||||
For example, @code{prec = 53} and @code{ expBits = 11} exactly give
|
|
||||||
the same precision as the IEEE 754 64 bit floating point format. The
|
|
||||||
default precision is @code{prec = 113} and @code{ expBits = 15} (IEEE
|
|
||||||
754 128 bit floating point format).
|
|
||||||
|
|
||||||
The global floating point environment can only be modified temporarily
|
|
||||||
when calling a function (see @code{BigFloatEnv.setPrec}). Hence a
|
|
||||||
function can change the global floating point environment for its
|
|
||||||
callees but not for its caller.
|
|
||||||
|
|
||||||
@section Operators
|
|
||||||
|
|
||||||
The builtin operators are extended so that a BigFloat is returned if
|
|
||||||
at least one operand is a BigFloat. The computations are always done
|
|
||||||
with infinite precision and rounded according to the global floating
|
|
||||||
point environment.
|
|
||||||
|
|
||||||
@code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}.
|
|
||||||
|
|
||||||
BigFloat can be compared with all the other numeric types and the
|
|
||||||
result follows the expected mathematical relations.
|
|
||||||
|
|
||||||
However, since BigFloat and Number are different types they are never
|
|
||||||
equal when using the strict comparison operators (e.g. @code{0.0 ===
|
|
||||||
0.0l} is false).
|
|
||||||
|
|
||||||
@section BigFloat literals
|
|
||||||
|
|
||||||
BigFloat literals are floating point numbers with a trailing @code{l}
|
|
||||||
suffix. BigFloat literals have an infinite precision. They are rounded
|
|
||||||
according to the global floating point environment when they are
|
|
||||||
evaluated.@footnote{Base 10 floating point literals cannot usually be
|
|
||||||
exactly represented as base 2 floating point number. In order to
|
|
||||||
ensure that the literal is represented accurately with the current
|
|
||||||
precision, it must be evaluated at runtime.}
|
|
||||||
|
|
||||||
@section Builtin Object changes
|
|
||||||
|
|
||||||
@subsection @code{BigFloat} function
|
|
||||||
|
|
||||||
The @code{BigFloat} function cannot be invoked as a constructor. When
|
|
||||||
invoked as a function: the parameter is converted to a primitive
|
|
||||||
type. If the result is a numeric type, it is converted to BigFloat
|
|
||||||
without rounding. If the result is a string, it is converted to
|
|
||||||
BigFloat using the precision of the global floating point environment.
|
|
||||||
|
|
||||||
@code{BigFloat} properties:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item LN2
|
|
||||||
@item PI
|
|
||||||
Getter. Return the value of the corresponding mathematical constant
|
|
||||||
rounded to nearest, ties to even with the current global
|
|
||||||
precision. The constant values are cached for small precisions.
|
|
||||||
|
|
||||||
@item MIN_VALUE
|
|
||||||
@item MAX_VALUE
|
|
||||||
@item EPSILON
|
|
||||||
Getter. Return the minimum, maximum and epsilon @code{BigFloat} values
|
|
||||||
(same definition as the corresponding @code{Number} constants).
|
|
||||||
|
|
||||||
@item fpRound(a[, e])
|
|
||||||
Round the floating point number @code{a} according to the floating
|
|
||||||
point environment @code{e} or the global environment if @code{e} is
|
|
||||||
undefined.
|
|
||||||
|
|
||||||
@item parseFloat(a[, radix[, e]])
|
|
||||||
Parse the string @code{a} as a floating point number in radix
|
|
||||||
@code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0
|
|
||||||
means radix 10 unless there is a hexadecimal or binary prefix. The
|
|
||||||
result is rounded according to the floating point environment @code{e}
|
|
||||||
or the global environment if @code{e} is undefined.
|
|
||||||
|
|
||||||
@item isFinite(a)
|
|
||||||
Return true if @code{a} is a finite bigfloat.
|
|
||||||
|
|
||||||
@item isNaN(a)
|
|
||||||
Return true if @code{a} is a NaN bigfloat.
|
|
||||||
|
|
||||||
@item add(a, b[, e])
|
|
||||||
@item sub(a, b[, e])
|
|
||||||
@item mul(a, b[, e])
|
|
||||||
@item div(a, b[, e])
|
|
||||||
Perform the specified floating point operation and round the floating
|
|
||||||
point number @code{a} according to the floating point environment
|
|
||||||
@code{e} or the global environment if @code{e} is undefined. If
|
|
||||||
@code{e} is specified, the floating point status flags are updated.
|
|
||||||
|
|
||||||
@item floor(x)
|
|
||||||
@item ceil(x)
|
|
||||||
@item round(x)
|
|
||||||
@item trunc(x)
|
|
||||||
Round to an integer. No additional rounding is performed.
|
|
||||||
|
|
||||||
@item abs(x)
|
|
||||||
Return the absolute value of x. No additional rounding is performed.
|
|
||||||
|
|
||||||
@item fmod(x, y[, e])
|
|
||||||
@item remainder(x, y[, e])
|
|
||||||
Floating point remainder. The quotient is truncated to zero (fmod) or
|
|
||||||
to the nearest integer with ties to even (remainder). @code{e} is an
|
|
||||||
optional floating point environment.
|
|
||||||
|
|
||||||
@item sqrt(x[, e])
|
|
||||||
Square root. Return a rounded floating point number. @code{e} is an
|
|
||||||
optional floating point environment.
|
|
||||||
|
|
||||||
@item sin(x[, e])
|
|
||||||
@item cos(x[, e])
|
|
||||||
@item tan(x[, e])
|
|
||||||
@item asin(x[, e])
|
|
||||||
@item acos(x[, e])
|
|
||||||
@item atan(x[, e])
|
|
||||||
@item atan2(x, y[, e])
|
|
||||||
@item exp(x[, e])
|
|
||||||
@item log(x[, e])
|
|
||||||
@item pow(x, y[, e])
|
|
||||||
Transcendental operations. Return a rounded floating point
|
|
||||||
number. @code{e} is an optional floating point environment.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@subsection @code{BigFloat.prototype}
|
|
||||||
|
|
||||||
The following properties are modified:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item valueOf()
|
|
||||||
Return the bigfloat primitive value corresponding to @code{this}.
|
|
||||||
|
|
||||||
@item toString(radix)
|
|
||||||
|
|
||||||
For floating point numbers:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
@item
|
|
||||||
If the radix is a power of two, the conversion is done with infinite
|
|
||||||
precision.
|
|
||||||
@item
|
|
||||||
Otherwise, the number is rounded to nearest with ties to even using
|
|
||||||
the global precision. It is then converted to string using the minimum
|
|
||||||
number of digits so that its conversion back to a floating point using
|
|
||||||
the global precision and round to nearest gives the same number.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
The exponent letter is @code{e} for base 10, @code{p} for bases 2, 8,
|
|
||||||
16 with a binary exponent and @code{@@} for the other bases.
|
|
||||||
|
|
||||||
@item toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
|
|
||||||
@item toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
|
|
||||||
@item toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
|
|
||||||
Same semantics as the corresponding @code{Number} functions with
|
|
||||||
BigFloats. There is no limit on the accepted precision @code{p}. The
|
|
||||||
rounding mode and radix can be optionally specified. The radix must be
|
|
||||||
between 2 and 36.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@subsection @code{BigFloatEnv} constructor
|
|
||||||
|
|
||||||
The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a
|
|
||||||
function. The floating point environment contains:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
@item the mantissa precision in bits
|
|
||||||
|
|
||||||
@item the exponent size in bits assuming an IEEE 754 representation;
|
|
||||||
|
|
||||||
@item the subnormal flag (if true, subnormal floating point numbers can
|
|
||||||
be generated by the floating point operations).
|
|
||||||
|
|
||||||
@item the rounding mode
|
|
||||||
|
|
||||||
@item the floating point status. The status flags can only be set by the floating point operations. They can be reset with @code{BigFloatEnv.prototype.clearStatus()} or with the various status flag setters.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
@code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point
|
|
||||||
environment. The status flags are reset. If no parameter is given the
|
|
||||||
precision, exponent bits and subnormal flags are copied from the
|
|
||||||
global floating point environment. Otherwise, the precision is set to
|
|
||||||
@code{p}, the number of exponent bits is set to @code{expBitsMax} and the
|
|
||||||
subnormal flags is set to @code{false}. If @code{rndMode} is
|
|
||||||
@code{undefined}, the rounding mode is set to @code{RNDN}.
|
|
||||||
|
|
||||||
@code{BigFloatEnv} properties:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item prec
|
|
||||||
Getter. Return the precision in bits of the global floating point
|
|
||||||
environment. The initial value is @code{113}.
|
|
||||||
|
|
||||||
@item expBits
|
|
||||||
Getter. Return the exponent size in bits of the global floating point
|
|
||||||
environment assuming an IEEE 754 representation. The initial value is
|
|
||||||
@code{15}.
|
|
||||||
|
|
||||||
@item setPrec(f, p[, e])
|
|
||||||
Set the precision of the global floating point environment to @code{p}
|
|
||||||
and the exponent size to @code{e} then call the function
|
|
||||||
@code{f}. Then the Float precision and exponent size are reset to
|
|
||||||
their precious value and the return value of @code{f} is returned (or
|
|
||||||
an exception is raised if @code{f} raised an exception). If @code{e}
|
|
||||||
is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}.
|
|
||||||
|
|
||||||
@item precMin
|
|
||||||
Read-only integer. Return the minimum allowed precision. Must be at least 2.
|
|
||||||
|
|
||||||
@item precMax
|
|
||||||
Read-only integer. Return the maximum allowed precision. Must be at least 113.
|
|
||||||
|
|
||||||
@item expBitsMin
|
|
||||||
Read-only integer. Return the minimum allowed exponent size in
|
|
||||||
bits. Must be at least 3.
|
|
||||||
|
|
||||||
@item expBitsMax
|
|
||||||
Read-only integer. Return the maximum allowed exponent size in
|
|
||||||
bits. Must be at least 15.
|
|
||||||
|
|
||||||
@item RNDN
|
|
||||||
Read-only integer. Round to nearest, with ties to even rounding mode.
|
|
||||||
|
|
||||||
@item RNDZ
|
|
||||||
Read-only integer. Round to zero rounding mode.
|
|
||||||
|
|
||||||
@item RNDD
|
|
||||||
Read-only integer. Round to -Infinity rounding mode.
|
|
||||||
|
|
||||||
@item RNDU
|
|
||||||
Read-only integer. Round to +Infinity rounding mode.
|
|
||||||
|
|
||||||
@item RNDNA
|
|
||||||
Read-only integer. Round to nearest, with ties away from zero rounding mode.
|
|
||||||
|
|
||||||
@item RNDA
|
|
||||||
Read-only integer. Round away from zero rounding mode.
|
|
||||||
|
|
||||||
@item RNDF@footnote{Could be removed in case a deterministic behavior for floating point operations is required.}
|
|
||||||
Read-only integer. Faithful rounding mode. The result is
|
|
||||||
non-deterministically rounded to -Infinity or +Infinity. This rounding
|
|
||||||
mode usually gives a faster and deterministic running time for the
|
|
||||||
floating point operations.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@code{BigFloatEnv.prototype} properties:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item prec
|
|
||||||
Getter and setter (Integer). Return or set the precision in bits.
|
|
||||||
|
|
||||||
@item expBits
|
|
||||||
Getter and setter (Integer). Return or set the exponent size in bits
|
|
||||||
assuming an IEEE 754 representation.
|
|
||||||
|
|
||||||
@item rndMode
|
|
||||||
Getter and setter (Integer). Return or set the rounding mode.
|
|
||||||
|
|
||||||
@item subnormal
|
|
||||||
Getter and setter (Boolean). subnormal flag. It is false when
|
|
||||||
@code{expBits = expBitsMax}.
|
|
||||||
|
|
||||||
@item clearStatus()
|
|
||||||
Clear the status flags.
|
|
||||||
|
|
||||||
@item invalidOperation
|
|
||||||
@item divideByZero
|
|
||||||
@item overflow
|
|
||||||
@item underflow
|
|
||||||
@item inexact
|
|
||||||
Getter and setter (Boolean). Status flags.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@chapter BigDecimal
|
|
||||||
|
|
||||||
This extension adds the @code{BigDecimal} primitive type. The
|
|
||||||
@code{BigDecimal} type represents floating point numbers in base
|
|
||||||
10. It is inspired from the proposal available at
|
|
||||||
@url{https://github.com/littledan/proposal-bigdecimal}.
|
|
||||||
|
|
||||||
The @code{BigDecimal} floating point numbers are always normalized and
|
|
||||||
finite. There is no concept of @code{-0}, @code{Infinity} or
|
|
||||||
@code{NaN}. By default, all the computations are done with infinite
|
|
||||||
precision.
|
|
||||||
|
|
||||||
@section Operators
|
|
||||||
|
|
||||||
The following builtin operators support BigDecimal:
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item +
|
|
||||||
@item -
|
|
||||||
@item *
|
|
||||||
Both operands must be BigDecimal. The result is computed with infinite
|
|
||||||
precision.
|
|
||||||
@item %
|
|
||||||
Both operands must be BigDecimal. The result is computed with infinite
|
|
||||||
precision. A range error is throws in case of division by zero.
|
|
||||||
|
|
||||||
@item /
|
|
||||||
Both operands must be BigDecimal. A range error is throws in case of
|
|
||||||
division by zero or if the result cannot be represented with infinite
|
|
||||||
precision (use @code{BigDecimal.div} to specify the rounding).
|
|
||||||
|
|
||||||
@item **
|
|
||||||
Both operands must be BigDecimal. The exponent must be a positive
|
|
||||||
integer. The result is computed with infinite precision.
|
|
||||||
|
|
||||||
@item ===
|
|
||||||
When one of the operand is a BigDecimal, return true if both operands
|
|
||||||
are a BigDecimal and if they are equal.
|
|
||||||
|
|
||||||
@item ==
|
|
||||||
@item !=
|
|
||||||
@item <=
|
|
||||||
@item >=
|
|
||||||
@item <
|
|
||||||
@item >
|
|
||||||
|
|
||||||
Numerical comparison. When one of the operand is not a BigDecimal, it is
|
|
||||||
converted to BigDecimal by using ToString(). Hence comparisons between
|
|
||||||
Number and BigDecimal do not use the exact mathematical value of the
|
|
||||||
Number value.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@section BigDecimal literals
|
|
||||||
|
|
||||||
BigDecimal literals are decimal floating point numbers with a trailing
|
|
||||||
@code{m} suffix.
|
|
||||||
|
|
||||||
@section Builtin Object changes
|
|
||||||
|
|
||||||
@subsection The @code{BigDecimal} function.
|
|
||||||
|
|
||||||
It returns @code{0m} if no parameter is provided. Otherwise the first
|
|
||||||
parameter is converted to a bigdecimal by using ToString(). Hence
|
|
||||||
Number values are not converted to their exact numerical value as
|
|
||||||
BigDecimal.
|
|
||||||
|
|
||||||
@subsection Properties of the @code{BigDecimal} object
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
|
|
||||||
@item add(a, b[, e])
|
|
||||||
@item sub(a, b[, e])
|
|
||||||
@item mul(a, b[, e])
|
|
||||||
@item div(a, b[, e])
|
|
||||||
@item mod(a, b[, e])
|
|
||||||
@item sqrt(a, e)
|
|
||||||
@item round(a, e)
|
|
||||||
Perform the specified floating point operation and round the floating
|
|
||||||
point result according to the rounding object @code{e}. If the
|
|
||||||
rounding object is not present, the operation is executed with
|
|
||||||
infinite precision.
|
|
||||||
|
|
||||||
For @code{div}, a @code{RangeError} exception is thrown in case of
|
|
||||||
division by zero or if the result cannot be represented with infinite
|
|
||||||
precision if no rounding object is present.
|
|
||||||
|
|
||||||
For @code{sqrt}, a range error is thrown if @code{a} is less than
|
|
||||||
zero.
|
|
||||||
|
|
||||||
The rounding object must contain the following properties:
|
|
||||||
@code{roundingMode} is a string specifying the rounding mode
|
|
||||||
(@code{"floor"}, @code{"ceiling"}, @code{"down"}, @code{"up"},
|
|
||||||
@code{"half-even"}, @code{"half-up"}). Either
|
|
||||||
@code{maximumSignificantDigits} or @code{maximumFractionDigits} must
|
|
||||||
be present to specify respectively the number of significant digits
|
|
||||||
(must be >= 1) or the number of digits after the decimal point (must
|
|
||||||
be >= 0).
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@subsection Properties of the @code{BigDecimal.prototype} object
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item valueOf()
|
|
||||||
Return the bigdecimal primitive value corresponding to @code{this}.
|
|
||||||
|
|
||||||
@item toString()
|
|
||||||
Convert @code{this} to a string with infinite precision in base 10.
|
|
||||||
|
|
||||||
@item toPrecision(p, rnd_mode = "half-up")
|
|
||||||
@item toFixed(p, rnd_mode = "half-up")
|
|
||||||
@item toExponential(p, rnd_mode = "half-up")
|
|
||||||
Convert the BigDecimal @code{this} to string with the specified
|
|
||||||
precision @code{p}. There is no limit on the accepted precision
|
|
||||||
@code{p}. The rounding mode can be optionally
|
|
||||||
specified. @code{toPrecision} outputs either in decimal fixed notation
|
|
||||||
or in decimal exponential notation with a @code{p} digits of
|
|
||||||
precision. @code{toExponential} outputs in decimal exponential
|
|
||||||
notation with @code{p} digits after the decimal point. @code{toFixed}
|
|
||||||
outputs in decimal notation with @code{p} digits after the decimal
|
|
||||||
point.
|
|
||||||
|
|
||||||
@end table
|
|
||||||
|
|
||||||
@chapter Math mode
|
|
||||||
|
|
||||||
A new @emph{math mode} is enabled with the @code{"use math"}
|
|
||||||
directive. It propagates the same way as the @emph{strict mode}. It is
|
|
||||||
designed so that arbitrarily large integers and floating point numbers
|
|
||||||
are available by default. In order to minimize the number of changes
|
|
||||||
in the Javascript semantics, integers are represented either as Number
|
|
||||||
or BigInt depending on their magnitude. Floating point numbers are
|
|
||||||
always represented as BigFloat.
|
|
||||||
|
|
||||||
The following changes are made to the Javascript semantics:
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
|
|
||||||
@item Floating point literals (i.e. number with a decimal point or an exponent) are @code{BigFloat} by default (i.e. a @code{l} suffix is implied). Hence @code{typeof 1.0 === "bigfloat"}.
|
|
||||||
|
|
||||||
@item Integer literals (i.e. numbers without a decimal point or an exponent) with or without the @code{n} suffix are @code{BigInt} if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to @code{2**53-1}. Hence @code{typeof 1 === "number "}, @code{typeof 1n === "number"} but @code{typeof 9007199254740992 === "bigint" }.
|
|
||||||
|
|
||||||
@item All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt.
|
|
||||||
|
|
||||||
@item The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result.
|
|
||||||
|
|
||||||
@item The @code{^} operator is an alias to the power operator (@code{**}).
|
|
||||||
|
|
||||||
@item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}.
|
|
||||||
|
|
||||||
@item The logical xor operator is still available with the @code{^^} operator.
|
|
||||||
|
|
||||||
@item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
|
|
||||||
|
|
||||||
@item The integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
|
|
||||||
|
|
||||||
@item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
@bye
|
|
|
@ -24,10 +24,6 @@ ES2020 specification
|
||||||
@footnote{@url{https://tc39.es/ecma262/}}
|
@footnote{@url{https://tc39.es/ecma262/}}
|
||||||
including modules, asynchronous generators, proxies and BigInt.
|
including modules, asynchronous generators, proxies and BigInt.
|
||||||
|
|
||||||
It supports mathematical extensions such as big decimal float float
|
|
||||||
numbers (BigDecimal), big binary floating point numbers (BigFloat),
|
|
||||||
and operator overloading.
|
|
||||||
|
|
||||||
@section Main Features
|
@section Main Features
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
|
@ -47,8 +43,6 @@ features from the upcoming ES2021 specification
|
||||||
|
|
||||||
@item Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal.
|
@item Garbage collection using reference counting (to reduce memory usage and have deterministic behavior) with cycle removal.
|
||||||
|
|
||||||
@item Mathematical extensions: BigDecimal, BigFloat, operator overloading, bigint mode, math mode.
|
|
||||||
|
|
||||||
@item Command line interpreter with contextual colorization and completion implemented in Javascript.
|
@item Command line interpreter with contextual colorization and completion implemented in Javascript.
|
||||||
|
|
||||||
@item Small built-in standard library with C library wrappers.
|
@item Small built-in standard library with C library wrappers.
|
||||||
|
@ -118,10 +112,6 @@ source is @code{import}.
|
||||||
@item --script
|
@item --script
|
||||||
Load as ES6 script (default=autodetect).
|
Load as ES6 script (default=autodetect).
|
||||||
|
|
||||||
@item --bignum
|
|
||||||
Enable the bignum extensions: BigDecimal object, BigFloat object and
|
|
||||||
the @code{"use math"} directive.
|
|
||||||
|
|
||||||
@item -I file
|
@item -I file
|
||||||
@item --include file
|
@item --include file
|
||||||
Include an additional file.
|
Include an additional file.
|
||||||
|
@ -188,10 +178,6 @@ when the @code{-fno-x} options are used.
|
||||||
@item -fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint]
|
@item -fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint]
|
||||||
Disable selected language features to produce a smaller executable file.
|
Disable selected language features to produce a smaller executable file.
|
||||||
|
|
||||||
@item -fbignum
|
|
||||||
Enable the bignum extensions: BigDecimal object, BigFloat object and
|
|
||||||
the @code{"use math"} directive.
|
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@section @code{qjscalc} application
|
@section @code{qjscalc} application
|
||||||
|
@ -290,21 +276,6 @@ ECMA402 (Internationalization API) is not supported.
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
@subsection Mathematical extensions
|
|
||||||
|
|
||||||
The mathematical extensions are fully backward compatible with
|
|
||||||
standard Javascript. See @code{jsbignum.pdf} for more information.
|
|
||||||
|
|
||||||
@itemize
|
|
||||||
|
|
||||||
@item @code{BigDecimal} support: arbitrary large floating point numbers in base 10.
|
|
||||||
|
|
||||||
@item @code{BigFloat} support: arbitrary large floating point numbers in base 2.
|
|
||||||
|
|
||||||
@item Operator overloading.
|
|
||||||
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
@section Modules
|
@section Modules
|
||||||
|
|
||||||
ES6 modules are fully supported. The default name resolution is the
|
ES6 modules are fully supported. The default name resolution is the
|
||||||
|
@ -1074,9 +1045,9 @@ binary properties.
|
||||||
|
|
||||||
The full Unicode library weights about 45 KiB (x86 code).
|
The full Unicode library weights about 45 KiB (x86 code).
|
||||||
|
|
||||||
@section BigInt, BigFloat, BigDecimal
|
@section BigInt
|
||||||
|
|
||||||
BigInt, BigFloat and BigDecimal are implemented with the @code{libbf}
|
BigInt is implemented with the @code{libbf}
|
||||||
library@footnote{@url{https://bellard.org/libbf}}. It weights about 90
|
library@footnote{@url{https://bellard.org/libbf}}. It weights about 90
|
||||||
KiB (x86 code) and provides arbitrary precision IEEE 754 floating
|
KiB (x86 code) and provides arbitrary precision IEEE 754 floating
|
||||||
point operations and transcendental functions with exact rounding.
|
point operations and transcendental functions with exact rounding.
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* PI computation in Javascript using the QuickJS bigdecimal type
|
|
||||||
* (decimal floating point)
|
|
||||||
*/
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/* compute PI with a precision of 'prec' digits */
|
|
||||||
function calc_pi(prec) {
|
|
||||||
const CHUD_A = 13591409m;
|
|
||||||
const CHUD_B = 545140134m;
|
|
||||||
const CHUD_C = 640320m;
|
|
||||||
const CHUD_C3 = 10939058860032000m; /* C^3/24 */
|
|
||||||
const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(C/12)*3 */
|
|
||||||
|
|
||||||
/* return [P, Q, G] */
|
|
||||||
function chud_bs(a, b, need_G) {
|
|
||||||
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2, b1;
|
|
||||||
if (a == (b - 1n)) {
|
|
||||||
b1 = BigDecimal(b);
|
|
||||||
G = (2m * b1 - 1m) * (6m * b1 - 1m) * (6m * b1 - 5m);
|
|
||||||
P = G * (CHUD_B * b1 + CHUD_A);
|
|
||||||
if (b & 1n)
|
|
||||||
P = -P;
|
|
||||||
G = G;
|
|
||||||
Q = b1 * b1 * b1 * CHUD_C3;
|
|
||||||
} else {
|
|
||||||
c = (a + b) >> 1n;
|
|
||||||
[P1, Q1, G1] = chud_bs(a, c, true);
|
|
||||||
[P2, Q2, G2] = chud_bs(c, b, need_G);
|
|
||||||
P = P1 * Q2 + P2 * G1;
|
|
||||||
Q = Q1 * Q2;
|
|
||||||
if (need_G)
|
|
||||||
G = G1 * G2;
|
|
||||||
else
|
|
||||||
G = 0m;
|
|
||||||
}
|
|
||||||
return [P, Q, G];
|
|
||||||
}
|
|
||||||
|
|
||||||
var n, P, Q, G;
|
|
||||||
/* number of serie terms */
|
|
||||||
n = BigInt(Math.ceil(prec / CHUD_DIGITS_PER_TERM)) + 10n;
|
|
||||||
[P, Q, G] = chud_bs(0n, n, false);
|
|
||||||
Q = BigDecimal.div(Q, (P + Q * CHUD_A),
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumSignificantDigits: prec });
|
|
||||||
G = (CHUD_C / 12m) * BigDecimal.sqrt(CHUD_C,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumSignificantDigits: prec });
|
|
||||||
return Q * G;
|
|
||||||
}
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
var r, n_digits, n_bits;
|
|
||||||
if (typeof scriptArgs != "undefined") {
|
|
||||||
if (scriptArgs.length < 2) {
|
|
||||||
print("usage: pi n_digits");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
n_digits = scriptArgs[1] | 0;
|
|
||||||
} else {
|
|
||||||
n_digits = 1000;
|
|
||||||
}
|
|
||||||
/* we add more digits to reduce the probability of bad rounding for
|
|
||||||
the last digits */
|
|
||||||
r = calc_pi(n_digits + 20);
|
|
||||||
print(r.toFixed(n_digits, "down"));
|
|
||||||
})();
|
|
4
qjs.c
4
qjs.c
|
@ -110,7 +110,6 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
if (bignum_ext) {
|
if (bignum_ext) {
|
||||||
JS_AddIntrinsicBigFloat(ctx);
|
JS_AddIntrinsicBigFloat(ctx);
|
||||||
JS_AddIntrinsicBigDecimal(ctx);
|
|
||||||
JS_AddIntrinsicOperators(ctx);
|
JS_AddIntrinsicOperators(ctx);
|
||||||
JS_EnableBignumExt(ctx, TRUE);
|
JS_EnableBignumExt(ctx, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -289,9 +288,6 @@ void help(void)
|
||||||
" --script load as ES6 script (default=autodetect)\n"
|
" --script load as ES6 script (default=autodetect)\n"
|
||||||
"-I --include file include an additional file\n"
|
"-I --include file include an additional file\n"
|
||||||
" --std make 'std' and 'os' available to the loaded script\n"
|
" --std make 'std' and 'os' available to the loaded script\n"
|
||||||
#ifdef CONFIG_BIGNUM
|
|
||||||
" --bignum enable the bignum extensions (BigFloat, BigDecimal)\n"
|
|
||||||
#endif
|
|
||||||
"-T --trace trace memory allocation\n"
|
"-T --trace trace memory allocation\n"
|
||||||
"-d --dump dump the memory usage stats\n"
|
"-d --dump dump the memory usage stats\n"
|
||||||
" --memory-limit n limit the memory usage to 'n' bytes\n"
|
" --memory-limit n limit the memory usage to 'n' bytes\n"
|
||||||
|
|
2
qjsc.c
2
qjsc.c
|
@ -634,7 +634,6 @@ int main(int argc, char **argv)
|
||||||
#ifdef CONFIG_BIGNUM
|
#ifdef CONFIG_BIGNUM
|
||||||
if (bignum_ext) {
|
if (bignum_ext) {
|
||||||
JS_AddIntrinsicBigFloat(ctx);
|
JS_AddIntrinsicBigFloat(ctx);
|
||||||
JS_AddIntrinsicBigDecimal(ctx);
|
|
||||||
JS_AddIntrinsicOperators(ctx);
|
JS_AddIntrinsicOperators(ctx);
|
||||||
JS_EnableBignumExt(ctx, TRUE);
|
JS_EnableBignumExt(ctx, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -691,7 +690,6 @@ int main(int argc, char **argv)
|
||||||
if (bignum_ext) {
|
if (bignum_ext) {
|
||||||
fprintf(fo,
|
fprintf(fo,
|
||||||
" JS_AddIntrinsicBigFloat(ctx);\n"
|
" JS_AddIntrinsicBigFloat(ctx);\n"
|
||||||
" JS_AddIntrinsicBigDecimal(ctx);\n"
|
|
||||||
" JS_AddIntrinsicOperators(ctx);\n"
|
" JS_AddIntrinsicOperators(ctx);\n"
|
||||||
" JS_EnableBignumExt(ctx, 1);\n");
|
" JS_EnableBignumExt(ctx, 1);\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,6 @@ DEF(DataView, "DataView")
|
||||||
DEF(BigInt, "BigInt")
|
DEF(BigInt, "BigInt")
|
||||||
DEF(BigFloat, "BigFloat")
|
DEF(BigFloat, "BigFloat")
|
||||||
DEF(BigFloatEnv, "BigFloatEnv")
|
DEF(BigFloatEnv, "BigFloatEnv")
|
||||||
DEF(BigDecimal, "BigDecimal")
|
|
||||||
DEF(OperatorSet, "OperatorSet")
|
DEF(OperatorSet, "OperatorSet")
|
||||||
DEF(Operators, "Operators")
|
DEF(Operators, "Operators")
|
||||||
#endif
|
#endif
|
||||||
|
|
10
quickjs.h
10
quickjs.h
|
@ -66,8 +66,7 @@ typedef uint32_t JSAtom;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* all tags with a reference count are negative */
|
/* all tags with a reference count are negative */
|
||||||
JS_TAG_FIRST = -11, /* first negative tag */
|
JS_TAG_FIRST = -10, /* first negative tag */
|
||||||
JS_TAG_BIG_DECIMAL = -11,
|
|
||||||
JS_TAG_BIG_INT = -10,
|
JS_TAG_BIG_INT = -10,
|
||||||
JS_TAG_BIG_FLOAT = -9,
|
JS_TAG_BIG_FLOAT = -9,
|
||||||
JS_TAG_SYMBOL = -8,
|
JS_TAG_SYMBOL = -8,
|
||||||
|
@ -372,7 +371,6 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx);
|
||||||
void JS_AddIntrinsicPromise(JSContext *ctx);
|
void JS_AddIntrinsicPromise(JSContext *ctx);
|
||||||
void JS_AddIntrinsicBigInt(JSContext *ctx);
|
void JS_AddIntrinsicBigInt(JSContext *ctx);
|
||||||
void JS_AddIntrinsicBigFloat(JSContext *ctx);
|
void JS_AddIntrinsicBigFloat(JSContext *ctx);
|
||||||
void JS_AddIntrinsicBigDecimal(JSContext *ctx);
|
|
||||||
/* enable operator overloading */
|
/* enable operator overloading */
|
||||||
void JS_AddIntrinsicOperators(JSContext *ctx);
|
void JS_AddIntrinsicOperators(JSContext *ctx);
|
||||||
/* enable "use math" */
|
/* enable "use math" */
|
||||||
|
@ -561,12 +559,6 @@ static inline JS_BOOL JS_IsBigFloat(JSValueConst v)
|
||||||
return tag == JS_TAG_BIG_FLOAT;
|
return tag == JS_TAG_BIG_FLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline JS_BOOL JS_IsBigDecimal(JSValueConst v)
|
|
||||||
{
|
|
||||||
int tag = JS_VALUE_GET_TAG(v);
|
|
||||||
return tag == JS_TAG_BIG_DECIMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline JS_BOOL JS_IsBool(JSValueConst v)
|
static inline JS_BOOL JS_IsBool(JSValueConst v)
|
||||||
{
|
{
|
||||||
return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
|
return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
|
||||||
|
|
|
@ -235,92 +235,7 @@ function test_bigfloat()
|
||||||
assert((0x123.438l).toExponential(4, BigFloatEnv.RNDNA, 16), "1.2344p+8");
|
assert((0x123.438l).toExponential(4, BigFloatEnv.RNDNA, 16), "1.2344p+8");
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_bigdecimal()
|
|
||||||
{
|
|
||||||
assert(1m === 1m);
|
|
||||||
assert(1m !== 2m);
|
|
||||||
test_less(1m, 2m);
|
|
||||||
test_eq(2m, 2m);
|
|
||||||
|
|
||||||
test_less(1, 2m);
|
|
||||||
test_eq(2, 2m);
|
|
||||||
|
|
||||||
test_less(1.1, 2m);
|
|
||||||
test_eq(Math.sqrt(4), 2m);
|
|
||||||
|
|
||||||
test_less(2n, 3m);
|
|
||||||
test_eq(3n, 3m);
|
|
||||||
|
|
||||||
assert(BigDecimal("1234.1") === 1234.1m);
|
|
||||||
assert(BigDecimal(" 1234.1") === 1234.1m);
|
|
||||||
assert(BigDecimal(" 1234.1 ") === 1234.1m);
|
|
||||||
|
|
||||||
assert(BigDecimal(0.1) === 0.1m);
|
|
||||||
assert(BigDecimal(123) === 123m);
|
|
||||||
assert(BigDecimal(true) === 1m);
|
|
||||||
|
|
||||||
assert(123m + 1m === 124m);
|
|
||||||
assert(123m - 1m === 122m);
|
|
||||||
|
|
||||||
assert(3.2m * 3m === 9.6m);
|
|
||||||
assert(10m / 2m === 5m);
|
|
||||||
assertThrows(RangeError, () => { 10m / 3m } );
|
|
||||||
|
|
||||||
assert(10m % 3m === 1m);
|
|
||||||
assert(-10m % 3m === -1m);
|
|
||||||
|
|
||||||
assert(1234.5m ** 3m === 1881365963.625m);
|
|
||||||
assertThrows(RangeError, () => { 2m ** 3.1m } );
|
|
||||||
assertThrows(RangeError, () => { 2m ** -3m } );
|
|
||||||
|
|
||||||
assert(BigDecimal.sqrt(2m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumSignificantDigits: 4 }) === 1.414m);
|
|
||||||
assert(BigDecimal.sqrt(101m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 3 }) === 10.050m);
|
|
||||||
assert(BigDecimal.sqrt(0.002m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 3 }) === 0.045m);
|
|
||||||
|
|
||||||
assert(BigDecimal.round(3.14159m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 3 }) === 3.142m);
|
|
||||||
|
|
||||||
assert(BigDecimal.add(3.14159m, 0.31212m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 2 }) === 3.45m);
|
|
||||||
assert(BigDecimal.sub(3.14159m, 0.31212m,
|
|
||||||
{ roundingMode: "down",
|
|
||||||
maximumFractionDigits: 2 }) === 2.82m);
|
|
||||||
assert(BigDecimal.mul(3.14159m, 0.31212m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 3 }) === 0.981m);
|
|
||||||
assert(BigDecimal.mod(3.14159m, 0.31211m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 4 }) === 0.0205m);
|
|
||||||
assert(BigDecimal.div(20m, 3m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumSignificantDigits: 3 }) === 6.67m);
|
|
||||||
assert(BigDecimal.div(20m, 3m,
|
|
||||||
{ roundingMode: "half-even",
|
|
||||||
maximumFractionDigits: 50 }) ===
|
|
||||||
6.66666666666666666666666666666666666666666666666667m);
|
|
||||||
|
|
||||||
/* string conversion */
|
|
||||||
assert((1234.125m).toString(), "1234.125");
|
|
||||||
assert((1234.125m).toFixed(2), "1234.13");
|
|
||||||
assert((1234.125m).toFixed(2, "down"), "1234.12");
|
|
||||||
assert((1234.125m).toExponential(), "1.234125e+3");
|
|
||||||
assert((1234.125m).toExponential(5), "1.23413e+3");
|
|
||||||
assert((1234.125m).toExponential(5, "down"), "1.23412e+3");
|
|
||||||
assert((1234.125m).toPrecision(6), "1234.13");
|
|
||||||
assert((1234.125m).toPrecision(6, "down"), "1234.12");
|
|
||||||
assert((-1234.125m).toPrecision(6, "floor"), "-1234.13");
|
|
||||||
}
|
|
||||||
|
|
||||||
test_bigint1();
|
test_bigint1();
|
||||||
test_bigint2();
|
test_bigint2();
|
||||||
test_bigint_ext();
|
test_bigint_ext();
|
||||||
test_bigfloat();
|
test_bigfloat();
|
||||||
test_bigdecimal();
|
|
||||||
|
|
|
@ -163,12 +163,6 @@ function bjson_test_all()
|
||||||
BigFloat.MIN_VALUE]);
|
BigFloat.MIN_VALUE]);
|
||||||
}, 113, 15);
|
}, 113, 15);
|
||||||
}
|
}
|
||||||
if (typeof BigDecimal !== "undefined") {
|
|
||||||
bjson_test([BigDecimal("0"),
|
|
||||||
BigDecimal("0.8"), BigDecimal("123321312321321e100"),
|
|
||||||
BigDecimal("-1233213123213214332333223332e100"),
|
|
||||||
BigDecimal("1.233e-1000")]);
|
|
||||||
}
|
|
||||||
|
|
||||||
bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]);
|
bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue