quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

jsbignum.texi (20718B)


      1 \input texinfo
      2 
      3 @iftex
      4 @afourpaper
      5 @headings double
      6 @end iftex
      7 
      8 @titlepage
      9 @afourpaper
     10 @sp 7
     11 @center @titlefont{Javascript Bignum Extensions}
     12 @sp 3
     13 @center Version 2020-01-11
     14 @sp 3
     15 @center Author: Fabrice Bellard
     16 @end titlepage
     17 
     18 @setfilename jsbignum.info
     19 @settitle Javascript Bignum Extensions
     20 
     21 @contents
     22 
     23 @chapter Introduction
     24 
     25 The Bignum extensions add the following features to the Javascript
     26 language while being 100% backward compatible:
     27 
     28 @itemize
     29 
     30 @item Operator overloading with a dispatch logic inspired from the proposal available at @url{https://github.com/tc39/proposal-operator-overloading/}.
     31 
     32 @item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics.
     33 
     34 @item Arbitrarily large floating point numbers (@code{BigDecimal}) in base 10 based on the proposal available at
     35 @url{https://github.com/littledan/proposal-bigdecimal}.
     36 
     37 @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
     38 remainder. @code{^} is an alias to the power operator
     39 (@code{**}). @code{^^} is used as the exclusive or operator.
     40 
     41 @end itemize
     42 
     43 The extensions are independent from each other except the @code{math}
     44 mode which relies on BigFloat and operator overloading.
     45 
     46 @chapter Operator overloading
     47 
     48 Operator overloading is inspired from the proposal available at
     49 @url{https://github.com/tc39/proposal-operator-overloading/}. It
     50 implements the same dispatch logic but finds the operator sets by
     51 looking at the @code{Symbol.operatorSet} property in the objects. The
     52 changes were done in order to simplify the implementation.
     53 
     54 More precisely, the following modifications were made:
     55 
     56 @itemize
     57 
     58 @item @code{with operators from} is not supported. Operator overloading is always enabled.
     59 
     60 @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.
     61 
     62 @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.
     63 
     64 @item @code{[]} cannot be overloaded.
     65 
     66 @item In math mode, the BigInt division and power operators can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
     67 
     68 @end itemize
     69 
     70 @chapter BigInt extensions
     71 
     72 A few properties are added to the BigInt object:
     73 
     74 @table @code
     75 
     76 @item tdiv(a, b)
     77 Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError
     78 exception.
     79 
     80 @item fdiv(a, b)
     81 Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError
     82 exception.
     83 
     84 @item cdiv(a, b)
     85 Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError
     86 exception.
     87 
     88 @item ediv(a, b)
     89 Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian
     90 division). @code{b = 0} raises a RangeError exception.
     91 
     92 @item tdivrem(a, b)
     93 @item fdivrem(a, b)
     94 @item cdivrem(a, b)
     95 @item edivrem(a, b)
     96 Return an array of two elements. The first element is the quotient,
     97 the second is the remainder. The same rounding is done as the
     98 corresponding division operation.
     99 
    100 @item sqrt(a)
    101 Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is
    102 raised if @math{a < 0}.
    103 
    104 @item sqrtrem(a)
    105 Return an array of two elements. The first element is @math{\lfloor
    106 \sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a}
    107 \rfloor^2}. A RangeError exception is raised if @math{a < 0}.
    108 
    109 @item floorLog2(a)
    110 Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}.
    111 
    112 @item ctz(a)
    113 Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}.
    114 
    115 @end table
    116 
    117 @chapter BigFloat
    118 
    119 @section Introduction
    120 
    121 This extension adds the @code{BigFloat} primitive type. The
    122 @code{BigFloat} type represents floating point numbers in base 2
    123 with the IEEE 754 semantics. A floating
    124 point number is represented as a sign, mantissa and exponent. The
    125 special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0}
    126 are supported. The mantissa and exponent can have any bit length with
    127 an implementation specific minimum and maximum.
    128 
    129 @section Floating point rounding
    130 
    131 Each floating point operation operates with infinite precision and
    132 then rounds the result according to the specified floating point
    133 environment (@code{BigFloatEnv} object). The status flags of the
    134 environment are also set according to the result of the operation.
    135 
    136 If no floating point environment is provided, the global floating
    137 point environment is used.
    138 
    139 The rounding mode of the global floating point environment is always
    140 @code{RNDN} (``round to nearest with ties to even'')@footnote{The
    141 rationale is that the rounding mode changes must always be
    142 explicit.}. The status flags of the global environment cannot be
    143 read@footnote{The rationale is to avoid side effects for the built-in
    144 operators.}. The precision of the global environment is
    145 @code{BigFloatEnv.prec}. The number of exponent bits of the global
    146 environment is @code{BigFloatEnv.expBits}. The global environment
    147 subnormal flag is set to @code{true}.
    148 
    149 For example, @code{prec = 53} and @code{ expBits = 11} exactly give
    150 the same precision as the IEEE 754 64 bit floating point format. The
    151 default precision is @code{prec = 113} and @code{ expBits = 15} (IEEE
    152 754 128 bit floating point format).
    153 
    154 The global floating point environment can only be modified temporarily
    155 when calling a function (see @code{BigFloatEnv.setPrec}). Hence a
    156 function can change the global floating point environment for its
    157 callees but not for its caller.
    158 
    159 @section Operators
    160 
    161 The builtin operators are extended so that a BigFloat is returned if
    162 at least one operand is a BigFloat. The computations are always done
    163 with infinite precision and rounded according to the global floating
    164 point environment.
    165 
    166 @code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}.
    167 
    168 BigFloat can be compared with all the other numeric types and the
    169 result follows the expected mathematical relations.
    170 
    171 However, since BigFloat and Number are different types they are never
    172 equal when using the strict comparison operators (e.g. @code{0.0 ===
    173 0.0l} is false).
    174 
    175 @section BigFloat literals
    176 
    177 BigFloat literals are floating point numbers with a trailing @code{l}
    178 suffix. BigFloat literals have an infinite precision. They are rounded
    179 according to the global floating point environment when they are
    180 evaluated.@footnote{Base 10 floating point literals cannot usually be
    181 exactly represented as base 2 floating point number. In order to
    182 ensure that the literal is represented accurately with the current
    183 precision, it must be evaluated at runtime.}
    184 
    185 @section Builtin Object changes
    186 
    187 @subsection @code{BigFloat} function
    188 
    189 The @code{BigFloat} function cannot be invoked as a constructor. When
    190 invoked as a function: the parameter is converted to a primitive
    191 type. If the result is a numeric type, it is converted to BigFloat
    192 without rounding. If the result is a string, it is converted to
    193 BigFloat using the precision of the global floating point environment.
    194 
    195 @code{BigFloat} properties:
    196 
    197 @table @code
    198 
    199 @item LN2
    200 @item PI
    201 Getter. Return the value of the corresponding mathematical constant
    202 rounded to nearest, ties to even with the current global
    203 precision. The constant values are cached for small precisions.
    204 
    205 @item MIN_VALUE
    206 @item MAX_VALUE
    207 @item EPSILON
    208 Getter. Return the minimum, maximum and epsilon @code{BigFloat} values
    209 (same definition as the corresponding @code{Number} constants).
    210 
    211 @item fpRound(a[, e])
    212 Round the floating point number @code{a} according to the floating
    213 point environment @code{e} or the global environment if @code{e} is
    214 undefined.
    215 
    216 @item parseFloat(a[, radix[, e]])
    217 Parse the string @code{a} as a floating point number in radix
    218 @code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0
    219 means radix 10 unless there is a hexadecimal or binary prefix. The
    220 result is rounded according to the floating point environment @code{e}
    221 or the global environment if @code{e} is undefined.
    222 
    223 @item isFinite(a)
    224 Return true if @code{a} is a finite bigfloat.
    225 
    226 @item isNaN(a)
    227 Return true if @code{a} is a NaN bigfloat.
    228 
    229 @item add(a, b[, e])
    230 @item sub(a, b[, e])
    231 @item mul(a, b[, e])
    232 @item div(a, b[, e])
    233 Perform the specified floating point operation and round the floating
    234 point number @code{a} according to the floating point environment
    235 @code{e} or the global environment if @code{e} is undefined. If
    236 @code{e} is specified, the floating point status flags are updated.
    237 
    238 @item floor(x)
    239 @item ceil(x)
    240 @item round(x)
    241 @item trunc(x)
    242 Round to an integer. No additional rounding is performed.
    243 
    244 @item abs(x)
    245 Return the absolute value of x. No additional rounding is performed.
    246 
    247 @item fmod(x, y[, e])
    248 @item remainder(x, y[, e])
    249 Floating point remainder. The quotient is truncated to zero (fmod) or
    250 to the nearest integer with ties to even (remainder). @code{e} is an
    251 optional floating point environment.
    252 
    253 @item sqrt(x[, e])
    254 Square root. Return a rounded floating point number. @code{e} is an
    255 optional floating point environment.
    256 
    257 @item sin(x[, e])
    258 @item cos(x[, e])
    259 @item tan(x[, e])
    260 @item asin(x[, e])
    261 @item acos(x[, e])
    262 @item atan(x[, e])
    263 @item atan2(x, y[, e])
    264 @item exp(x[, e])
    265 @item log(x[, e])
    266 @item pow(x, y[, e])
    267 Transcendental operations. Return a rounded floating point
    268 number. @code{e} is an optional floating point environment.
    269 
    270 @end table
    271 
    272 @subsection @code{BigFloat.prototype}
    273 
    274 The following properties are modified:
    275 
    276 @table @code
    277 @item valueOf()
    278 Return the bigfloat primitive value corresponding to @code{this}.
    279 
    280 @item toString(radix)
    281 
    282 For floating point numbers:
    283 
    284 @itemize
    285 @item
    286 If the radix is a power of two, the conversion is done with infinite
    287 precision.
    288 @item
    289 Otherwise, the number is rounded to nearest with ties to even using
    290 the global precision. It is then converted to string using the minimum
    291 number of digits so that its conversion back to a floating point using
    292 the global precision and round to nearest gives the same number.
    293 
    294 @end itemize
    295 
    296 The exponent letter is @code{e} for base 10, @code{p} for bases 2, 8,
    297 16 with a binary exponent and @code{@@} for the other bases.
    298 
    299 @item toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
    300 @item toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
    301 @item toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
    302 Same semantics as the corresponding @code{Number} functions with
    303 BigFloats. There is no limit on the accepted precision @code{p}. The
    304 rounding mode and radix can be optionally specified. The radix must be
    305 between 2 and 36.
    306 
    307 @end table
    308 
    309 @subsection @code{BigFloatEnv} constructor
    310 
    311 The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a
    312 function. The floating point environment contains:
    313 
    314 @itemize
    315 @item the mantissa precision in bits
    316 
    317 @item the exponent size in bits assuming an IEEE 754 representation;
    318 
    319 @item the subnormal flag (if true, subnormal floating point numbers can
    320 be generated by the floating point operations).
    321 
    322 @item the rounding mode
    323 
    324 @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.
    325 
    326 @end itemize
    327 
    328 @code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point
    329 environment. The status flags are reset. If no parameter is given the
    330 precision, exponent bits and subnormal flags are copied from the
    331 global floating point environment. Otherwise, the precision is set to
    332 @code{p}, the number of exponent bits is set to @code{expBitsMax} and the
    333 subnormal flags is set to @code{false}. If @code{rndMode} is
    334 @code{undefined}, the rounding mode is set to @code{RNDN}.
    335 
    336 @code{BigFloatEnv} properties:
    337 
    338 @table @code
    339 
    340 @item prec
    341 Getter. Return the precision in bits of the global floating point
    342 environment. The initial value is @code{113}.
    343 
    344 @item expBits
    345 Getter. Return the exponent size in bits of the global floating point
    346 environment assuming an IEEE 754 representation. The initial value is
    347 @code{15}.
    348 
    349 @item setPrec(f, p[, e])
    350 Set the precision of the global floating point environment to @code{p}
    351 and the exponent size to @code{e} then call the function
    352 @code{f}. Then the Float precision and exponent size are reset to
    353 their precious value and the return value of @code{f} is returned (or
    354 an exception is raised if @code{f} raised an exception). If @code{e}
    355 is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}.
    356 
    357 @item precMin
    358 Read-only integer. Return the minimum allowed precision. Must be at least 2.
    359 
    360 @item precMax
    361 Read-only integer. Return the maximum allowed precision. Must be at least 113.
    362 
    363 @item expBitsMin
    364 Read-only integer. Return the minimum allowed exponent size in
    365 bits. Must be at least 3.
    366 
    367 @item expBitsMax
    368 Read-only integer. Return the maximum allowed exponent size in
    369 bits. Must be at least 15.
    370 
    371 @item RNDN
    372 Read-only integer. Round to nearest, with ties to even rounding mode.
    373 
    374 @item RNDZ
    375 Read-only integer. Round to zero rounding mode.
    376 
    377 @item RNDD
    378 Read-only integer. Round to -Infinity rounding mode.
    379 
    380 @item RNDU
    381 Read-only integer. Round to +Infinity rounding mode.
    382 
    383 @item RNDNA
    384 Read-only integer. Round to nearest, with ties away from zero rounding mode.
    385 
    386 @item RNDA
    387 Read-only integer. Round away from zero rounding mode.
    388 
    389 @item RNDF@footnote{Could be removed in case a deterministic behavior for floating point operations is required.}
    390 Read-only integer. Faithful rounding mode. The result is
    391 non-deterministically rounded to -Infinity or +Infinity. This rounding
    392 mode usually gives a faster and deterministic running time for the
    393 floating point operations.
    394 
    395 @end table
    396 
    397 @code{BigFloatEnv.prototype} properties:
    398 
    399 @table @code
    400 
    401 @item prec
    402 Getter and setter (Integer). Return or set the precision in bits.
    403 
    404 @item expBits
    405 Getter and setter (Integer). Return or set the exponent size in bits
    406 assuming an IEEE 754 representation.
    407 
    408 @item rndMode
    409 Getter and setter (Integer). Return or set the rounding mode.
    410 
    411 @item subnormal
    412 Getter and setter (Boolean). subnormal flag. It is false when
    413 @code{expBits = expBitsMax}.
    414 
    415 @item clearStatus()
    416 Clear the status flags.
    417 
    418 @item invalidOperation
    419 @item divideByZero
    420 @item overflow
    421 @item underflow
    422 @item inexact
    423 Getter and setter (Boolean). Status flags.
    424 
    425 @end table
    426 
    427 @chapter BigDecimal
    428 
    429 This extension adds the @code{BigDecimal} primitive type. The
    430 @code{BigDecimal} type represents floating point numbers in base
    431 10. It is inspired from the proposal available at
    432 @url{https://github.com/littledan/proposal-bigdecimal}.
    433 
    434 The @code{BigDecimal} floating point numbers are always normalized and
    435 finite. There is no concept of @code{-0}, @code{Infinity} or
    436 @code{NaN}. By default, all the computations are done with infinite
    437 precision.
    438 
    439 @section Operators
    440 
    441 The following builtin operators support BigDecimal:
    442 
    443 @table @code
    444 
    445 @item +
    446 @item -
    447 @item *
    448 Both operands must be BigDecimal. The result is computed with infinite
    449 precision.
    450 @item %
    451 Both operands must be BigDecimal. The result is computed with infinite
    452 precision. A range error is throws in case of division by zero.
    453 
    454 @item /
    455 Both operands must be BigDecimal. A range error is throws in case of
    456 division by zero or if the result cannot be represented with infinite
    457 precision (use @code{BigDecimal.div} to specify the rounding).
    458 
    459 @item **
    460 Both operands must be BigDecimal. The exponent must be a positive
    461 integer. The result is computed with infinite precision.
    462 
    463 @item ===
    464 When one of the operand is a BigDecimal, return true if both operands
    465 are a BigDecimal and if they are equal.
    466 
    467 @item ==
    468 @item !=
    469 @item <=
    470 @item >=
    471 @item <
    472 @item >
    473 
    474 Numerical comparison. When one of the operand is not a BigDecimal, it is
    475 converted to BigDecimal by using ToString(). Hence comparisons between
    476 Number and BigDecimal do not use the exact mathematical value of the
    477 Number value.
    478 
    479 @end table
    480 
    481 @section BigDecimal literals
    482 
    483 BigDecimal literals are decimal floating point numbers with a trailing
    484 @code{m} suffix.
    485 
    486 @section Builtin Object changes
    487 
    488 @subsection The @code{BigDecimal} function.
    489 
    490 It returns @code{0m} if no parameter is provided. Otherwise the first
    491 parameter is converted to a bigdecimal by using ToString(). Hence
    492 Number values are not converted to their exact numerical value as
    493 BigDecimal.
    494 
    495 @subsection Properties of the @code{BigDecimal} object
    496 
    497 @table @code
    498 
    499 @item add(a, b[, e])
    500 @item sub(a, b[, e])
    501 @item mul(a, b[, e])
    502 @item div(a, b[, e])
    503 @item mod(a, b[, e])
    504 @item sqrt(a, e)
    505 @item round(a, e)
    506 Perform the specified floating point operation and round the floating
    507 point result according to the rounding object @code{e}. If the
    508 rounding object is not present, the operation is executed with
    509 infinite precision.
    510 
    511 For @code{div}, a @code{RangeError} exception is thrown in case of
    512 division by zero or if the result cannot be represented with infinite
    513 precision if no rounding object is present.
    514 
    515 For @code{sqrt}, a range error is thrown if @code{a} is less than
    516 zero.
    517 
    518 The rounding object must contain the following properties:
    519 @code{roundingMode} is a string specifying the rounding mode
    520 (@code{"floor"}, @code{"ceiling"}, @code{"down"}, @code{"up"},
    521 @code{"half-even"}, @code{"half-up"}). Either
    522 @code{maximumSignificantDigits} or @code{maximumFractionDigits} must
    523 be present to specify respectively the number of significant digits
    524 (must be >= 1) or the number of digits after the decimal point (must
    525 be >= 0).
    526 
    527 @end table
    528 
    529 @subsection Properties of the @code{BigDecimal.prototype} object
    530 
    531 @table @code
    532 @item valueOf()
    533 Return the bigdecimal primitive value corresponding to @code{this}.
    534 
    535 @item toString()
    536 Convert @code{this} to a string with infinite precision in base 10.
    537 
    538 @item toPrecision(p, rnd_mode = "half-up")
    539 @item toFixed(p, rnd_mode = "half-up")
    540 @item toExponential(p, rnd_mode = "half-up")
    541 Convert the BigDecimal @code{this} to string with the specified
    542 precision @code{p}. There is no limit on the accepted precision
    543 @code{p}. The rounding mode can be optionally
    544 specified. @code{toPrecision} outputs either in decimal fixed notation
    545 or in decimal exponential notation with a @code{p} digits of
    546 precision.  @code{toExponential} outputs in decimal exponential
    547 notation with @code{p} digits after the decimal point. @code{toFixed}
    548 outputs in decimal notation with @code{p} digits after the decimal
    549 point.
    550 
    551 @end table
    552 
    553 @chapter Math mode
    554 
    555 A new @emph{math mode} is enabled with the @code{"use math"}
    556 directive. It propagates the same way as the @emph{strict mode}. It is
    557 designed so that arbitrarily large integers and floating point numbers
    558 are available by default. In order to minimize the number of changes
    559 in the Javascript semantics, integers are represented either as Number
    560 or BigInt depending on their magnitude. Floating point numbers are
    561 always represented as BigFloat.
    562 
    563 The following changes are made to the Javascript semantics:
    564 
    565 @itemize
    566 
    567 @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"}.
    568 
    569 @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" }.
    570 
    571 @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.
    572 
    573 @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.
    574 
    575 @item The @code{^} operator is an alias to the power operator (@code{**}).
    576 
    577 @item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}.
    578 
    579 @item The logical xor operator is still available with the @code{^^} operator.
    580 
    581 @item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
    582 
    583 @item The integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
    584 
    585 @item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
    586 
    587 @end itemize
    588 
    589 @bye