diff --git a/Makefile b/Makefile index e51fb22..9c983db 100644 --- a/Makefile +++ b/Makefile @@ -404,7 +404,7 @@ examples/point.so: $(OBJDIR)/examples/point.pic.o ############################################################################### # documentation -DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html +DOCS=doc/quickjs.pdf doc/quickjs.html build_doc: $(DOCS) diff --git a/doc/jsbignum.texi b/doc/jsbignum.texi deleted file mode 100644 index 95fee54..0000000 --- a/doc/jsbignum.texi +++ /dev/null @@ -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 diff --git a/doc/quickjs.texi b/doc/quickjs.texi index 34ddf35..83294e8 100644 --- a/doc/quickjs.texi +++ b/doc/quickjs.texi @@ -24,10 +24,6 @@ ES2023 specification @footnote{@url{https://tc39.es/ecma262/2023 }} 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 @itemize @@ -47,8 +43,6 @@ features from the upcoming ES2024 specification @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 Small built-in standard library with C library wrappers. @@ -123,10 +117,6 @@ source is @code{import}. @item --script 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 --include file Include an additional file. @@ -193,21 +183,8 @@ when the @code{-fno-x} options are used. @item -fno-[eval|string-normalize|regexp|json|proxy|map|typedarray|promise|bigint] 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 -@section @code{qjscalc} application - -The @code{qjscalc} application is a superset of the @code{qjs} -command line interpreter implementing a Javascript calculator with -arbitrarily large integer and floating point numbers, fractions, -complex numbers, polynomials and matrices. The source code is in -@file{qjscalc.js}. More documentation and a web version are available at -@url{http://numcalc.com}. - @section Built-in tests Run @code{make test} to run the few built-in tests included in the @@ -301,25 +278,6 @@ ECMA402 (Internationalization API) is not supported. @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. - -@item The directive @code{"use bigint"} enables the bigint mode where integers are @code{BigInt} by default. - -@item The directive @code{"use math"} enables the math mode where the division and power operators on integers produce fractions. Floating point literals are @code{BigFloat} by default and integers are @code{BigInt} by default. - -@end itemize - @section Modules ES6 modules are fully supported. The default name resolution is the @@ -1105,12 +1063,11 @@ binary properties. 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} -library@footnote{@url{https://bellard.org/libbf}}. It weights about 90 -KiB (x86 code) and provides arbitrary precision IEEE 754 floating -point operations and transcendental functions with exact rounding. +BigInts are represented using binary two's complement notation. An +additional short bigint value is used to optimize the performance on +small BigInt values. @chapter License diff --git a/fuzz/fuzz.dict b/fuzz/fuzz.dict index a5010e4..f31eb9f 100644 --- a/fuzz/fuzz.dict +++ b/fuzz/fuzz.dict @@ -14,9 +14,6 @@ "atan2" "atanh" "Atomics" -"BigDecimal" -"BigFloat" -"BigFloatEnv" "BigInt" "BigInt64Array" "BigUint64Array" diff --git a/fuzz/fuzz_common.c b/fuzz/fuzz_common.c index 9f1662d..92548d2 100644 --- a/fuzz/fuzz_common.c +++ b/fuzz/fuzz_common.c @@ -34,10 +34,6 @@ void test_one_input_init(JSRuntime *rt, JSContext *ctx) { // 64 Kb JS_SetMaxStackSize(rt, 0x10000); - JS_AddIntrinsicBigFloat(ctx); - JS_AddIntrinsicBigDecimal(ctx); - JS_AddIntrinsicOperators(ctx); - JS_EnableBignumExt(ctx, 1); JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL); js_std_add_helpers(ctx, 0, NULL); diff --git a/quickjs.c b/quickjs.c index 76dfcb5..f4446d3 100644 --- a/quickjs.c +++ b/quickjs.c @@ -286,8 +286,7 @@ struct JSClass { #define JS_MODE_STRICT (1 << 0) #define JS_MODE_STRIP (1 << 1) -#define JS_MODE_MATH (1 << 2) -#define JS_MODE_ASYNC (1 << 3) /* async function */ +#define JS_MODE_ASYNC (1 << 2) /* async function */ typedef struct JSStackFrame { struct JSStackFrame *prev_frame; /* NULL if first stack frame */ @@ -298,7 +297,7 @@ typedef struct JSStackFrame { const uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ int arg_count; - int js_mode; /* for C functions, only JS_MODE_MATH may be set */ + int js_mode; /* not supported for C functions */ /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp; @@ -17723,8 +17722,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, op2 = sp[-1]; if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int v1, v2; - if (unlikely(sf->js_mode & JS_MODE_MATH)) - goto binary_arith_slow; v1 = JS_VALUE_GET_INT(op1); v2 = JS_VALUE_GET_INT(op2); sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2); @@ -36465,7 +36462,6 @@ static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val, { double d; - /* XXX: does this work for bigfloat? */ if (unlikely(JS_ToFloat64(ctx, &d, argv[0]))) return JS_EXCEPTION; return JS_NewBool(ctx, isnan(d)); @@ -44666,7 +44662,6 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, /* check for object.toJSON method */ /* ECMA specifies this is done only for Object and BigInt */ - /* we do it for BigFloat and BigDecimal as an extension */ if (JS_IsObject(val) || JS_IsBigInt(ctx, val)) { JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON); if (JS_IsException(f)) diff --git a/quickjs.h b/quickjs.h index e908885..c59446d 100644 --- a/quickjs.h +++ b/quickjs.h @@ -74,10 +74,8 @@ typedef uint32_t JSAtom; enum { /* all tags with a reference count are negative */ - JS_TAG_FIRST = -11, /* first negative tag */ - JS_TAG_BIG_DECIMAL = -11, - JS_TAG_BIG_INT = -10, - JS_TAG_BIG_FLOAT = -9, + JS_TAG_FIRST = -9, /* first negative tag */ + JS_TAG_BIG_INT = -9, JS_TAG_SYMBOL = -8, JS_TAG_STRING = -7, JS_TAG_MODULE = -3, /* used internally */ @@ -409,12 +407,6 @@ void JS_AddIntrinsicMapSet(JSContext *ctx); void JS_AddIntrinsicTypedArrays(JSContext *ctx); void JS_AddIntrinsicPromise(JSContext *ctx); void JS_AddIntrinsicBigInt(JSContext *ctx); -void JS_AddIntrinsicBigFloat(JSContext *ctx); -void JS_AddIntrinsicBigDecimal(JSContext *ctx); -/* enable operator overloading */ -void JS_AddIntrinsicOperators(JSContext *ctx); -/* enable "use math" */ -void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable); JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); @@ -614,18 +606,6 @@ static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v) return tag == JS_TAG_BIG_INT || tag == JS_TAG_SHORT_BIG_INT; } -static inline JS_BOOL JS_IsBigFloat(JSValueConst v) -{ - int tag = JS_VALUE_GET_TAG(v); - 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) { return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; diff --git a/repl.js b/repl.js index cb92d3b..e6e720b 100644 --- a/repl.js +++ b/repl.js @@ -41,11 +41,6 @@ import * as os from "os"; var isFinite = g.isFinite; var parseFloat = g.parseFloat; - /* XXX: use preprocessor ? */ - var config_numcalc = (typeof os.open === "undefined"); - var has_jscalc = (typeof Fraction === "function"); - var has_bignum = (typeof BigFloat === "function"); - var colors = { none: "\x1b[0m", black: "\x1b[30m", @@ -913,48 +908,6 @@ import * as os from "os"; } } - function bigfloat_to_string(a, radix) { - var s; - if (!BigFloat.isFinite(a)) { - /* NaN, Infinite */ - if (eval_mode !== "math") { - return "BigFloat(" + a.toString() + ")"; - } else { - return a.toString(); - } - } else { - if (a == 0) { - if (1 / a < 0) - s = "-0"; - else - s = "0"; - } else { - if (radix == 16) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); - } else { - s = a.toString(); - } - } - if (typeof a === "bigfloat" && eval_mode !== "math") { - s += "l"; - } else if (eval_mode !== "std" && s.indexOf(".") < 0 && - ((radix == 16 && s.indexOf("p") < 0) || - (radix == 10 && s.indexOf("e") < 0))) { - /* add a decimal point so that the floating point type - is visible */ - s += ".0"; - } - return s; - } - } - function bigint_to_string(a, radix) { var s; if (radix == 16) { @@ -988,14 +941,6 @@ import * as os from "os"; std.puts("[circular]"); } else if (a instanceof Date) { std.puts("Date " + a.toGMTString().__quote()); - } else if (has_jscalc && (a instanceof Fraction || - a instanceof Complex || - a instanceof Mod || - a instanceof Polynomial || - a instanceof PolyMod || - a instanceof RationalFunction || - a instanceof Series)) { - std.puts(a.toString()); } else { stack.push(a); if (Array.isArray(a)) { @@ -1041,10 +986,6 @@ import * as os from "os"; std.puts(number_to_string(a, hex_mode ? 16 : 10)); } else if (type === "bigint") { std.puts(bigint_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigfloat") { - std.puts(bigfloat_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigdecimal") { - std.puts(a.toString() + "m"); } else if (type === "symbol") { std.puts(String(a)); } else if (type === "function") { @@ -1085,75 +1026,10 @@ import * as os from "os"; hex_mode = false; } else if (cmd === "t") { show_time = !show_time; - } else if (has_bignum && cmd === "p") { - param = expr.substring(cmd.length + 1).trim().split(" "); - if (param.length === 1 && param[0] === "") { - std.puts("BigFloat precision=" + prec + " bits (~" + - Math.floor(prec / log2_10) + - " digits), exponent size=" + expBits + " bits\n"); - } else if (param[0] === "f16") { - prec = 11; - expBits = 5; - } else if (param[0] === "f32") { - prec = 24; - expBits = 8; - } else if (param[0] === "f64") { - prec = 53; - expBits = 11; - } else if (param[0] === "f128") { - prec = 113; - expBits = 15; - } else { - prec1 = parseInt(param[0]); - if (param.length >= 2) - expBits1 = parseInt(param[1]); - else - expBits1 = BigFloatEnv.expBitsMax; - if (Number.isNaN(prec1) || - prec1 < BigFloatEnv.precMin || - prec1 > BigFloatEnv.precMax) { - std.puts("Invalid precision\n"); - return false; - } - if (Number.isNaN(expBits1) || - expBits1 < BigFloatEnv.expBitsMin || - expBits1 > BigFloatEnv.expBitsMax) { - std.puts("Invalid exponent bits\n"); - return false; - } - prec = prec1; - expBits = expBits1; - } - return false; - } else if (has_bignum && cmd === "digits") { - param = expr.substring(cmd.length + 1).trim(); - prec1 = Math.ceil(parseFloat(param) * log2_10); - if (prec1 < BigFloatEnv.precMin || - prec1 > BigFloatEnv.precMax) { - std.puts("Invalid precision\n"); - return false; - } - prec = prec1; - expBits = BigFloatEnv.expBitsMax; - return false; - } else if (has_bignum && cmd === "mode") { - param = expr.substring(cmd.length + 1).trim(); - if (param === "") { - std.puts("Running mode=" + eval_mode + "\n"); - } else if (param === "std" || param === "math") { - eval_mode = param; - } else { - std.puts("Invalid mode\n"); - } - return false; } else if (cmd === "clear") { std.puts("\x1b[H\x1b[J"); } else if (cmd === "q") { std.exit(0); - } else if (has_jscalc && cmd === "a") { - algebraicMode = true; - } else if (has_jscalc && cmd === "n") { - algebraicMode = false; } else { std.puts("Unknown directive: " + cmd + "\n"); return false; @@ -1161,43 +1037,6 @@ import * as os from "os"; return true; } - if (config_numcalc) { - styles = { - 'default': 'black', - 'comment': 'white', - 'string': 'green', - 'regex': 'cyan', - 'number': 'green', - 'keyword': 'blue', - 'function': 'gray', - 'type': 'bright_magenta', - 'identifier': 'yellow', - 'error': 'bright_red', - 'result': 'black', - 'error_msg': 'bright_red', - }; - - ps1 = "> "; - - /* called by the GUI */ - g.execCmd = function (cmd) { - switch(cmd) { - case "dec": - hex_mode = false; - break; - case "hex": - hex_mode = true; - break; - case "num": - algebraicMode = false; - break; - case "alg": - algebraicMode = true; - break; - } - } - } - function help() { function sel(n) { return n ? "*": " "; @@ -1206,40 +1045,12 @@ import * as os from "os"; "\\x " + sel(hex_mode) + "hexadecimal number display\n" + "\\d " + sel(!hex_mode) + "decimal number display\n" + "\\t " + sel(show_time) + "toggle timing display\n" + - "\\clear clear the terminal\n"); - if (has_jscalc) { - std.puts("\\a " + sel(algebraicMode) + "algebraic mode\n" + - "\\n " + sel(!algebraicMode) + "numeric mode\n"); - } - if (has_bignum) { - std.puts("\\p [m [e]] set the BigFloat precision to 'm' bits\n" + - "\\digits n set the BigFloat precision to 'ceil(n*log2(10))' bits\n"); - if (!has_jscalc) { - std.puts("\\mode [std|math] change the running mode (current = " + eval_mode + ")\n"); - } - } - if (!config_numcalc) { - std.puts("\\q exit\n"); - } + "\\clear clear the terminal\n" + + "\\q exit\n"); } function cmd_start() { - if (!config_numcalc) { - if (has_jscalc) - std.puts('QJSCalc - Type "\\h" for help\n'); - else - std.puts('QuickJS - Type "\\h" for help\n'); - } - if (has_bignum) { - log2_10 = Math.log(10) / Math.log(2); - prec = 113; - expBits = 15; - if (has_jscalc) { - eval_mode = "math"; - /* XXX: numeric mode should always be the default ? */ - g.algebraicMode = config_numcalc; - } - } + std.puts('QuickJS - Type "\\h" for help\n'); cmd_readline_start(); } @@ -1287,13 +1098,8 @@ import * as os from "os"; } mexpr = ""; - if (has_bignum) { - /* XXX: async is not supported in this case */ - BigFloatEnv.setPrec(eval_and_print_start.bind(null, expr, false), - prec, expBits); - } else { - eval_and_print_start(expr, true); - } + eval_and_print_start(expr, true); + return true; } @@ -1301,8 +1107,6 @@ import * as os from "os"; var result; try { - if (eval_mode === "math") - expr = '"use math"; void 0;' + expr; eval_start_time = os.now(); /* eval as a script */ result = std.evalScript(expr, { backtrace_barrier: true, async: is_async }); diff --git a/tests/test_bjson.js b/tests/test_bjson.js index f15ef91..a270796 100644 --- a/tests/test_bjson.js +++ b/tests/test_bjson.js @@ -87,7 +87,6 @@ function toStr(a) case "string": return a.__quote(); case "number": - case "bigfloat": if (a == 0 && 1 / a < 0) return "-0"; else @@ -155,21 +154,6 @@ function bjson_test_all() bjson_test([BigInt("1"), -BigInt("0x123456789"), BigInt("0x123456789abcdef123456789abcdef")]); } - if (typeof BigFloat !== "undefined") { - BigFloatEnv.setPrec(function () { - bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"), - BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"), - 0.0 / BigFloat("0"), BigFloat.MAX_VALUE, - BigFloat.MIN_VALUE]); - }, 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 Int32Array([123123, 222111, -32222]));