Merge branch 'master' of https://github.com/jart/cosmopolitan into FEATURE/ioctl_SIOCGIFCONF

This commit is contained in:
Fabrizio Bertocci 2021-04-11 22:07:39 -04:00
commit b59a3eb470
141 changed files with 99998 additions and 223 deletions

62
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,62 @@
# Contributing Guidelines
We'd love to accept your patches! Please read this guide first.
## Copyright Assignment
Please send an email to Justine Tunney <jtunney@gmail.com> stating that
you intend to assign her the copyright to the changes you contribute to
Cosmopolitan. Please use the same email address you use for git commits
which should only contain original source code from you or other people
who are also assigning copyright. Please note that, if you're employed,
you may need to get your employer's approval beforehand. If you can not
assign copyright due to local laws, then you may alternatively consider
disclaiming it using the language in [Unlicense](https://unlicense.org)
or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0)
This is important because we can't produce 12kb single-file executables
that comply with license requirements if we have to embed lots of them.
Although that's less of an issue depending on the purpose of the files.
For example, ownership is much less of a concern in the unit test files
so you're encouraged to put your copyright on those, provided it's ISC.
## Style Guide
You can use clang-format to automatically format your files:
```sh
clang-format -i -style=file tool/net/redbean.c
```
If you use Emacs this can be automated on save for Cosmopolitan using
[tool/emacs/cosmo-format.el]([tool/emacs/cosmo-format.el]).
### Source Files
- Must use include paths relative to the root of the repository
- Must have comment at top of file documenting copyright and license
- Must have notice embedding if not owned by Justine (exception: tests)
- May use language extensions that are supported by both GCC and Clang
- Should use Google indentation (otherwise use `/* clang-format off */`)
- Should use asm() instead of compiler APIs (exception: ctz, clz, memcpy)
### Header Files
- Must not have copyright or license comments
- Must have once guards (otherwise change `.h` to `.inc`)
- Must be ANSI C89 compatible to be included in the amalgamation header
- Must include its dependencies (exception: libc/integral/normalize.inc)
- Must not define objects (i.e. `cc -c -xc foo.h` will produce empty `.o`)
- Should not use typedefs
- Should not use forward declarations
- Should not include documentation comments
- Should not include parameter names in prototypes
- Should not pose problems if included by C++ or Assembly sources
- Should not declare non-ANSI code, at all, when the user requests ANSI
### Build Config
- Must not write files outside `o/`
- Must not communicate with Internet
- Must not depend on system libraries
- Must not depend on system commands (exception: sh, make, gzip, zip)

View file

@ -136,6 +136,7 @@ include third_party/third_party.mk
include libc/testlib/testlib.mk
include tool/viz/lib/vizlib.mk
include third_party/lua/lua.mk
include third_party/quickjs/quickjs.mk
include examples/examples.mk
include third_party/lz4cli/lz4cli.mk
include tool/build/lib/buildlib.mk

Binary file not shown.

View file

@ -69,6 +69,9 @@ CONFIG_CCFLAGS += \
$(BACKTRACES) \
-O2
TARGET_ARCH ?= \
-msse3
endif
# Debug Mode
@ -88,7 +91,7 @@ CONFIG_CPPFLAGS += \
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-O2
-Og
CONFIG_COPTS += \
$(SECURITY_BLANKETS) \

52
examples/walk.c Normal file
View file

@ -0,0 +1,52 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/musl/ftw.h"
/**
* @fileoverview Directory walker example.
* Copied from IEEE Std 1003.1-2017
*/
static int display_info(const char *fpath, const struct stat *sb, int tflag,
struct FTW *ftwbuf) {
printf("%-3s %2d %7jd %-40s %d %s\n",
(tflag == FTW_D) ? "d"
: (tflag == FTW_DNR) ? "dnr"
: (tflag == FTW_DP) ? "dp"
: (tflag == FTW_F) ? (S_ISBLK(sb->st_mode) ? "f b"
: S_ISCHR(sb->st_mode) ? "f c"
: S_ISFIFO(sb->st_mode) ? "f p"
: S_ISREG(sb->st_mode) ? "f r"
: S_ISSOCK(sb->st_mode) ? "f s"
: "f ?")
: (tflag == FTW_NS) ? "ns"
: (tflag == FTW_SL) ? "sl"
: (tflag == FTW_SLN) ? "sln"
: "?",
ftwbuf->level, (intmax_t)sb->st_size, fpath, ftwbuf->base,
fpath + ftwbuf->base);
return 0; /* To tell nftw() to continue */
}
int main(int argc, char *argv[]) {
int flags = 0;
if (argc > 2 && strchr(argv[2], 'd') != NULL) flags |= FTW_DEPTH;
if (argc > 2 && strchr(argv[2], 'p') != NULL) flags |= FTW_PHYS;
if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1) {
perror("nftw");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}

23
libc/runtime/dlfcn.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_DLFCN_H_
#define COSMOPOLITAN_LIBC_RUNTIME_DLFCN_H_
#define RTLD_LOCAL 0
#define RTLD_LAZY 1
#define RTLD_NOW 2
#define RTLD_GLOBAL 256
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define RTLD_NEXT ((void *)-1)
#define RTLD_DEFAULT ((void *)0)
char *dlerror(void);
void *dlopen(const char *, int);
void *dlsym(void *, const char *);
int dlclose(void *);
int dl_iterate_phdr(int (*)(void *, size_t, void *), void *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_DLFCN_H_ */

32
libc/runtime/fegetround.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/fenv.h"
/**
* Returns rounding mode.
*
* This implementation retrieves it from the x87 FPU control word.
*
* @see fesetround() for changing this
*/
int fegetround(void) {
uint16_t x87cw;
asm("fnstcw\t%0" : "=m"(x87cw));
return x87cw & 0x0c00;
}

41
libc/runtime/fenv.c Normal file
View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/fenv.h"
/* TODO: implement these functions */
int feclearexcept(int mask) {
return 0;
}
int fegetenv(fenv_t *envp) {
return 0;
}
int feraiseexcept(int mask) {
return 0;
}
int fetestexcept(int mask) {
return 0;
}
int fesetenv(const fenv_t *envp) {
return 0;
}

39
libc/runtime/fenv.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_FENV_H_
#define COSMOPOLITAN_LIBC_RUNTIME_FENV_H_
#define FE_TONEAREST 0x0000
#define FE_DOWNWARD 0x0400
#define FE_UPWARD 0x0800
#define FE_TOWARDZERO 0x0c00
#define FE_INVALID 1
#define FE_DIVBYZERO 4
#define FE_OVERFLOW 8
#define FE_UNDERFLOW 16
#define FE_INEXACT 32
#define FE_ALL_EXCEPT 61
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define FLT_ROUNDS (__flt_rounds())
typedef void *fenv_t;
typedef uint16_t fexcept_t;
int feclearexcept(int);
int fegetenv(fenv_t *);
int fegetexceptflag(fexcept_t *, int);
int fegetround(void);
int feholdexcept(fenv_t *);
int feraiseexcept(int);
int fesetenv(const fenv_t *);
int fesetexceptflag(const fexcept_t *, int);
int fesetround(int);
int fetestexcept(int);
int feupdateenv(const fenv_t *);
int __flt_rounds(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_FENV_H_ */

49
libc/runtime/fesetround.c Normal file
View file

@ -0,0 +1,49 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/fenv.h"
/**
* Sets rounding mode.
*
* This configures the x87 FPU as well as SSE.
*
* @param mode may be FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, or FE_TOWARDZERO
* @return 0 on success, or -1 on error
*/
int fesetround(int mode) {
uint16_t x87cw;
uint32_t ssecw;
switch (mode) {
case FE_TONEAREST:
case FE_DOWNWARD:
case FE_UPWARD:
case FE_TOWARDZERO:
asm("fnstcw\t%0" : "=m"(x87cw));
x87cw &= ~0x0c00;
x87cw |= mode;
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
asm("stmxcsr\t%0" : "=m"(ssecw));
ssecw &= ~(0x0c00 << 3);
ssecw |= (mode << 3);
asm volatile("ldmxcsr\t%0" : /* no outputs */ : "m"(ssecw));
return 0;
default:
return -1;
}
}

36
libc/runtime/fltrounds.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/fenv.h"
int __flt_rounds(void) {
int x87cw;
asm("fnstcw\t%0" : "=m"(x87cw));
switch ((x87cw & 0x0c00) >> 10) {
case FE_TOWARDZERO >> 10:
return 0;
case FE_TONEAREST >> 10:
return 1;
case FE_UPWARD >> 10:
return 2;
case FE_DOWNWARD >> 10:
return 3;
default:
unreachable;
}
}

View file

@ -16,7 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/runtime.h"
#include "libc/runtime/dlfcn.h"
char *dlerror(void) {
return "cosmopolitan doesn't support dsos";

View file

@ -1573,17 +1573,6 @@ syscon misc TCOFLUSH 1 2 2 2 2 0 # bsd consensus
syscon misc TCOOFF 0 1 1 1 1 0 # bsd consensus
syscon misc TCOON 1 2 2 2 2 0 # bsd consensus
syscon misc FE_TONEAREST 0 0 0 0 0 0 # consensus
syscon misc FE_DIVBYZERO 4 4 4 4 4 0 # unix consensus
syscon misc FE_DOWNWARD 0x0400 0x0400 0x0400 0x0400 0x0400 0 # unix consensus
syscon misc FE_INEXACT 0x20 0x20 0x20 0x20 0x20 0 # unix consensus
syscon misc FE_INVALID 1 1 1 1 1 0 # unix consensus
syscon misc FE_OVERFLOW 8 8 8 8 8 0 # unix consensus
syscon misc FE_TOWARDZERO 0x0c00 0x0c00 0x0c00 0x0c00 0x0c00 0 # unix consensus
syscon misc FE_UNDERFLOW 0x10 0x10 0x10 0x10 0x10 0 # unix consensus
syscon misc FE_UPWARD 0x0800 0x0800 0x0800 0x0800 0x0800 0 # unix consensus
syscon misc FE_ALL_EXCEPT 61 63 63 63 63 0 # bsd consensus
syscon misc TYPE_DISK 0 0 0 0 0 0 # consensus
syscon misc TYPE_A 1 1 1 1 1 0 # unix consensus
syscon misc TYPE_E 2 2 2 2 2 0 # unix consensus
@ -1637,18 +1626,6 @@ syscon misc PTHREAD_MUTEX_NORMAL 0 0 0 3 3 0
syscon misc PTHREAD_MUTEX_ROBUST 0 0 1 0 0 0
syscon misc PTHREAD_PROCESS_PRIVATE 0 2 0 0 0 0
syscon misc FTW_F 0 0 0 0 0 0 # consensus
syscon misc FTW_D 1 1 1 1 1 0 # unix consensus
syscon misc FTW_DNR 2 2 2 2 2 0 # unix consensus
syscon misc FTW_MOUNT 2 2 2 2 2 0 # unix consensus
syscon misc FTW_PHYS 1 1 1 1 1 0 # unix consensus
syscon misc FTW_SLN 6 6 6 6 6 0 # unix consensus
syscon misc FTW_CHDIR 4 8 8 8 8 0 # bsd consensus
syscon misc FTW_DEPTH 8 4 4 4 4 0 # bsd consensus
syscon misc FTW_DP 5 3 3 3 3 0 # bsd consensus
syscon misc FTW_NS 3 4 4 4 4 0 # bsd consensus
syscon misc FTW_SL 4 5 5 5 5 0 # bsd consensus
syscon misc N_TTY 0 0 0 0 0 0 # consensus
syscon misc N_6PACK 7 0 0 0 0 0
syscon misc N_AX25 5 0 0 0 0 0
@ -2009,14 +1986,6 @@ syscon misc NL_TEXTMAX 0x7fffffff 0x0800 0x0800 255 255 0
syscon misc NL_NMAX 0x7fffffff 1 1 0 0 0
syscon misc NL_SETD 1 1 0 1 1 0
syscon misc RTLD_LAZY 1 1 1 1 1 0 # unix consensus
syscon misc RTLD_NOW 2 2 2 2 2 0 # unix consensus
syscon misc RTLD_GLOBAL 0x0100 8 0x0100 0x0100 0x0100 0
syscon misc RTLD_NODELETE 0x1000 0x80 0x1000 0 0 0
syscon misc RTLD_NOLOAD 4 0x10 0x2000 0 0 0
syscon misc RTLD_DI_LINKMAP 0 0 2 0 0 0
syscon misc RTLD_LOCAL 0 4 0 0 0 0
syscon rusage RUSAGE_SELF 0 0 0 0 0 0 # unix consensus & faked nt
syscon rusage RUSAGE_CHILDREN -1 -1 -1 -1 -1 99 # unix consensus & unavailable on nt
syscon rusage RUSAGE_THREAD 1 99 1 1 1 1 # faked nt & unavailable on xnu

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_ALL_EXCEPT,61,63,63,63,63,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_DIVBYZERO,4,4,4,4,4,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_DOWNWARD,0x0400,0x0400,0x0400,0x0400,0x0400,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_INEXACT,0x20,0x20,0x20,0x20,0x20,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_INVALID,1,1,1,1,1,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_OVERFLOW,8,8,8,8,8,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_TONEAREST,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_TOWARDZERO,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_UNDERFLOW,0x10,0x10,0x10,0x10,0x10,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FE_UPWARD,0x0800,0x0800,0x0800,0x0800,0x0800,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_CHDIR,4,8,8,8,8,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_D,1,1,1,1,1,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_DEPTH,8,4,4,4,4,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_DNR,2,2,2,2,2,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_DP,5,3,3,3,3,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_F,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_MOUNT,2,2,2,2,2,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_NS,3,4,4,4,4,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_PHYS,1,1,1,1,1,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_SL,4,5,5,5,5,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,FTW_SLN,6,6,6,6,6,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_DI_LINKMAP,0,0,2,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_GLOBAL,0x0100,8,0x0100,0x0100,0x0100,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_LAZY,1,1,1,1,1,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_LOCAL,0,4,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_NODELETE,0x1000,0x80,0x1000,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_NOLOAD,4,0x10,0x2000,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon misc,RTLD_NOW,2,2,2,2,2,0

View file

@ -1,32 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_FE_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_FE_H_
#include "libc/runtime/symbolic.h"
#define FE_ALL_EXCEPT SYMBOLIC(FE_ALL_EXCEPT)
#define FE_DIVBYZERO SYMBOLIC(FE_DIVBYZERO)
#define FE_DOWNWARD SYMBOLIC(FE_DOWNWARD)
#define FE_INEXACT SYMBOLIC(FE_INEXACT)
#define FE_INVALID SYMBOLIC(FE_INVALID)
#define FE_OVERFLOW SYMBOLIC(FE_OVERFLOW)
#define FE_TONEAREST SYMBOLIC(FE_TONEAREST)
#define FE_TOWARDZERO SYMBOLIC(FE_TOWARDZERO)
#define FE_UNDERFLOW SYMBOLIC(FE_UNDERFLOW)
#define FE_UPWARD SYMBOLIC(FE_UPWARD)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern const long FE_ALL_EXCEPT;
extern const long FE_DIVBYZERO;
extern const long FE_DOWNWARD;
extern const long FE_INEXACT;
extern const long FE_INVALID;
extern const long FE_OVERFLOW;
extern const long FE_TONEAREST;
extern const long FE_TOWARDZERO;
extern const long FE_UNDERFLOW;
extern const long FE_UPWARD;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_FE_H_ */

View file

@ -1,34 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_FTW_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_FTW_H_
#include "libc/runtime/symbolic.h"
#define FTW_CHDIR SYMBOLIC(FTW_CHDIR)
#define FTW_D SYMBOLIC(FTW_D)
#define FTW_DEPTH SYMBOLIC(FTW_DEPTH)
#define FTW_DNR SYMBOLIC(FTW_DNR)
#define FTW_DP SYMBOLIC(FTW_DP)
#define FTW_F SYMBOLIC(FTW_F)
#define FTW_MOUNT SYMBOLIC(FTW_MOUNT)
#define FTW_NS SYMBOLIC(FTW_NS)
#define FTW_PHYS SYMBOLIC(FTW_PHYS)
#define FTW_SL SYMBOLIC(FTW_SL)
#define FTW_SLN SYMBOLIC(FTW_SLN)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern const long FTW_CHDIR;
extern const long FTW_D;
extern const long FTW_DEPTH;
extern const long FTW_DNR;
extern const long FTW_DP;
extern const long FTW_F;
extern const long FTW_MOUNT;
extern const long FTW_NS;
extern const long FTW_PHYS;
extern const long FTW_SL;
extern const long FTW_SLN;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_FTW_H_ */

View file

@ -1,26 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_RTLD_H_
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_RTLD_H_
#include "libc/runtime/symbolic.h"
#define RTLD_DI_LINKMAP SYMBOLIC(RTLD_DI_LINKMAP)
#define RTLD_GLOBAL SYMBOLIC(RTLD_GLOBAL)
#define RTLD_LAZY SYMBOLIC(RTLD_LAZY)
#define RTLD_LOCAL SYMBOLIC(RTLD_LOCAL)
#define RTLD_NODELETE SYMBOLIC(RTLD_NODELETE)
#define RTLD_NOLOAD SYMBOLIC(RTLD_NOLOAD)
#define RTLD_NOW SYMBOLIC(RTLD_NOW)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern const long RTLD_DI_LINKMAP;
extern const long RTLD_GLOBAL;
extern const long RTLD_LAZY;
extern const long RTLD_LOCAL;
extern const long RTLD_NODELETE;
extern const long RTLD_NOLOAD;
extern const long RTLD_NOW;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_RTLD_H_ */

View file

@ -19,12 +19,9 @@
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
#include "third_party/gdtoa/gdtoa.h"
testonly char *testlib_formatfloat(long double x) {
char buf[32];
char *str = malloc(256);
g_xfmt_p(buf, &x, 15, sizeof(buf), 0);
sprintf(str, "%Lf (%s)", x, buf);
return str;
return xasprintf("%.15Lg", x);
}

View file

@ -22,5 +22,5 @@
* Returns inverse hyperbolic tangent of 𝑥.
*/
double atanh(double x) {
return log((1 + x) / (1 - x)) / 2;
return x ? log((1 + x) / (1 - x)) / 2 : x;
}

View file

@ -22,5 +22,5 @@
* Returns inverse hyperbolic tangent of 𝑥.
*/
float atanhf(float x) {
return logf((1 + x) / (1 - x)) / 2;
return x ? logf((1 + x) / (1 - x)) / 2 : x;
}

View file

@ -22,5 +22,5 @@
* Returns inverse hyperbolic tangent of 𝑥.
*/
long double atanhl(long double x) {
return logl((1 + x) / (1 - x)) / 2;
return x ? logl((1 + x) / (1 - x)) / 2 : x;
}

View file

@ -19,7 +19,7 @@
#include "libc/runtime/pc.internal.h"
#include "libc/macros.internal.h"
// Returns 𝑒^x-1.
// Returns 𝑒^𝑥-𝟷.
//
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
// @return result of exponentiation on FPU stack in %st
@ -27,11 +27,13 @@ expm1l: push %rbp
mov %rsp,%rbp
.profilable
fldt 16(%rbp)
fxam # isinf(x)
fxam
fstsw %ax
mov %ah,%al
and $0x45,%ah
cmp $5,%ah
and $(FPU_C3|FPU_C2|FPU_C0)>>8,%ah
cmp $(FPU_C3)>>8,%ah # !x
je 0f
cmp $(FPU_C2|FPU_C0)>>8,%ah # isinf(x)
je 1f
fldl2e
fmulp %st,%st(1)
@ -50,7 +52,7 @@ expm1l: push %rbp
faddp %st,%st(1)
0: pop %rbp
ret
1: test $2,%al # signbit(x)
1: test $FPU_C1>>8,%al # signbit(x)
jz 0b
fstp %st
fld1

View file

@ -46,7 +46,11 @@ long double powl(long double x, long double y) {
return 1;
}
} else if (y > 0) {
return y == 1 ? x : 0;
if (signbit(x) && y == truncl(y) && ((int64_t)y & 1)) {
return -0.;
} else {
return 0;
}
} else if (!y) {
return 1;
} else {

View file

@ -22,5 +22,6 @@
* Returns hyperbolic sine of 𝑥.
*/
double sinh(double x) {
if (!x) return x;
return (exp(x) - exp(-x)) / 2;
}

View file

@ -22,5 +22,6 @@
* Returns hyperbolic sine of 𝑥.
*/
float sinhf(float x) {
if (!x) return x;
return (expf(x) - expf(-x)) / 2;
}

View file

@ -22,5 +22,6 @@
* Returns hyperbolic sine of 𝑥.
*/
long double sinhl(long double x) {
if (!x) return x;
return (expl(x) - expl(-x)) / 2;
}

View file

@ -22,6 +22,7 @@
* Returns hyperbolic tangent of 𝑥.
*/
double tanh(double x) {
if (!x) return x;
if (isinf(x)) return copysign(1, x);
return sinh(x) / cosh(x);
}

View file

@ -22,6 +22,7 @@
* Returns hyperbolic tangent of 𝑥.
*/
float tanhf(float x) {
if (!x) return x;
if (isinf(x)) return copysignf(1, x);
return sinhf(x) / coshf(x);
}

View file

@ -22,6 +22,7 @@
* Returns hyperbolic tangent of 𝑥.
*/
long double tanhl(long double x) {
if (!x) return x;
if (isinf(x)) return copysignl(1, x);
return sinhl(x) / coshl(x);
}

View file

@ -282,6 +282,11 @@ TEST(atan2, test) {
gc(xasprintf("%.15g", atan2(__DBL_MAX__, __DBL_MIN__))));
EXPECT_STREQ("0.785398163397448",
gc(xasprintf("%.15g", atan2(__DBL_MAX__, __DBL_MAX__))));
EXPECT_STREQ("-0",
gc(xasprintf("%.15g", atan2(-0.000000000000001, INFINITY))));
EXPECT_STREQ("-0", gc(xasprintf("%.15g", atan2(-1, INFINITY))));
EXPECT_STREQ(
"-0", gc(xasprintf("%.15g", atan2(-1.7976931348623157e308, INFINITY))));
}
BENCH(atan2, bench) {

View file

@ -27,6 +27,7 @@
TEST(atanh, test) {
EXPECT_STREQ("0", gc(xdtoa(atanh(0))));
EXPECT_STREQ("-0", gc(xdtoa(atanh(-0.))));
EXPECT_STREQ(".549306144334055", gc(xdtoa(atanh(.5))));
EXPECT_STREQ("-.549306144334055", gc(xdtoa(atanh(-.5))));
EXPECT_STREQ("INFINITY", gc(xdtoa(atanh(+1))));
@ -37,6 +38,7 @@ TEST(atanh, test) {
TEST(atanhl, test) {
EXPECT_STREQ("0", gc(xdtoal(atanhl(0))));
EXPECT_STREQ("-0", gc(xdtoal(atanhl(-0.))));
EXPECT_STREQ(".5493061443340548", gc(xdtoal(atanhl(.5))));
EXPECT_STREQ("-.5493061443340548", gc(xdtoal(atanhl(-.5))));
EXPECT_STREQ("INFINITY", gc(xdtoal(atanhl(+1))));
@ -47,6 +49,7 @@ TEST(atanhl, test) {
TEST(atanhf, test) {
EXPECT_STREQ("0", gc(xdtoaf(atanhf(0))));
EXPECT_STREQ("-0", gc(xdtoaf(atanhf(-0.))));
EXPECT_STREQ(".549306", gc(xdtoaf(atanhf(.5))));
EXPECT_STREQ("-.549306", gc(xdtoaf(atanhf(-.5))));
EXPECT_STREQ("INFINITY", gc(xdtoaf(atanhf(+1))));

View file

@ -25,11 +25,37 @@
#define expm1(x) expm1(VEIL("x", (double)(x)))
#define expm1f(x) expm1f(VEIL("x", (float)(x)))
TEST(expm1, test) {
EXPECT_STREQ("0", gc(xdtoa(expm1(0))));
EXPECT_STREQ("-0", gc(xdtoa(expm1(-0.))));
EXPECT_STREQ("NAN", gc(xdtoa(expm1(NAN))));
EXPECT_STREQ("-1", gc(xdtoa(expm1(-INFINITY))));
EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(INFINITY))));
/* EXPECT_STREQ("-INFINITY", gc(xdtoa(expm1(-132098844872390)))); */
/* EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(132098844872390)))); */
EXPECT_STREQ("0", gc(xasprintf("%.15g", expm1(0.))));
EXPECT_STREQ("-0", gc(xasprintf("%.15g", expm1(-0.))));
EXPECT_STREQ("0.648721270700128", gc(xasprintf("%.15g", expm1(.5))));
EXPECT_STREQ("-0.393469340287367", gc(xasprintf("%.15g", expm1(-.5))));
EXPECT_STREQ("1.71828182845905", gc(xasprintf("%.15g", expm1(1.))));
EXPECT_STREQ("-0.632120558828558", gc(xasprintf("%.15g", expm1(-1.))));
EXPECT_STREQ("3.48168907033806", gc(xasprintf("%.15g", expm1(1.5))));
EXPECT_STREQ("-0.77686983985157", gc(xasprintf("%.15g", expm1(-1.5))));
EXPECT_STREQ("6.38905609893065", gc(xasprintf("%.15g", expm1(2.))));
EXPECT_TRUE(isnan(expm1(NAN)));
EXPECT_TRUE(isnan(expm1(-NAN)));
EXPECT_STREQ("inf", gc(xasprintf("%.15g", expm1(INFINITY))));
EXPECT_STREQ("-1", gc(xasprintf("%.15g", expm1(-INFINITY))));
EXPECT_STREQ("2.2250738585072e-308",
gc(xasprintf("%.15g", expm1(__DBL_MIN__))));
EXPECT_STREQ("inf", gc(xasprintf("%.15g", expm1(__DBL_MAX__))));
}
TEST(expm1l, test) {
EXPECT_STREQ("1.718281828459045", gc(xdtoal(expm1l(1))));
EXPECT_STREQ("1.718281828459045", gc(xdtoal(expl(1) - 1)));
EXPECT_STREQ("0", gc(xdtoal(expm1l(0))));
EXPECT_STREQ("0", gc(xdtoal(expm1l(-0.))));
EXPECT_STREQ("-0", gc(xdtoal(expm1l(-0.))));
EXPECT_STREQ("NAN", gc(xdtoal(expm1l(NAN))));
EXPECT_STREQ("-1", gc(xdtoal(expm1l(-INFINITY))));
EXPECT_STREQ("INFINITY", gc(xdtoal(expm1l(INFINITY))));
@ -37,19 +63,9 @@ TEST(expm1l, test) {
/* EXPECT_STREQ("INFINITY", gc(xdtoal(expm1l(132098844872390)))); */
}
TEST(expm1, test) {
EXPECT_STREQ("0", gc(xdtoa(expm1(0))));
EXPECT_STREQ("0", gc(xdtoa(expm1(-0.))));
EXPECT_STREQ("NAN", gc(xdtoa(expm1(NAN))));
EXPECT_STREQ("-1", gc(xdtoa(expm1(-INFINITY))));
EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(INFINITY))));
/* EXPECT_STREQ("-INFINITY", gc(xdtoa(expm1(-132098844872390)))); */
/* EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(132098844872390)))); */
}
TEST(expm1f, test) {
EXPECT_STREQ("0", gc(xdtoaf(expm1f(0))));
EXPECT_STREQ("0", gc(xdtoaf(expm1f(-0.))));
EXPECT_STREQ("-0", gc(xdtoaf(expm1f(-0.))));
EXPECT_STREQ("NAN", gc(xdtoaf(expm1f(NAN))));
EXPECT_STREQ("-1", gc(xdtoaf(expm1f(-INFINITY))));
EXPECT_STREQ("INFINITY", gc(xdtoaf(expm1f(INFINITY))));

View file

@ -100,6 +100,8 @@ TEST(powl, test) {
EXPECT_TRUE(isnan(powl(-3, -(1. / MAX(rando, 2)))));
EXPECT_STREQ("-.3333333333333333", gc(xdtoal(powl(-3, -1))));
EXPECT_STREQ(".1111111111111111", gc(xdtoal(powl(-3, -2))));
EXPECT_STREQ("-0", gc(xdtoal(powl(-0., MAX(1, rando) | 1))));
EXPECT_STREQ("0", gc(xdtoal(powl(-0., MAX(1, rando) & ~1))));
}
TEST(pow, test) {
@ -150,6 +152,8 @@ TEST(pow, test) {
EXPECT_STREQ("inf", fmtd(pow(-0., -(rando & -2))));
EXPECT_STREQ("-0.333333333333333", fmtd(pow(-3, -1)));
EXPECT_STREQ("0.111111111111111", fmtd(pow(-3, -2)));
EXPECT_STREQ("-0", gc(xdtoa(pow(-0., MAX(1, rando) | 1))));
EXPECT_STREQ("0", gc(xdtoa(pow(-0., MAX(1, rando) & ~1))));
}
TEST(powf, test) {
@ -200,6 +204,8 @@ TEST(powf, test) {
EXPECT_STREQ("inf", fmtf(powf(-0., -(rando & -2))));
EXPECT_STREQ("-0.333333", fmtf(powf(-3, -1)));
EXPECT_STREQ("0.111111", fmtf(powf(-3, -2)));
EXPECT_STREQ("-0", gc(xdtoaf(powf(-0., MAX(1, rando) | 1))));
EXPECT_STREQ("0", gc(xdtoaf(powf(-0., MAX(1, rando) & ~1))));
}
TEST(powl, errors) {
@ -537,6 +543,15 @@ TEST(powl, errors) {
errno = 0;
EXPECT_STREQ("inf", fmtd(pow(__DBL_MAX__, __DBL_MAX__)));
/* EXPECT_EQ(ERANGE, errno); */
EXPECT_STREQ("1", gc(xasprintf("%.15g", pow(0., 0))));
EXPECT_STREQ("1", gc(xasprintf("%.15g", pow(-0., 0))));
EXPECT_STREQ("-0", gc(xasprintf("%.15g", pow(-0., 1))));
EXPECT_STREQ("-0", gc(xasprintf("%.15g", pow(-0., 11))));
EXPECT_STREQ("-0", gc(xasprintf("%.15g", pow(-0., 111))));
EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 2))));
EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 22))));
EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 222))));
EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 2.5))));
}
BENCH(powl, bench) {

View file

@ -31,6 +31,7 @@ TEST(sinh, test) {
EXPECT_STREQ("INFINITY", gc(xdtoa(sinh(30000))));
EXPECT_STREQ("-INFINITY", gc(xdtoa(sinh(-30000))));
EXPECT_STREQ("0", gc(xdtoa(sinh(0))));
EXPECT_STREQ("-0", gc(xdtoa(sinh(-0.))));
EXPECT_STREQ("NAN", gc(xdtoa(sinh(NAN))));
EXPECT_STREQ("INFINITY", gc(xdtoa(sinh(INFINITY))));
EXPECT_STREQ("-INFINITY", gc(xdtoa(sinh(-INFINITY))));
@ -42,6 +43,7 @@ TEST(sinhl, test) {
EXPECT_STREQ("INFINITY", gc(xdtoal(sinhl(30000))));
EXPECT_STREQ("-INFINITY", gc(xdtoal(sinhl(-30000))));
EXPECT_STREQ("0", gc(xdtoal(sinhl(0))));
EXPECT_STREQ("-0", gc(xdtoal(sinhl(-0.))));
EXPECT_STREQ("NAN", gc(xdtoal(sinhl(NAN))));
EXPECT_STREQ("INFINITY", gc(xdtoal(sinhl(INFINITY))));
EXPECT_STREQ("-INFINITY", gc(xdtoal(sinhl(-INFINITY))));
@ -53,6 +55,7 @@ TEST(sinhf, test) {
EXPECT_STREQ("INFINITY", gc(xdtoaf(sinhf(30000))));
EXPECT_STREQ("-INFINITY", gc(xdtoaf(sinhf(-30000))));
EXPECT_STREQ("0", gc(xdtoaf(sinhf(0))));
EXPECT_STREQ("-0", gc(xdtoaf(sinhf(-0.))));
EXPECT_STREQ("NAN", gc(xdtoaf(sinhf(NAN))));
EXPECT_STREQ("INFINITY", gc(xdtoaf(sinhf(INFINITY))));
EXPECT_STREQ("-INFINITY", gc(xdtoaf(sinhf(-INFINITY))));

View file

@ -0,0 +1,72 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/runtime/fenv.h"
#include "libc/runtime/gc.internal.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
#include "third_party/gdtoa/gdtoa.h"
TEST(strtod, testNearest) {
EXPECT_STREQ("-1.79769313486231e+308",
gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL))));
}
#if 0 /* TODO(jart): Why doesn't this work on Travis CI? */
int oldround;
void SetUp(void) {
oldround = fegetround();
}
void TearDown(void) {
fesetround(oldround);
}
TEST(strtod, testNearest) {
fesetround(FE_TONEAREST);
EXPECT_STREQ("-1.79769313486231e+308",
gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL))));
}
TEST(strtod, testDownward) {
fesetround(FE_DOWNWARD);
EXPECT_STREQ("-1.79769313486232e+308",
gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL))));
}
TEST(strtod, testUpward) {
fesetround(FE_UPWARD);
EXPECT_STREQ("-1.7976931348623e+308",
gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL))));
}
TEST(strtod, testTowardzero) {
char *p;
for (int i = 0; i < 9999; ++i) {
fesetround(FE_TOWARDZERO);
EXPECT_STREQ(
"-1.7976931348623e+308",
(p = xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL))));
fesetround(FE_TONEAREST);
free(p);
}
}
#endif

View file

@ -29,6 +29,7 @@ TEST(tanhl, test) {
EXPECT_STREQ(".09966799462495582", gc(xdtoal(tanhl(+.1))));
EXPECT_STREQ("-.09966799462495582", gc(xdtoal(tanhl(-.1))));
EXPECT_STREQ("0", gc(xdtoal(tanhl(0))));
EXPECT_STREQ("-0", gc(xdtoal(tanhl(-0.))));
EXPECT_TRUE(isnan(tanhl(NAN)));
EXPECT_STREQ("1", gc(xdtoal(tanhl(INFINITY))));
EXPECT_STREQ("-1", gc(xdtoal(tanhl(-INFINITY))));
@ -38,6 +39,7 @@ TEST(tanh, test) {
EXPECT_STREQ(".0996679946249559", gc(xdtoa(tanh(+.1))));
EXPECT_STREQ("-.0996679946249559", gc(xdtoa(tanh(-.1))));
EXPECT_STREQ("0", gc(xdtoa(tanh(0))));
EXPECT_STREQ("-0", gc(xdtoa(tanh(-0.))));
EXPECT_TRUE(isnan(tanh(NAN)));
EXPECT_STREQ("1", gc(xdtoa(tanh(INFINITY))));
EXPECT_STREQ("-1", gc(xdtoa(tanh(-INFINITY))));
@ -47,6 +49,7 @@ TEST(tanhf, test) {
EXPECT_STREQ(".099668", gc(xdtoaf(tanhf(+.1))));
EXPECT_STREQ("-.099668", gc(xdtoaf(tanhf(-.1))));
EXPECT_STREQ("0", gc(xdtoaf(tanhf(0))));
EXPECT_STREQ("-0", gc(xdtoaf(tanhf(-0.))));
EXPECT_TRUE(isnan(tanhf(NAN)));
EXPECT_STREQ("1", gc(xdtoaf(tanhf(INFINITY))));
EXPECT_STREQ("-1", gc(xdtoaf(tanhf(-INFINITY))));

View file

@ -37,7 +37,8 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \
LIBC_TESTLIB \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X
LIBC_X \
THIRD_PARTY_GDTOA
TEST_LIBC_TINYMATH_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBC_TINYMATH_DIRECTDEPS),$($(x))))

View file

@ -1,5 +1,6 @@
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/fenv.h"
#include "libc/str/str.h"
#include "third_party/gdtoa/gdtoa.h"
@ -10,11 +11,15 @@ Kudos go to Guy L. Steele, Jr. and Jon L. White\\n\
Copyright (C) 1997, 1998, 2000 by Lucent Technologies\"");
asm(".include \"libc/disclaimer.inc\"");
#define IEEE_Arith 1
#define IEEE_8087 1
#define f_QNAN 0x7fc00000
#define d_QNAN0 0x7ff80000
#define d_QNAN1 0x0
#define IEEE_Arith 1
#define IEEE_8087 1
#define Honor_FLT_ROUNDS 1
#define f_QNAN 0x7fc00000
#define d_QNAN0 0x7ff80000
#define d_QNAN1 0x0
#define Check_FLT_ROUNDS 1
#define Trust_FLT_ROUNDS 1
/****************************************************************

View file

@ -28,6 +28,7 @@ THIRD_PARTY_GDTOA_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
@ -45,13 +46,6 @@ $(THIRD_PARTY_GDTOA_A).pkg: \
$(THIRD_PARTY_GDTOA_A_OBJS) \
$(foreach x,$(THIRD_PARTY_GDTOA_A_DIRECTDEPS),$($(x)_A).pkg)
$(THIRD_PARTY_GDTOA_A_OBJS): \
OVERRIDE_CFLAGS += \
$(OLD_CODE) \
$(IEEE_MATH) \
-ffunction-sections \
-fdata-sections
THIRD_PARTY_GDTOA_LIBS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)))
THIRD_PARTY_GDTOA_SRCS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_SRCS))
THIRD_PARTY_GDTOA_HDRS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_HDRS))

View file

@ -729,7 +729,7 @@ strtod(CONST char *s00, char **se)
}
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
dval(&adj) *= ulp(&rv);
dval(&adj) *= ulp(&rv); /* XXX */
if (dsign) {
if (word0(&rv) == Big0 && word1(&rv) == Big1)
goto ovfl;

View file

@ -41,7 +41,7 @@ THIRD_PARTY_LUA_DEPS := \
$(THIRD_PARTY_LUA_A): \
third_party/lua/ \
$(THIRD_PARTY_LUA_A).pkg \
$(filter-out %/lua.c,$(THIRD_PARTY_LUA_OBJS))
$(filter-out %/lua.o,$(THIRD_PARTY_LUA_OBJS))
$(THIRD_PARTY_LUA_A).pkg: \
$(THIRD_PARTY_LUA_OBJS) \

49
third_party/musl/ftw.c vendored Normal file
View file

@ -0,0 +1,49 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "third_party/musl/ftw.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
/**
* Walks file tree.
*
* @see examples/walk.c for example
* @see nftw()
*/
int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int fd_limit)
{
/* The following cast assumes that calling a function with one
* argument more than it needs behaves as expected. This is
* actually undefined, but works on all real-world machines. */
return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS);
}

32
third_party/musl/ftw.h vendored Normal file
View file

@ -0,0 +1,32 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_FTW_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_FTW_H_
#include "libc/calls/struct/stat.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define FTW_F 1
#define FTW_D 2
#define FTW_DNR 3
#define FTW_NS 4
#define FTW_SL 5
#define FTW_DP 6
#define FTW_SLN 7
#define FTW_PHYS 1
#define FTW_MOUNT 2
#define FTW_CHDIR 4
#define FTW_DEPTH 8
struct FTW {
int base;
int level;
};
int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
int nftw(const char *,
int (*)(const char *, const struct stat *, int, struct FTW *), int,
int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_FTW_H_ */

182
third_party/musl/nftw.c vendored Normal file
View file

@ -0,0 +1,182 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│
vi: set et ft=c ts=4 sw=4 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/weirdtypes.h"
#include "libc/errno.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "third_party/musl/ftw.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* no reason to impose windows limit
small enough to fit in stack frame
should be changed to use realloc */
#define PATH_MAX2 2048
/* no cosmo pthreads support atm */
#define pthread_setcancelstate(...)
/* clang-format off */
struct history
{
struct history *chain;
dev_t dev;
ino_t ino;
int level;
int base;
};
static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
{
size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
struct stat st;
struct history new;
int type;
int r;
int dfd=-1;
int err=0;
struct FTW lev;
if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
type = FTW_SLN;
else if (errno != EACCES) return -1;
else type = FTW_NS;
} else if (S_ISDIR(st.st_mode)) {
if (flags & FTW_DEPTH) type = FTW_DP;
else type = FTW_D;
} else if (S_ISLNK(st.st_mode)) {
if (flags & FTW_PHYS) type = FTW_SL;
else type = FTW_SLN;
} else {
type = FTW_F;
}
if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
return 0;
new.chain = h;
new.dev = st.st_dev;
new.ino = st.st_ino;
new.level = h ? h->level+1 : 0;
new.base = j+1;
lev.level = new.level;
if (h) {
lev.base = h->base;
} else {
size_t k;
for (k=j; k && path[k]=='/'; k--);
for (; k && path[k-1]!='/'; k--);
lev.base = k;
}
if (type == FTW_D || type == FTW_DP) {
dfd = open(path, O_RDONLY);
err = errno;
if (dfd < 0 && err == EACCES) type = FTW_DNR;
if (!fd_limit) close(dfd);
}
if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
for (; h; h = h->chain)
if (h->dev == st.st_dev && h->ino == st.st_ino)
return 0;
if ((type == FTW_D || type == FTW_DP) && fd_limit) {
if (dfd < 0) {
errno = err;
return -1;
}
DIR *d = fdopendir(dfd);
if (d) {
struct dirent *de;
while ((de = readdir(d))) {
if (de->d_name[0] == '.'
&& (!de->d_name[1]
|| (de->d_name[1]=='.'
&& !de->d_name[2]))) continue;
if (strlen(de->d_name) >= PATH_MAX2-l) {
errno = ENAMETOOLONG;
closedir(d);
return -1;
}
path[j]='/';
strcpy(path+j+1, de->d_name);
if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
closedir(d);
return r;
}
}
closedir(d);
} else {
close(dfd);
return -1;
}
}
path[l] = 0;
if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
return r;
return 0;
}
/**
* Walks file tree.
*
* @see examples/walk.c for example
*/
int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
{
int r, cs;
size_t l;
char pathbuf[PATH_MAX2+1];
if (fd_limit <= 0) return 0;
l = strlen(path);
if (l > PATH_MAX2) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(pathbuf, path, l+1);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
pthread_setcancelstate(cs, 0);
return r;
}

148
third_party/quickjs/Changelog vendored Normal file
View file

@ -0,0 +1,148 @@
2021-03-27:
- faster Array.prototype.push and Array.prototype.unshift
- added JS_UpdateStackTop()
- fixed Windows console
- misc bug fixes
2020-11-08:
- improved function parameter initializers
- added std.setenv(), std.unsetenv() and std.getenviron()
- added JS_EvalThis()
- misc bug fixes
2020-09-06:
- added logical assignment operators
- added IsHTMLDDA support
- faster for-of loops
- os.Worker now takes a module filename as parameter
- qjsc: added -D option to compile dynamically loaded modules or workers
- misc bug fixes
2020-07-05:
- modified JS_GetPrototype() to return a live value
- REPL: support unicode characters larger than 16 bits
- added os.Worker
- improved object serialization
- added std.parseExtJSON
- misc bug fixes
2020-04-12:
- added cross realm support
- added AggregateError and Promise.any
- added env, uid and gid options in os.exec()
- misc bug fixes
2020-03-16:
- reworked error handling in std and os libraries: suppressed I/O
exceptions in std FILE functions and return a positive errno value
when it is explicit
- output exception messages to stderr
- added std.loadFile(), std.strerror(), std.FILE.prototype.tello()
- added JS_GetRuntimeOpaque(), JS_SetRuntimeOpaque(), JS_NewUint32()
- updated to Unicode 13.0.0
- misc bug fixes
2020-01-19:
- keep CONFIG_BIGNUM in the makefile
- added os.chdir()
- qjs: added -I option
- more memory checks in the bignum operations
- modified operator overloading semantics to be closer to the TC39
proposal
- suppressed "use bigint" mode. Simplified "use math" mode
- BigDecimal: changed suffix from 'd' to 'm'
- misc bug fixes
2020-01-05:
- always compile the bignum code. Added '--bignum' option to qjs.
- added BigDecimal
- added String.prototype.replaceAll
- misc bug fixes
2019-12-21:
- added nullish coalescing operator (ES2020)
- added optional chaining (ES2020)
- removed recursions in garbage collector
- test stack overflow in the parser
- improved backtrace logic
- added JS_SetHostPromiseRejectionTracker()
- allow exotic constructors
- improved c++ compatibility
- misc bug fixes
2019-10-27:
- added example of C class in a module (examples/test_point.js)
- added JS_GetTypedArrayBuffer()
- misc bug fixes
2019-09-18:
- added os.exec and other system calls
- exported JS_ValueToAtom()
- qjsc: added 'qjsc_' prefix to the generated C identifiers
- added cross-compilation support
- misc bug fixes
2019-09-01:
- added globalThis
- documented JS_EVAL_FLAG_COMPILE_ONLY
- added import.meta.url and import.meta.main
- added 'debugger' statement
- misc bug fixes
2019-08-18:
- added os.realpath, os.getcwd, os.mkdir, os.stat, os.lstat,
os.readlink, os.readdir, os.utimes, std.popen
- module autodetection
- added import.meta
- misc bug fixes
2019-08-10:
- added public class fields and private class fields, methods and
accessors (TC39 proposal)
- changed JS_ToCStringLen() prototype
- qjsc: handle '-' in module names and modules with the same filename
- added std.urlGet
- exported JS_GetOwnPropertyNames() and JS_GetOwnProperty()
- exported some bigint C functions
- added support for eshost in run-test262
- misc bug fixes
2019-07-28:
- added dynamic import
- added Promise.allSettled
- added String.prototype.matchAll
- added Object.fromEntries
- reduced number of ticks in await
- added BigInt support in Atomics
- exported JS_NewPromiseCapability()
- misc async function and async generator fixes
- enabled hashbang support by default
2019-07-21:
- updated test262 tests
- updated to Unicode version 12.1.0
- fixed missing Date object in qjsc
- fixed multi-context creation
- misc ES2020 related fixes
- simplified power and division operators in bignum extension
- fixed several crash conditions
2019-07-09:
- first public release

22
third_party/quickjs/LICENSE vendored Normal file
View file

@ -0,0 +1,22 @@
QuickJS Javascript Engine
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

7
third_party/quickjs/README.cosmo vendored Normal file
View file

@ -0,0 +1,7 @@
Source:
- https://bellard.org/quickjs/quickjs-2021-03-27.tar.xz
Local Changes:
- Replace snprintf with xasprintf in find_unique_cname
- Squash uninitialized read of harnessbuf in run-test262.c
- Change run-test262.c to not rebase configured paths

70
third_party/quickjs/TODO vendored Normal file
View file

@ -0,0 +1,70 @@
Bugs:
- modules: better error handling with cyclic module references
Misc ideas:
- use custom printf to avoid compatibility issues with floating point numbers
- consistent naming for preprocessor defines
- unify coding style and naming conventions
- use names from the ECMA spec in library implementation
- use byte code emitters with typed arguments (for clarity)
- use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing
and use the same wrappers in all phases
- use more generic method for line numbers in resolve_variables and resolve_labels
- use custom timezone support to avoid C library compatibility issues
Memory:
- use memory pools for objects, etc?
- test border cases for max number of atoms, object properties, string length
- add emergency malloc mode for out of memory exceptions.
- test all DynBuf memory errors
- test all js_realloc memory errors
- improve JS_ComputeMemoryUsage() with more info
Built-in standard library:
- BSD sockets
- modules: use realpath in module name normalizer and put it in quickjs-libc
- modules: if no ".", use a well known module loading path ?
- get rid of __loadScript, use more common name
REPL:
- debugger
- readline: support MS Windows terminal
- readline: handle dynamic terminal resizing
- readline: handle double width unicode characters
- multiline editing
- runtime object and function inspectors
- interactive object browser
- use more generic approach to display evaluation results
- improve directive handling: dispatch, colorize, completion...
- save history
- close all predefined methods in repl.js and jscalc.js
Optimization ideas:
- 64-bit atoms in 64-bit mode ?
- 64-bit small bigint in 64-bit mode ?
- reuse stack slots for disjoint scopes, if strip
- add heuristic to avoid some cycles in closures
- small String (0-2 charcodes) with immediate storage
- perform static string concatenation at compile time
- optimize string concatenation with ropes or miniropes?
- add implicit numeric strings for Uint32 numbers?
- optimize `s += a + b`, `s += a.b` and similar simple expressions
- ensure string canonical representation and optimise comparisons and hashes?
- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references
- property access optimization on the global object, functions,
prototypes and special non extensible objects.
- create object literals with the correct length by backpatching length argument
- remove redundant set_loc_uninitialized/check_uninitialized opcodes
- peephole optim: push_atom_value, to_propkey -> push_atom_value
- peephole optim: put_loc x, get_loc_check x -> set_loc x
- convert slow array to fast array when all properties != length are numeric
- optimize destructuring assignments for global and local variables
- implement some form of tail-call-optimization
- optimize OP_apply
- optimize f(...b)
Test262o: 0/11262 errors, 463 excluded
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
Result: 35/75280 errors, 909 excluded, 585 skipped
Test262 commit: 31126581e7290f9233c29cefd93f66c6ac78f1c9

1
third_party/quickjs/VERSION vendored Normal file
View file

@ -0,0 +1 @@
2021-03-27

637
third_party/quickjs/cutils.c vendored Normal file
View file

@ -0,0 +1,637 @@
/*
* C utilities
*
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "libc/fmt/fmt.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "third_party/quickjs/cutils.h"
asm(".ident\t\"\\n\\n\
QuickJS (MIT License)\\n\
Copyright (c) 2017-2021 Fabrice Bellard\\n\
Copyright (c) 2017-2021 Charlie Gordon\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
void pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
char *q = buf;
if (buf_size <= 0)
return;
for(;;) {
c = *str++;
if (c == 0 || q >= buf + buf_size - 1)
break;
*q++ = c;
}
*q = '\0';
}
/* strcat and truncate. */
char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
int strstart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
q = val;
while (*q != '\0') {
if (*p != *q)
return 0;
p++;
q++;
}
if (ptr)
*ptr = p;
return 1;
}
int has_suffix(const char *str, const char *suffix)
{
size_t len = strlen(str);
size_t slen = strlen(suffix);
return (len >= slen && !memcmp(str + len - slen, suffix, slen));
}
/* Dynamic buffer package */
static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
{
return realloc(ptr, size);
}
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
{
memset(s, 0, sizeof(*s));
if (!realloc_func)
realloc_func = dbuf_default_realloc;
s->opaque = opaque;
s->realloc_func = realloc_func;
}
void dbuf_init(DynBuf *s)
{
dbuf_init2(s, NULL, NULL);
}
/* return < 0 if error */
int dbuf_realloc(DynBuf *s, size_t new_size)
{
size_t size;
uint8_t *new_buf;
if (new_size > s->allocated_size) {
if (s->error)
return -1;
size = s->allocated_size * 3 / 2;
if (size > new_size)
new_size = size;
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
if (!new_buf) {
s->error = TRUE;
return -1;
}
s->buf = new_buf;
s->allocated_size = new_size;
}
return 0;
}
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
{
size_t end;
end = offset + len;
if (dbuf_realloc(s, end))
return -1;
memcpy(s->buf + offset, data, len);
if (end > s->size)
s->size = end;
return 0;
}
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
memcpy(s->buf + s->size, data, len);
s->size += len;
return 0;
}
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
memcpy(s->buf + s->size, s->buf + offset, len);
s->size += len;
return 0;
}
int dbuf_putc(DynBuf *s, uint8_t c)
{
return dbuf_put(s, &c, 1);
}
int dbuf_putstr(DynBuf *s, const char *str)
{
return dbuf_put(s, (const uint8_t *)str, strlen(str));
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...)
{
va_list ap;
char buf[128];
int len;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
if (len < sizeof(buf)) {
/* fast case */
return dbuf_put(s, (uint8_t *)buf, len);
} else {
if (dbuf_realloc(s, s->size + len + 1))
return -1;
va_start(ap, fmt);
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
fmt, ap);
va_end(ap);
s->size += len;
}
return 0;
}
void dbuf_free(DynBuf *s)
{
/* we test s->buf as a fail safe to avoid crashing if dbuf_free()
is called twice */
if (s->buf) {
s->realloc_func(s->opaque, s->buf, 0);
}
memset(s, 0, sizeof(*s));
}
/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
are output. */
int unicode_to_utf8(uint8_t *buf, unsigned int c)
{
uint8_t *q = buf;
if (c < 0x80) {
*q++ = c;
} else {
if (c < 0x800) {
*q++ = (c >> 6) | 0xc0;
} else {
if (c < 0x10000) {
*q++ = (c >> 12) | 0xe0;
} else {
if (c < 0x00200000) {
*q++ = (c >> 18) | 0xf0;
} else {
if (c < 0x04000000) {
*q++ = (c >> 24) | 0xf8;
} else if (c < 0x80000000) {
*q++ = (c >> 30) | 0xfc;
*q++ = ((c >> 24) & 0x3f) | 0x80;
} else {
return 0;
}
*q++ = ((c >> 18) & 0x3f) | 0x80;
}
*q++ = ((c >> 12) & 0x3f) | 0x80;
}
*q++ = ((c >> 6) & 0x3f) | 0x80;
}
*q++ = (c & 0x3f) | 0x80;
}
return q - buf;
}
static const unsigned int utf8_min_code[5] = {
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
};
static const unsigned char utf8_first_code_mask[5] = {
0x1f, 0xf, 0x7, 0x3, 0x1,
};
/* return -1 if error. *pp is not updated in this case. max_len must
be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
{
int l, c, b, i;
c = *p++;
if (c < 0x80) {
*pp = p;
return c;
}
switch(c) {
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
l = 1;
break;
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
case 0xec: case 0xed: case 0xee: case 0xef:
l = 2;
break;
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
l = 3;
break;
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
l = 4;
break;
case 0xfc: case 0xfd:
l = 5;
break;
default:
return -1;
}
/* check that we have enough characters */
if (l > (max_len - 1))
return -1;
c &= utf8_first_code_mask[l - 1];
for(i = 0; i < l; i++) {
b = *p++;
if (b < 0x80 || b >= 0xc0)
return -1;
c = (c << 6) | (b & 0x3f);
}
if (c < utf8_min_code[l - 1])
return -1;
*pp = p;
return c;
}
#if 0
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
static void *rqsort_arg;
static int (*rqsort_cmp)(const void *, const void *, void *);
static int rqsort_cmp2(const void *p1, const void *p2)
{
return rqsort_cmp(p1, p2, rqsort_arg);
}
/* not reentrant, but not needed with emscripten */
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg)
{
rqsort_arg = arg;
rqsort_cmp = cmp;
qsort(base, nmemb, size, rqsort_cmp2);
}
#endif
#else
typedef void (*exchange_f)(void *a, void *b, size_t size);
typedef int (*cmp_f)(const void *, const void *, void *opaque);
static void exchange_bytes(void *a, void *b, size_t size) {
uint8_t *ap = (uint8_t *)a;
uint8_t *bp = (uint8_t *)b;
while (size-- != 0) {
uint8_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_byte(void *a, void *b, size_t size) {
uint8_t *ap = (uint8_t *)a;
uint8_t *bp = (uint8_t *)b;
uint8_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int16s(void *a, void *b, size_t size) {
uint16_t *ap = (uint16_t *)a;
uint16_t *bp = (uint16_t *)b;
for (size /= sizeof(uint16_t); size-- != 0;) {
uint16_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int16(void *a, void *b, size_t size) {
uint16_t *ap = (uint16_t *)a;
uint16_t *bp = (uint16_t *)b;
uint16_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int32s(void *a, void *b, size_t size) {
uint32_t *ap = (uint32_t *)a;
uint32_t *bp = (uint32_t *)b;
for (size /= sizeof(uint32_t); size-- != 0;) {
uint32_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int32(void *a, void *b, size_t size) {
uint32_t *ap = (uint32_t *)a;
uint32_t *bp = (uint32_t *)b;
uint32_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int64s(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
for (size /= sizeof(uint64_t); size-- != 0;) {
uint64_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int64(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
uint64_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int128s(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
uint64_t t = ap[0];
uint64_t u = ap[1];
ap[0] = bp[0];
ap[1] = bp[1];
bp[0] = t;
bp[1] = u;
}
}
static void exchange_one_int128(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
uint64_t t = ap[0];
uint64_t u = ap[1];
ap[0] = bp[0];
ap[1] = bp[1];
bp[0] = t;
bp[1] = u;
}
static inline exchange_f exchange_func(const void *base, size_t size) {
switch (((uintptr_t)base | (uintptr_t)size) & 15) {
case 0:
if (size == sizeof(uint64_t) * 2)
return exchange_one_int128;
else
return exchange_int128s;
case 8:
if (size == sizeof(uint64_t))
return exchange_one_int64;
else
return exchange_int64s;
case 4:
case 12:
if (size == sizeof(uint32_t))
return exchange_one_int32;
else
return exchange_int32s;
case 2:
case 6:
case 10:
case 14:
if (size == sizeof(uint16_t))
return exchange_one_int16;
else
return exchange_int16s;
default:
if (size == 1)
return exchange_one_byte;
else
return exchange_bytes;
}
}
static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
uint8_t *basep = (uint8_t *)base;
size_t i, n, c, r;
exchange_f swap = exchange_func(base, size);
if (nmemb > 1) {
i = (nmemb / 2) * size;
n = nmemb * size;
while (i > 0) {
i -= size;
for (r = i; (c = r * 2 + size) < n; r = c) {
if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
c += size;
if (cmp(basep + r, basep + c, opaque) > 0)
break;
swap(basep + r, basep + c, size);
}
}
for (i = n - size; i > 0; i -= size) {
swap(basep, basep + i, size);
for (r = 0; (c = r * 2 + size) < i; r = c) {
if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
c += size;
if (cmp(basep + r, basep + c, opaque) > 0)
break;
swap(basep + r, basep + c, size);
}
}
}
}
static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
{
return cmp(a, b, opaque) < 0 ?
(cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
(cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
}
/* pointer based version with local stack and insertion sort threshhold */
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
size_t m4, i, lt, gt, span, span2;
int c, depth;
exchange_f swap = exchange_func(base, size);
exchange_f swap_block = exchange_func(base, size | 128);
if (nmemb < 2 || size <= 0)
return;
sp->base = (uint8_t *)base;
sp->count = nmemb;
sp->depth = 0;
sp++;
while (sp > stack) {
sp--;
ptr = sp->base;
nmemb = sp->count;
depth = sp->depth;
while (nmemb > 6) {
if (++depth > 50) {
/* depth check to ensure worst case logarithmic time */
heapsortx(ptr, nmemb, size, cmp, opaque);
nmemb = 0;
break;
}
/* select median of 3 from 1/4, 1/2, 3/4 positions */
/* should use median of 5 or 9? */
m4 = (nmemb >> 2) * size;
m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
swap(ptr, m, size); /* move the pivot to the start or the array */
i = lt = 1;
pi = plt = ptr + size;
gt = nmemb;
pj = pgt = top = ptr + nmemb * size;
for (;;) {
while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
if (c == 0) {
swap(plt, pi, size);
lt++;
plt += size;
}
i++;
pi += size;
}
while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
if (c == 0) {
gt--;
pgt -= size;
swap(pgt, pj, size);
}
}
if (pi >= pj)
break;
swap(pi, pj, size);
i++;
pi += size;
}
/* array has 4 parts:
* from 0 to lt excluded: elements identical to pivot
* from lt to pi excluded: elements smaller than pivot
* from pi to gt excluded: elements greater than pivot
* from gt to n excluded: elements identical to pivot
*/
/* move elements identical to pivot in the middle of the array: */
/* swap values in ranges [0..lt[ and [i-lt..i[
swapping the smallest span between lt and i-lt is sufficient
*/
span = plt - ptr;
span2 = pi - plt;
lt = i - lt;
if (span > span2)
span = span2;
swap_block(ptr, pi - span, span);
/* swap values in ranges [gt..top[ and [i..top-(top-gt)[
swapping the smallest span between top-gt and gt-i is sufficient
*/
span = top - pgt;
span2 = pgt - pi;
pgt = top - span2;
gt = nmemb - (gt - i);
if (span > span2)
span = span2;
swap_block(pi, top - span, span);
/* now array has 3 parts:
* from 0 to lt excluded: elements smaller than pivot
* from lt to gt excluded: elements identical to pivot
* from gt to n excluded: elements greater than pivot
*/
/* stack the larger segment and keep processing the smaller one
to minimize stack use for pathological distributions */
if (lt > nmemb - gt) {
sp->base = ptr;
sp->count = lt;
sp->depth = depth;
sp++;
ptr = pgt;
nmemb -= gt;
} else {
sp->base = pgt;
sp->count = nmemb - gt;
sp->depth = depth;
sp++;
nmemb = lt;
}
}
/* Use insertion sort for small fragments */
for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
swap(pj, pj - size, size);
}
}
}
#endif

276
third_party/quickjs/cutils.h vendored Normal file
View file

@ -0,0 +1,276 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_QUICKJS_CUTILS_H_
#define COSMOPOLITAN_THIRD_PARTY_QUICKJS_CUTILS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
/* set if CPU is big endian */
#undef WORDS_BIGENDIAN
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline forceinline
#define no_inline noinline
#define __maybe_unused __attribute__((__unused__))
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#endif
typedef int BOOL;
#ifndef FALSE
enum {
FALSE = 0,
TRUE = 1,
};
#endif
void pstrcpy(char *buf, int buf_size, const char *str);
char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int has_suffix(const char *str, const char *suffix);
static inline int max_int(int a, int b)
{
if (a > b)
return a;
else
return b;
}
static inline int min_int(int a, int b)
{
if (a < b)
return a;
else
return b;
}
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
{
if (a > b)
return a;
else
return b;
}
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
{
if (a < b)
return a;
else
return b;
}
static inline int64_t max_int64(int64_t a, int64_t b)
{
if (a > b)
return a;
else
return b;
}
static inline int64_t min_int64(int64_t a, int64_t b)
{
if (a < b)
return a;
else
return b;
}
/* WARNING: undefined if a = 0 */
forceinline int clz32(unsigned int a)
{
return __builtin_clz(a);
}
/* WARNING: undefined if a = 0 */
forceinline int clz64(uint64_t a)
{
return __builtin_clzll(a);
}
/* WARNING: undefined if a = 0 */
forceinline int ctz32(unsigned int a)
{
return __builtin_ctz(a);
}
/* WARNING: undefined if a = 0 */
forceinline int ctz64(uint64_t a)
{
return __builtin_ctzll(a);
}
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
struct __attribute__((packed)) packed_u32 {
uint32_t v;
};
struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
static inline uint64_t get_u64(const uint8_t *tab)
{
return ((const struct packed_u64 *)tab)->v;
}
static inline int64_t get_i64(const uint8_t *tab)
{
return (int64_t)((const struct packed_u64 *)tab)->v;
}
static inline void put_u64(uint8_t *tab, uint64_t val)
{
((struct packed_u64 *)tab)->v = val;
}
static inline uint32_t get_u32(const uint8_t *tab)
{
return ((const struct packed_u32 *)tab)->v;
}
static inline int32_t get_i32(const uint8_t *tab)
{
return (int32_t)((const struct packed_u32 *)tab)->v;
}
static inline void put_u32(uint8_t *tab, uint32_t val)
{
((struct packed_u32 *)tab)->v = val;
}
static inline uint32_t get_u16(const uint8_t *tab)
{
return ((const struct packed_u16 *)tab)->v;
}
static inline int32_t get_i16(const uint8_t *tab)
{
return (int16_t)((const struct packed_u16 *)tab)->v;
}
static inline void put_u16(uint8_t *tab, uint16_t val)
{
((struct packed_u16 *)tab)->v = val;
}
static inline uint32_t get_u8(const uint8_t *tab)
{
return *tab;
}
static inline int32_t get_i8(const uint8_t *tab)
{
return (int8_t)*tab;
}
static inline void put_u8(uint8_t *tab, uint8_t val)
{
*tab = val;
}
forceinline uint16_t bswap16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
forceinline uint32_t bswap32(uint32_t v)
{
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
}
forceinline uint64_t bswap64(uint64_t v)
{
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
typedef struct DynBuf {
uint8_t *buf;
size_t size;
size_t allocated_size;
BOOL error; /* true if a memory allocation error occurred */
DynBufReallocFunc *realloc_func;
void *opaque; /* for realloc_func */
} DynBuf;
void dbuf_init(DynBuf *s);
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
int dbuf_realloc(DynBuf *s, size_t new_size);
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
int dbuf_putc(DynBuf *s, uint8_t c);
int dbuf_putstr(DynBuf *s, const char *str);
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
{
return dbuf_put(s, (uint8_t *)&val, 2);
}
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
{
return dbuf_put(s, (uint8_t *)&val, 4);
}
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
{
return dbuf_put(s, (uint8_t *)&val, 8);
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...);
void dbuf_free(DynBuf *s);
static inline BOOL dbuf_error(DynBuf *s) {
return s->error;
}
static inline void dbuf_set_error(DynBuf *s)
{
s->error = TRUE;
}
#define UTF8_CHAR_LEN_MAX 6
int unicode_to_utf8(uint8_t *buf, unsigned int c);
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
static inline int from_hex(int c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else
return -1;
}
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg);
/* clang-format on */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_QUICKJS_CUTILS_H_ */

734
third_party/quickjs/doc/jsbignum.html vendored Normal file
View file

@ -0,0 +1,734 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Created by GNU Texinfo 6.1, http://www.gnu.org/software/texinfo/ -->
<head>
<title>Javascript Bignum Extensions</title>
<meta name="description" content="Javascript Bignum Extensions">
<meta name="keywords" content="Javascript Bignum Extensions">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="#SEC_Contents" rel="contents" title="Table of Contents">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
blockquote.indentedblock {margin-right: 0em}
blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
blockquote.smallquotation {font-size: smaller}
div.display {margin-left: 3.2em}
div.example {margin-left: 3.2em}
div.lisp {margin-left: 3.2em}
div.smalldisplay {margin-left: 3.2em}
div.smallexample {margin-left: 3.2em}
div.smalllisp {margin-left: 3.2em}
kbd {font-style: oblique}
pre.display {font-family: inherit}
pre.format {font-family: inherit}
pre.menu-comment {font-family: serif}
pre.menu-preformatted {font-family: serif}
pre.smalldisplay {font-family: inherit; font-size: smaller}
pre.smallexample {font-size: smaller}
pre.smallformat {font-family: inherit; font-size: smaller}
pre.smalllisp {font-size: smaller}
span.nolinebreak {white-space: nowrap}
span.roman {font-family: initial; font-weight: normal}
span.sansserif {font-family: sans-serif; font-weight: normal}
ul.no-bullet {list-style: none}
-->
</style>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body lang="en">
<h1 class="settitle" align="center">Javascript Bignum Extensions</h1>
<a name="SEC_Contents"></a>
<h2 class="contents-heading">Table of Contents</h2>
<div class="contents">
<ul class="no-bullet">
<li><a name="toc-Introduction" href="#Introduction">1 Introduction</a></li>
<li><a name="toc-Operator-overloading" href="#Operator-overloading">2 Operator overloading</a></li>
<li><a name="toc-BigInt-extensions" href="#BigInt-extensions">3 BigInt extensions</a></li>
<li><a name="toc-BigFloat" href="#BigFloat">4 BigFloat</a>
<ul class="no-bullet">
<li><a name="toc-Introduction-1" href="#Introduction-1">4.1 Introduction</a></li>
<li><a name="toc-Floating-point-rounding" href="#Floating-point-rounding">4.2 Floating point rounding</a></li>
<li><a name="toc-Operators" href="#Operators">4.3 Operators</a></li>
<li><a name="toc-BigFloat-literals" href="#BigFloat-literals">4.4 BigFloat literals</a></li>
<li><a name="toc-Builtin-Object-changes" href="#Builtin-Object-changes">4.5 Builtin Object changes</a>
<ul class="no-bullet">
<li><a name="toc-BigFloat-function" href="#BigFloat-function">4.5.1 <code>BigFloat</code> function</a></li>
<li><a name="toc-BigFloat_002eprototype" href="#BigFloat_002eprototype">4.5.2 <code>BigFloat.prototype</code></a></li>
<li><a name="toc-BigFloatEnv-constructor" href="#BigFloatEnv-constructor">4.5.3 <code>BigFloatEnv</code> constructor</a></li>
</ul></li>
</ul></li>
<li><a name="toc-BigDecimal" href="#BigDecimal">5 BigDecimal</a>
<ul class="no-bullet">
<li><a name="toc-Operators-1" href="#Operators-1">5.1 Operators</a></li>
<li><a name="toc-BigDecimal-literals" href="#BigDecimal-literals">5.2 BigDecimal literals</a></li>
<li><a name="toc-Builtin-Object-changes-1" href="#Builtin-Object-changes-1">5.3 Builtin Object changes</a>
<ul class="no-bullet">
<li><a name="toc-The-BigDecimal-function_002e" href="#The-BigDecimal-function_002e">5.3.1 The <code>BigDecimal</code> function.</a></li>
<li><a name="toc-Properties-of-the-BigDecimal-object" href="#Properties-of-the-BigDecimal-object">5.3.2 Properties of the <code>BigDecimal</code> object</a></li>
<li><a name="toc-Properties-of-the-BigDecimal_002eprototype-object" href="#Properties-of-the-BigDecimal_002eprototype-object">5.3.3 Properties of the <code>BigDecimal.prototype</code> object</a></li>
</ul></li>
</ul></li>
<li><a name="toc-Math-mode" href="#Math-mode">6 Math mode</a></li>
</ul>
</div>
<a name="Introduction"></a>
<h2 class="chapter">1 Introduction</h2>
<p>The Bignum extensions add the following features to the Javascript
language while being 100% backward compatible:
</p>
<ul>
<li> Operator overloading with a dispatch logic inspired from the proposal available at <a href="https://github.com/tc39/proposal-operator-overloading/">https://github.com/tc39/proposal-operator-overloading/</a>.
</li><li> Arbitrarily large floating point numbers (<code>BigFloat</code>) in base 2 using the IEEE 754 semantics.
</li><li> Arbitrarily large floating point numbers (<code>BigDecimal</code>) in base 10 based on the proposal available at
<a href="https://github.com/littledan/proposal-bigdecimal">https://github.com/littledan/proposal-bigdecimal</a>.
</li><li> <code>math</code> 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>%</code>) is defined as the Euclidian
remainder. <code>^</code> is an alias to the power operator
(<code>**</code>). <code>^^</code> is used as the exclusive or operator.
</li></ul>
<p>The extensions are independent from each other except the <code>math</code>
mode which relies on BigFloat and operator overloading.
</p>
<a name="Operator-overloading"></a>
<h2 class="chapter">2 Operator overloading</h2>
<p>Operator overloading is inspired from the proposal available at
<a href="https://github.com/tc39/proposal-operator-overloading/">https://github.com/tc39/proposal-operator-overloading/</a>. It
implements the same dispatch logic but finds the operator sets by
looking at the <code>Symbol.operatorSet</code> property in the objects. The
changes were done in order to simplify the implementation.
</p>
<p>More precisely, the following modifications were made:
</p>
<ul>
<li> <code>with operators from</code> is not supported. Operator overloading is always enabled.
</li><li> The dispatch is not based on a static <code>[[OperatorSet]]</code> field in all instances. Instead, a dynamic lookup of the <code>Symbol.operatorSet</code> property is done. This property is typically added in the prototype of each object.
</li><li> <code>Operators.create(...dictionaries)</code> is used to create a new OperatorSet object. The <code>Operators</code> function is supported as an helper to be closer to the TC39 proposal.
</li><li> <code>[]</code> cannot be overloaded.
</li><li> In math mode, the BigInt division and power operators can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li></ul>
<a name="BigInt-extensions"></a>
<h2 class="chapter">3 BigInt extensions</h2>
<p>A few properties are added to the BigInt object:
</p>
<dl compact="compact">
<dt><code>tdiv(a, b)</code></dt>
<dd><p>Return <em>trunc(a/b)</em>. <code>b = 0</code> raises a RangeError
exception.
</p>
</dd>
<dt><code>fdiv(a, b)</code></dt>
<dd><p>Return <em>\lfloor a/b \rfloor</em>. <code>b = 0</code> raises a RangeError
exception.
</p>
</dd>
<dt><code>cdiv(a, b)</code></dt>
<dd><p>Return <em>\lceil a/b \rceil</em>. <code>b = 0</code> raises a RangeError
exception.
</p>
</dd>
<dt><code>ediv(a, b)</code></dt>
<dd><p>Return <em>sgn(b) \lfloor a/{|b|} \rfloor</em> (Euclidian
division). <code>b = 0</code> raises a RangeError exception.
</p>
</dd>
<dt><code>tdivrem(a, b)</code></dt>
<dt><code>fdivrem(a, b)</code></dt>
<dt><code>cdivrem(a, b)</code></dt>
<dt><code>edivrem(a, b)</code></dt>
<dd><p>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.
</p>
</dd>
<dt><code>sqrt(a)</code></dt>
<dd><p>Return <em>\lfloor \sqrt(a) \rfloor</em>. A RangeError exception is
raised if <em>a &lt; 0</em>.
</p>
</dd>
<dt><code>sqrtrem(a)</code></dt>
<dd><p>Return an array of two elements. The first element is <em>\lfloor
\sqrt{a} \rfloor</em>. The second element is <em>a-\lfloor \sqrt{a}
\rfloor^2</em>. A RangeError exception is raised if <em>a &lt; 0</em>.
</p>
</dd>
<dt><code>floorLog2(a)</code></dt>
<dd><p>Return -1 if <em>a \leq 0</em> otherwise return <em>\lfloor \log2(a) \rfloor</em>.
</p>
</dd>
<dt><code>ctz(a)</code></dt>
<dd><p>Return the number of trailing zeros in the two&rsquo;s complement binary representation of a. Return -1 if <em>a=0</em>.
</p>
</dd>
</dl>
<a name="BigFloat"></a>
<h2 class="chapter">4 BigFloat</h2>
<a name="Introduction-1"></a>
<h3 class="section">4.1 Introduction</h3>
<p>This extension adds the <code>BigFloat</code> primitive type. The
<code>BigFloat</code> 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>, <code>+/-Infinity</code>, <code>+0</code> and <code>-0</code>
are supported. The mantissa and exponent can have any bit length with
an implementation specific minimum and maximum.
</p>
<a name="Floating-point-rounding"></a>
<h3 class="section">4.2 Floating point rounding</h3>
<p>Each floating point operation operates with infinite precision and
then rounds the result according to the specified floating point
environment (<code>BigFloatEnv</code> object). The status flags of the
environment are also set according to the result of the operation.
</p>
<p>If no floating point environment is provided, the global floating
point environment is used.
</p>
<p>The rounding mode of the global floating point environment is always
<code>RNDN</code> (&ldquo;round to nearest with ties to even&rdquo;)<a name="DOCF1" href="#FOOT1"><sup>1</sup></a>. The status flags of the global environment cannot be
read<a name="DOCF2" href="#FOOT2"><sup>2</sup></a>. The precision of the global environment is
<code>BigFloatEnv.prec</code>. The number of exponent bits of the global
environment is <code>BigFloatEnv.expBits</code>. The global environment
subnormal flag is set to <code>true</code>.
</p>
<p>For example, <code>prec = 53</code> and <code> expBits = 11</code> exactly give
the same precision as the IEEE 754 64 bit floating point format. The
default precision is <code>prec = 113</code> and <code> expBits = 15</code> (IEEE
754 128 bit floating point format).
</p>
<p>The global floating point environment can only be modified temporarily
when calling a function (see <code>BigFloatEnv.setPrec</code>). Hence a
function can change the global floating point environment for its
callees but not for its caller.
</p>
<a name="Operators"></a>
<h3 class="section">4.3 Operators</h3>
<p>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.
</p>
<p><code>typeof</code> applied on a <code>BigFloat</code> returns <code>bigfloat</code>.
</p>
<p>BigFloat can be compared with all the other numeric types and the
result follows the expected mathematical relations.
</p>
<p>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</code> is false).
</p>
<a name="BigFloat-literals"></a>
<h3 class="section">4.4 BigFloat literals</h3>
<p>BigFloat literals are floating point numbers with a trailing <code>l</code>
suffix. BigFloat literals have an infinite precision. They are rounded
according to the global floating point environment when they are
evaluated.<a name="DOCF3" href="#FOOT3"><sup>3</sup></a>
</p>
<a name="Builtin-Object-changes"></a>
<h3 class="section">4.5 Builtin Object changes</h3>
<a name="BigFloat-function"></a>
<h4 class="subsection">4.5.1 <code>BigFloat</code> function</h4>
<p>The <code>BigFloat</code> 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.
</p>
<p><code>BigFloat</code> properties:
</p>
<dl compact="compact">
<dt><code>LN2</code></dt>
<dt><code>PI</code></dt>
<dd><p>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.
</p>
</dd>
<dt><code>MIN_VALUE</code></dt>
<dt><code>MAX_VALUE</code></dt>
<dt><code>EPSILON</code></dt>
<dd><p>Getter. Return the minimum, maximum and epsilon <code>BigFloat</code> values
(same definition as the corresponding <code>Number</code> constants).
</p>
</dd>
<dt><code>fpRound(a[, e])</code></dt>
<dd><p>Round the floating point number <code>a</code> according to the floating
point environment <code>e</code> or the global environment if <code>e</code> is
undefined.
</p>
</dd>
<dt><code>parseFloat(a[, radix[, e]])</code></dt>
<dd><p>Parse the string <code>a</code> as a floating point number in radix
<code>radix</code>. 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</code>
or the global environment if <code>e</code> is undefined.
</p>
</dd>
<dt><code>isFinite(a)</code></dt>
<dd><p>Return true if <code>a</code> is a finite bigfloat.
</p>
</dd>
<dt><code>isNaN(a)</code></dt>
<dd><p>Return true if <code>a</code> is a NaN bigfloat.
</p>
</dd>
<dt><code>add(a, b[, e])</code></dt>
<dt><code>sub(a, b[, e])</code></dt>
<dt><code>mul(a, b[, e])</code></dt>
<dt><code>div(a, b[, e])</code></dt>
<dd><p>Perform the specified floating point operation and round the floating
point number <code>a</code> according to the floating point environment
<code>e</code> or the global environment if <code>e</code> is undefined. If
<code>e</code> is specified, the floating point status flags are updated.
</p>
</dd>
<dt><code>floor(x)</code></dt>
<dt><code>ceil(x)</code></dt>
<dt><code>round(x)</code></dt>
<dt><code>trunc(x)</code></dt>
<dd><p>Round to an integer. No additional rounding is performed.
</p>
</dd>
<dt><code>abs(x)</code></dt>
<dd><p>Return the absolute value of x. No additional rounding is performed.
</p>
</dd>
<dt><code>fmod(x, y[, e])</code></dt>
<dt><code>remainder(x, y[, e])</code></dt>
<dd><p>Floating point remainder. The quotient is truncated to zero (fmod) or
to the nearest integer with ties to even (remainder). <code>e</code> is an
optional floating point environment.
</p>
</dd>
<dt><code>sqrt(x[, e])</code></dt>
<dd><p>Square root. Return a rounded floating point number. <code>e</code> is an
optional floating point environment.
</p>
</dd>
<dt><code>sin(x[, e])</code></dt>
<dt><code>cos(x[, e])</code></dt>
<dt><code>tan(x[, e])</code></dt>
<dt><code>asin(x[, e])</code></dt>
<dt><code>acos(x[, e])</code></dt>
<dt><code>atan(x[, e])</code></dt>
<dt><code>atan2(x, y[, e])</code></dt>
<dt><code>exp(x[, e])</code></dt>
<dt><code>log(x[, e])</code></dt>
<dt><code>pow(x, y[, e])</code></dt>
<dd><p>Transcendental operations. Return a rounded floating point
number. <code>e</code> is an optional floating point environment.
</p>
</dd>
</dl>
<a name="BigFloat_002eprototype"></a>
<h4 class="subsection">4.5.2 <code>BigFloat.prototype</code></h4>
<p>The following properties are modified:
</p>
<dl compact="compact">
<dt><code>valueOf()</code></dt>
<dd><p>Return the bigfloat primitive value corresponding to <code>this</code>.
</p>
</dd>
<dt><code>toString(radix)</code></dt>
<dd>
<p>For floating point numbers:
</p>
<ul>
<li> If the radix is a power of two, the conversion is done with infinite
precision.
</li><li> 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.
</li></ul>
<p>The exponent letter is <code>e</code> for base 10, <code>p</code> for bases 2, 8,
16 with a binary exponent and <code>@</code> for the other bases.
</p>
</dd>
<dt><code>toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
<dt><code>toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
<dt><code>toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)</code></dt>
<dd><p>Same semantics as the corresponding <code>Number</code> functions with
BigFloats. There is no limit on the accepted precision <code>p</code>. The
rounding mode and radix can be optionally specified. The radix must be
between 2 and 36.
</p>
</dd>
</dl>
<a name="BigFloatEnv-constructor"></a>
<h4 class="subsection">4.5.3 <code>BigFloatEnv</code> constructor</h4>
<p>The <code>BigFloatEnv([p, [,rndMode]]</code> constructor cannot be invoked as a
function. The floating point environment contains:
</p>
<ul>
<li> the mantissa precision in bits
</li><li> the exponent size in bits assuming an IEEE 754 representation;
</li><li> the subnormal flag (if true, subnormal floating point numbers can
be generated by the floating point operations).
</li><li> the rounding mode
</li><li> 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()</code> or with the various status flag setters.
</li></ul>
<p><code>new BigFloatEnv([p, [,rndMode]]</code> 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</code>, the number of exponent bits is set to <code>expBitsMax</code> and the
subnormal flags is set to <code>false</code>. If <code>rndMode</code> is
<code>undefined</code>, the rounding mode is set to <code>RNDN</code>.
</p>
<p><code>BigFloatEnv</code> properties:
</p>
<dl compact="compact">
<dt><code>prec</code></dt>
<dd><p>Getter. Return the precision in bits of the global floating point
environment. The initial value is <code>113</code>.
</p>
</dd>
<dt><code>expBits</code></dt>
<dd><p>Getter. Return the exponent size in bits of the global floating point
environment assuming an IEEE 754 representation. The initial value is
<code>15</code>.
</p>
</dd>
<dt><code>setPrec(f, p[, e])</code></dt>
<dd><p>Set the precision of the global floating point environment to <code>p</code>
and the exponent size to <code>e</code> then call the function
<code>f</code>. Then the Float precision and exponent size are reset to
their precious value and the return value of <code>f</code> is returned (or
an exception is raised if <code>f</code> raised an exception). If <code>e</code>
is <code>undefined</code> it is set to <code>BigFloatEnv.expBitsMax</code>.
</p>
</dd>
<dt><code>precMin</code></dt>
<dd><p>Read-only integer. Return the minimum allowed precision. Must be at least 2.
</p>
</dd>
<dt><code>precMax</code></dt>
<dd><p>Read-only integer. Return the maximum allowed precision. Must be at least 113.
</p>
</dd>
<dt><code>expBitsMin</code></dt>
<dd><p>Read-only integer. Return the minimum allowed exponent size in
bits. Must be at least 3.
</p>
</dd>
<dt><code>expBitsMax</code></dt>
<dd><p>Read-only integer. Return the maximum allowed exponent size in
bits. Must be at least 15.
</p>
</dd>
<dt><code>RNDN</code></dt>
<dd><p>Read-only integer. Round to nearest, with ties to even rounding mode.
</p>
</dd>
<dt><code>RNDZ</code></dt>
<dd><p>Read-only integer. Round to zero rounding mode.
</p>
</dd>
<dt><code>RNDD</code></dt>
<dd><p>Read-only integer. Round to -Infinity rounding mode.
</p>
</dd>
<dt><code>RNDU</code></dt>
<dd><p>Read-only integer. Round to +Infinity rounding mode.
</p>
</dd>
<dt><code>RNDNA</code></dt>
<dd><p>Read-only integer. Round to nearest, with ties away from zero rounding mode.
</p>
</dd>
<dt><code>RNDA</code></dt>
<dd><p>Read-only integer. Round away from zero rounding mode.
</p>
</dd>
<dt><code>RNDF<a name="DOCF4" href="#FOOT4"><sup>4</sup></a></code></dt>
<dd><p>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.
</p>
</dd>
</dl>
<p><code>BigFloatEnv.prototype</code> properties:
</p>
<dl compact="compact">
<dt><code>prec</code></dt>
<dd><p>Getter and setter (Integer). Return or set the precision in bits.
</p>
</dd>
<dt><code>expBits</code></dt>
<dd><p>Getter and setter (Integer). Return or set the exponent size in bits
assuming an IEEE 754 representation.
</p>
</dd>
<dt><code>rndMode</code></dt>
<dd><p>Getter and setter (Integer). Return or set the rounding mode.
</p>
</dd>
<dt><code>subnormal</code></dt>
<dd><p>Getter and setter (Boolean). subnormal flag. It is false when
<code>expBits = expBitsMax</code>.
</p>
</dd>
<dt><code>clearStatus()</code></dt>
<dd><p>Clear the status flags.
</p>
</dd>
<dt><code>invalidOperation</code></dt>
<dt><code>divideByZero</code></dt>
<dt><code>overflow</code></dt>
<dt><code>underflow</code></dt>
<dt><code>inexact</code></dt>
<dd><p>Getter and setter (Boolean). Status flags.
</p>
</dd>
</dl>
<a name="BigDecimal"></a>
<h2 class="chapter">5 BigDecimal</h2>
<p>This extension adds the <code>BigDecimal</code> primitive type. The
<code>BigDecimal</code> type represents floating point numbers in base
10. It is inspired from the proposal available at
<a href="https://github.com/littledan/proposal-bigdecimal">https://github.com/littledan/proposal-bigdecimal</a>.
</p>
<p>The <code>BigDecimal</code> floating point numbers are always normalized and
finite. There is no concept of <code>-0</code>, <code>Infinity</code> or
<code>NaN</code>. By default, all the computations are done with infinite
precision.
</p>
<a name="Operators-1"></a>
<h3 class="section">5.1 Operators</h3>
<p>The following builtin operators support BigDecimal:
</p>
<dl compact="compact">
<dt><code>+</code></dt>
<dt><code>-</code></dt>
<dt><code>*</code></dt>
<dd><p>Both operands must be BigDecimal. The result is computed with infinite
precision.
</p></dd>
<dt><code>%</code></dt>
<dd><p>Both operands must be BigDecimal. The result is computed with infinite
precision. A range error is throws in case of division by zero.
</p>
</dd>
<dt><code>/</code></dt>
<dd><p>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</code> to specify the rounding).
</p>
</dd>
<dt><code>**</code></dt>
<dd><p>Both operands must be BigDecimal. The exponent must be a positive
integer. The result is computed with infinite precision.
</p>
</dd>
<dt><code>===</code></dt>
<dd><p>When one of the operand is a BigDecimal, return true if both operands
are a BigDecimal and if they are equal.
</p>
</dd>
<dt><code>==</code></dt>
<dt><code>!=</code></dt>
<dt><code>&lt;=</code></dt>
<dt><code>&gt;=</code></dt>
<dt><code>&lt;</code></dt>
<dt><code>&gt;</code></dt>
<dd>
<p>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.
</p>
</dd>
</dl>
<a name="BigDecimal-literals"></a>
<h3 class="section">5.2 BigDecimal literals</h3>
<p>BigDecimal literals are decimal floating point numbers with a trailing
<code>m</code> suffix.
</p>
<a name="Builtin-Object-changes-1"></a>
<h3 class="section">5.3 Builtin Object changes</h3>
<a name="The-BigDecimal-function_002e"></a>
<h4 class="subsection">5.3.1 The <code>BigDecimal</code> function.</h4>
<p>It returns <code>0m</code> 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.
</p>
<a name="Properties-of-the-BigDecimal-object"></a>
<h4 class="subsection">5.3.2 Properties of the <code>BigDecimal</code> object</h4>
<dl compact="compact">
<dt><code>add(a, b[, e])</code></dt>
<dt><code>sub(a, b[, e])</code></dt>
<dt><code>mul(a, b[, e])</code></dt>
<dt><code>div(a, b[, e])</code></dt>
<dt><code>mod(a, b[, e])</code></dt>
<dt><code>sqrt(a, e)</code></dt>
<dt><code>round(a, e)</code></dt>
<dd><p>Perform the specified floating point operation and round the floating
point result according to the rounding object <code>e</code>. If the
rounding object is not present, the operation is executed with
infinite precision.
</p>
<p>For <code>div</code>, a <code>RangeError</code> 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.
</p>
<p>For <code>sqrt</code>, a range error is thrown if <code>a</code> is less than
zero.
</p>
<p>The rounding object must contain the following properties:
<code>roundingMode</code> is a string specifying the rounding mode
(<code>&quot;floor&quot;</code>, <code>&quot;ceiling&quot;</code>, <code>&quot;down&quot;</code>, <code>&quot;up&quot;</code>,
<code>&quot;half-even&quot;</code>, <code>&quot;half-up&quot;</code>). Either
<code>maximumSignificantDigits</code> or <code>maximumFractionDigits</code> must
be present to specify respectively the number of significant digits
(must be &gt;= 1) or the number of digits after the decimal point (must
be &gt;= 0).
</p>
</dd>
</dl>
<a name="Properties-of-the-BigDecimal_002eprototype-object"></a>
<h4 class="subsection">5.3.3 Properties of the <code>BigDecimal.prototype</code> object</h4>
<dl compact="compact">
<dt><code>valueOf()</code></dt>
<dd><p>Return the bigdecimal primitive value corresponding to <code>this</code>.
</p>
</dd>
<dt><code>toString()</code></dt>
<dd><p>Convert <code>this</code> to a string with infinite precision in base 10.
</p>
</dd>
<dt><code>toPrecision(p, rnd_mode = &quot;half-up&quot;)</code></dt>
<dt><code>toFixed(p, rnd_mode = &quot;half-up&quot;)</code></dt>
<dt><code>toExponential(p, rnd_mode = &quot;half-up&quot;)</code></dt>
<dd><p>Convert the BigDecimal <code>this</code> to string with the specified
precision <code>p</code>. There is no limit on the accepted precision
<code>p</code>. The rounding mode can be optionally
specified. <code>toPrecision</code> outputs either in decimal fixed notation
or in decimal exponential notation with a <code>p</code> digits of
precision. <code>toExponential</code> outputs in decimal exponential
notation with <code>p</code> digits after the decimal point. <code>toFixed</code>
outputs in decimal notation with <code>p</code> digits after the decimal
point.
</p>
</dd>
</dl>
<a name="Math-mode"></a>
<h2 class="chapter">6 Math mode</h2>
<p>A new <em>math mode</em> is enabled with the <code>&quot;use math&quot;</code>
directive. It propagates the same way as the <em>strict mode</em>. 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.
</p>
<p>The following changes are made to the Javascript semantics:
</p>
<ul>
<li> Floating point literals (i.e. number with a decimal point or an exponent) are <code>BigFloat</code> by default (i.e. a <code>l</code> suffix is implied). Hence <code>typeof 1.0 === &quot;bigfloat&quot;</code>.
</li><li> Integer literals (i.e. numbers without a decimal point or an exponent) with or without the <code>n</code> suffix are <code>BigInt</code> 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</code>. Hence <code>typeof 1 === &quot;number &quot;</code>, <code>typeof 1n === &quot;number&quot;</code> but <code>typeof 9007199254740992 === &quot;bigint&quot; </code>.
</li><li> 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.
</li><li> 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.
</li><li> The <code>^</code> operator is an alias to the power operator (<code>**</code>).
</li><li> The power operator (both <code>^</code> and <code>**</code>) grammar is modified so that <code>-2^2</code> is allowed and yields <code>-4</code>.
</li><li> The logical xor operator is still available with the <code>^^</code> operator.
</li><li> The modulo operator (<code>%</code>) returns the Euclidian remainder (always positive) instead of the truncated remainder.
</li><li> The integer division operator can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li><li> The integer power operator with a non zero negative exponent can be overloaded with <code>Operators.updateBigIntOperators(dictionary)</code>.
</li></ul>
<div class="footnote">
<hr>
<h4 class="footnotes-heading">Footnotes</h4>
<h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
<p>The
rationale is that the rounding mode changes must always be
explicit.</p>
<h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
<p>The rationale is to avoid side effects for the built-in
operators.</p>
<h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
<p>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.</p>
<h3><a name="FOOT4" href="#DOCF4">(4)</a></h3>
<p>Could be removed in case a deterministic behavior for floating point operations is required.</p>
</div>
<hr>
</body>
</html>

BIN
third_party/quickjs/doc/jsbignum.pdf vendored Normal file

Binary file not shown.

589
third_party/quickjs/doc/jsbignum.texi vendored Normal file
View file

@ -0,0 +1,589 @@
\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

1383
third_party/quickjs/doc/quickjs.html vendored Normal file

File diff suppressed because it is too large Load diff

BIN
third_party/quickjs/doc/quickjs.pdf vendored Normal file

Binary file not shown.

1097
third_party/quickjs/doc/quickjs.texi vendored Normal file

File diff suppressed because it is too large Load diff

72
third_party/quickjs/examples/fib.c vendored Normal file
View file

@ -0,0 +1,72 @@
/*
* QuickJS: Example of C module
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "../quickjs.h"
#define countof(x) (sizeof(x) / sizeof((x)[0]))
static int fib(int n)
{
if (n <= 0)
return 0;
else if (n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
static JSValue js_fib(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int n, res;
if (JS_ToInt32(ctx, &n, argv[0]))
return JS_EXCEPTION;
res = fib(n);
return JS_NewInt32(ctx, res);
}
static const JSCFunctionListEntry js_fib_funcs[] = {
JS_CFUNC_DEF("fib", 1, js_fib ),
};
static int js_fib_init(JSContext *ctx, JSModuleDef *m)
{
return JS_SetModuleExportList(ctx, m, js_fib_funcs,
countof(js_fib_funcs));
}
#ifdef JS_SHARED_LIBRARY
#define JS_INIT_MODULE js_init_module
#else
#define JS_INIT_MODULE js_init_module_fib
#endif
JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_fib_init);
if (!m)
return NULL;
JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs));
return m;
}

View file

@ -0,0 +1,10 @@
/* fib module */
export function fib(n)
{
if (n <= 0)
return 0;
else if (n == 1)
return 1;
else
return fib(n - 1) + fib(n - 2);
}

1
third_party/quickjs/examples/hello.js vendored Normal file
View file

@ -0,0 +1 @@
console.log("Hello World");

View file

@ -0,0 +1,6 @@
/* example of JS module */
import { fib } from "./fib_module.js";
console.log("Hello World");
console.log("fib(10)=", fib(10));

View file

@ -0,0 +1,68 @@
/*
* 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"));
})();

View file

@ -0,0 +1,66 @@
/*
* PI computation in Javascript using the QuickJS bigfloat type
* (binary floating point)
*/
"use strict";
/* compute PI with a precision of 'prec' bits */
function calc_pi() {
const CHUD_A = 13591409n;
const CHUD_B = 545140134n;
const CHUD_C = 640320n;
const CHUD_C3 = 10939058860032000n; /* C^3/24 */
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(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;
if (a == (b - 1n)) {
G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n);
P = BigFloat(G * (CHUD_B * b + CHUD_A));
if (b & 1n)
P = -P;
G = BigFloat(G);
Q = BigFloat(b * b * b * 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 = 0l;
}
return [P, Q, G];
}
var n, P, Q, G;
/* number of serie terms */
n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n;
[P, Q, G] = chud_bs(0n, n, false);
Q = Q / (P + Q * BigFloat(CHUD_A));
G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C));
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];
} else {
n_digits = 1000;
}
n_bits = Math.ceil(n_digits * Math.log2(10));
/* we add more bits to reduce the probability of bad rounding for
the last digits */
BigFloatEnv.setPrec( () => {
r = calc_pi();
print(r.toFixed(n_digits, BigFloatEnv.RNDZ));
}, n_bits + 32);
})();

View file

@ -0,0 +1,118 @@
/*
* PI computation in Javascript using the BigInt type
*/
"use strict";
/* return floor(log2(a)) for a > 0 and 0 for a = 0 */
function floor_log2(a)
{
var k_max, a1, k, i;
k_max = 0n;
while ((a >> (2n ** k_max)) != 0n) {
k_max++;
}
k = 0n;
a1 = a;
for(i = k_max - 1n; i >= 0n; i--) {
a1 = a >> (2n ** i);
if (a1 != 0n) {
a = a1;
k |= (1n << i);
}
}
return k;
}
/* return ceil(log2(a)) for a > 0 */
function ceil_log2(a)
{
return floor_log2(a - 1n) + 1n;
}
/* return floor(sqrt(a)) (not efficient but simple) */
function int_sqrt(a)
{
var l, u, s;
if (a == 0n)
return a;
l = ceil_log2(a);
u = 1n << ((l + 1n) / 2n);
/* u >= floor(sqrt(a)) */
for(;;) {
s = u;
u = ((a / s) + s) / 2n;
if (u >= s)
break;
}
return s;
}
/* return pi * 2**prec */
function calc_pi(prec) {
const CHUD_A = 13591409n;
const CHUD_B = 545140134n;
const CHUD_C = 640320n;
const CHUD_C3 = 10939058860032000n; /* C^3/24 */
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(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;
if (a == (b - 1n)) {
G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n);
P = G * (CHUD_B * b + CHUD_A);
if (b & 1n)
P = -P;
Q = b * b * b * 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 = 0n;
}
return [P, Q, G];
}
var n, P, Q, G;
/* number of serie terms */
n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n;
[P, Q, G] = chud_bs(0n, n, false);
Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A);
G = int_sqrt(CHUD_C << (2n * prec));
return (Q * G) >> prec;
}
function main(args) {
var r, n_digits, n_bits, out;
if (args.length < 1) {
print("usage: pi n_digits");
return;
}
n_digits = args[0] | 0;
/* we add more bits to reduce the probability of bad rounding for
the last digits */
n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n;
r = calc_pi(n_bits);
r = ((10n ** BigInt(n_digits)) * r) >> n_bits;
out = r.toString();
print(out[0] + "." + out.slice(1));
}
var args;
if (typeof scriptArgs != "undefined") {
args = scriptArgs;
args.shift();
} else if (typeof arguments != "undefined") {
args = arguments;
} else {
/* default: 1000 digits */
args=[1000];
}
main(args);

151
third_party/quickjs/examples/point.c vendored Normal file
View file

@ -0,0 +1,151 @@
/*
* QuickJS: Example of C module with a class
*
* Copyright (c) 2019 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "../quickjs.h"
#include <math.h>
#define countof(x) (sizeof(x) / sizeof((x)[0]))
/* Point Class */
typedef struct {
int x;
int y;
} JSPointData;
static JSClassID js_point_class_id;
static void js_point_finalizer(JSRuntime *rt, JSValue val)
{
JSPointData *s = JS_GetOpaque(val, js_point_class_id);
/* Note: 's' can be NULL in case JS_SetOpaque() was not called */
js_free_rt(rt, s);
}
static JSValue js_point_ctor(JSContext *ctx,
JSValueConst new_target,
int argc, JSValueConst *argv)
{
JSPointData *s;
JSValue obj = JS_UNDEFINED;
JSValue proto;
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &s->x, argv[0]))
goto fail;
if (JS_ToInt32(ctx, &s->y, argv[1]))
goto fail;
/* using new_target to get the prototype is necessary when the
class is extended. */
proto = JS_GetPropertyStr(ctx, new_target, "prototype");
if (JS_IsException(proto))
goto fail;
obj = JS_NewObjectProtoClass(ctx, proto, js_point_class_id);
JS_FreeValue(ctx, proto);
if (JS_IsException(obj))
goto fail;
JS_SetOpaque(obj, s);
return obj;
fail:
js_free(ctx, s);
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
if (!s)
return JS_EXCEPTION;
if (magic == 0)
return JS_NewInt32(ctx, s->x);
else
return JS_NewInt32(ctx, s->y);
}
static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
int v;
if (!s)
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &v, val))
return JS_EXCEPTION;
if (magic == 0)
s->x = v;
else
s->y = v;
return JS_UNDEFINED;
}
static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
if (!s)
return JS_EXCEPTION;
return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y));
}
static JSClassDef js_point_class = {
"Point",
.finalizer = js_point_finalizer,
};
static const JSCFunctionListEntry js_point_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0),
JS_CGETSET_MAGIC_DEF("y", js_point_get_xy, js_point_set_xy, 1),
JS_CFUNC_DEF("norm", 0, js_point_norm),
};
static int js_point_init(JSContext *ctx, JSModuleDef *m)
{
JSValue point_proto, point_class;
/* create the Point class */
JS_NewClassID(&js_point_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class);
point_proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs));
point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0);
/* set proto.constructor and ctor.prototype */
JS_SetConstructor(ctx, point_class, point_proto);
JS_SetClassProto(ctx, js_point_class_id, point_proto);
JS_SetModuleExport(ctx, m, "Point", point_class);
return 0;
}
JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_point_init);
if (!m)
return NULL;
JS_AddModuleExport(ctx, m, "Point");
return m;
}

View file

@ -0,0 +1,6 @@
/* example of JS module importing a C module */
import { fib } from "./fib.so";
console.log("Hello World");
console.log("fib(10)=", fib(10));

View file

@ -0,0 +1,40 @@
/* example of JS module importing a C module */
import { Point } from "./point.so";
function assert(b, str)
{
if (b) {
return;
} else {
throw Error("assertion failed: " + str);
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
get_color() {
return this.color;
}
};
function main()
{
var pt, pt2;
pt = new Point(2, 3);
assert(pt.x === 2);
assert(pt.y === 3);
pt.x = 4;
assert(pt.x === 4);
assert(pt.norm() == 5);
pt2 = new ColorPoint(2, 3, 0xffffff);
assert(pt2.x === 2);
assert(pt2.color === 0xffffff);
assert(pt2.get_color() === 0xffffff);
}
main();

8472
third_party/quickjs/libbf.c vendored Normal file

File diff suppressed because it is too large Load diff

517
third_party/quickjs/libbf.h vendored Normal file
View file

@ -0,0 +1,517 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_QUICKJS_LIBBF_H_
#define COSMOPOLITAN_THIRD_PARTY_QUICKJS_LIBBF_H_
#include "libc/limits.h"
#include "libc/literal.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
#if INTPTR_MAX >= INT64_MAX
#define LIMB_LOG2_BITS 6
#else
#define LIMB_LOG2_BITS 5
#endif
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
#if LIMB_BITS == 64
typedef __int128 int128_t;
typedef unsigned __int128 uint128_t;
typedef int64_t slimb_t;
typedef uint64_t limb_t;
typedef uint128_t dlimb_t;
#define BF_RAW_EXP_MIN INT64_MIN
#define BF_RAW_EXP_MAX INT64_MAX
#define LIMB_DIGITS 19
#define BF_DEC_BASE UINT64_C(10000000000000000000)
#else
typedef int32_t slimb_t;
typedef uint32_t limb_t;
typedef uint64_t dlimb_t;
#define BF_RAW_EXP_MIN INT32_MIN
#define BF_RAW_EXP_MAX INT32_MAX
#define LIMB_DIGITS 9
#define BF_DEC_BASE 1000000000U
#endif
/* in bits */
/* minimum number of bits for the exponent */
#define BF_EXP_BITS_MIN 3
/* maximum number of bits for the exponent */
#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
/* extended range for exponent, used internally */
#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
/* minimum possible precision */
#define BF_PREC_MIN 2
/* minimum possible precision */
#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
/* some operations support infinite precision */
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
#if LIMB_BITS == 64
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
#else
#define BF_CHKSUM_MOD 975620677U
#endif
#define BF_EXP_ZERO BF_RAW_EXP_MIN
#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
#define BF_EXP_NAN BF_RAW_EXP_MAX
/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
+/-infinity is represented with expn = BF_EXP_INF and len = 0,
NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
*/
typedef struct {
struct bf_context_t *ctx;
int sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bf_t;
typedef struct {
/* must be kept identical to bf_t */
struct bf_context_t *ctx;
int sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bfdec_t;
typedef enum {
BF_RNDN, /* round to nearest, ties to even */
BF_RNDZ, /* round to zero */
BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
BF_RNDU, /* round to +inf */
BF_RNDNA, /* round to nearest, ties away from zero */
BF_RNDA, /* round away from zero */
BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
inexact flag is always set) */
} bf_rnd_t;
/* allow subnormal numbers. Only available if the number of exponent
bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
#define BF_FLAG_SUBNORMAL (1 << 3)
/* 'prec' is the precision after the radix point instead of the whole
mantissa. Can only be used with bf_round() and
bfdec_[add|sub|mul|div|sqrt|round](). */
#define BF_FLAG_RADPNT_PREC (1 << 4)
#define BF_RND_MASK 0x7
#define BF_EXP_BITS_SHIFT 5
#define BF_EXP_BITS_MASK 0x3f
/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
/* contains the rounding mode and number of exponents bits */
typedef uint32_t bf_flags_t;
typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
typedef struct {
bf_t val;
limb_t prec;
} BFConstCache;
typedef struct bf_context_t {
void *realloc_opaque;
bf_realloc_func_t *realloc_func;
BFConstCache log2_cache;
BFConstCache pi_cache;
struct BFNTTState *ntt_state;
} bf_context_t;
static inline int bf_get_exp_bits(bf_flags_t flags)
{
int e;
e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
if (e == BF_EXP_BITS_MASK)
return BF_EXP_BITS_MAX + 1;
else
return BF_EXP_BITS_MAX - e;
}
static inline bf_flags_t bf_set_exp_bits(int n)
{
return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
}
/* returned status */
#define BF_ST_INVALID_OP (1 << 0)
#define BF_ST_DIVIDE_ZERO (1 << 1)
#define BF_ST_OVERFLOW (1 << 2)
#define BF_ST_UNDERFLOW (1 << 3)
#define BF_ST_INEXACT (1 << 4)
/* indicate that a memory allocation error occured. NaN is returned */
#define BF_ST_MEM_ERROR (1 << 5)
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
static inline slimb_t bf_max(slimb_t a, slimb_t b)
{
if (a > b)
return a;
else
return b;
}
static inline slimb_t bf_min(slimb_t a, slimb_t b)
{
if (a < b)
return a;
else
return b;
}
void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
void *realloc_opaque);
void bf_context_end(bf_context_t *s);
/* free memory allocated for the bf cache data */
void bf_clear_cache(bf_context_t *s);
static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
{
return s->realloc_func(s->realloc_opaque, ptr, size);
}
/* 'size' must be != 0 */
static inline void *bf_malloc(bf_context_t *s, size_t size)
{
return bf_realloc(s, NULL, size);
}
static inline void bf_free(bf_context_t *s, void *ptr)
{
/* must test ptr otherwise equivalent to malloc(0) */
if (ptr)
bf_realloc(s, ptr, 0);
}
void bf_init(bf_context_t *s, bf_t *r);
static inline void bf_delete(bf_t *r)
{
bf_context_t *s = r->ctx;
/* we accept to delete a zeroed bf_t structure */
if (s && r->tab) {
bf_realloc(s, r->tab, 0);
}
}
static inline void bf_neg(bf_t *r)
{
r->sign ^= 1;
}
static inline int bf_is_finite(const bf_t *a)
{
return (a->expn < BF_EXP_INF);
}
static inline int bf_is_nan(const bf_t *a)
{
return (a->expn == BF_EXP_NAN);
}
static inline int bf_is_zero(const bf_t *a)
{
return (a->expn == BF_EXP_ZERO);
}
static inline void bf_memcpy(bf_t *r, const bf_t *a)
{
*r = *a;
}
int bf_set_ui(bf_t *r, uint64_t a);
int bf_set_si(bf_t *r, int64_t a);
void bf_set_nan(bf_t *r);
void bf_set_zero(bf_t *r, int is_neg);
void bf_set_inf(bf_t *r, int is_neg);
int bf_set(bf_t *r, const bf_t *a);
void bf_move(bf_t *r, bf_t *a);
int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
int bf_set_float64(bf_t *a, double d);
int bf_cmpu(const bf_t *a, const bf_t *b);
int bf_cmp_full(const bf_t *a, const bf_t *b);
int bf_cmp(const bf_t *a, const bf_t *b);
static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) == 0;
}
static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) <= 0;
}
static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) < 0;
}
int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
#define BF_DIVREM_EUCLIDIAN BF_RNDF
int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
limb_t prec, bf_flags_t flags, int rnd_mode);
int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
/* round to integer with infinite precision */
int bf_rint(bf_t *r, int rnd_mode);
int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
slimb_t bf_get_exp_min(const bf_t *a);
int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
/* additional flags for bf_atof */
/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
#define BF_ATOF_NO_HEX (1 << 16)
/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
#define BF_ATOF_BIN_OCT (1 << 17)
/* Do not parse NaN or Inf */
#define BF_ATOF_NO_NAN_INF (1 << 18)
/* return the exponent separately */
#define BF_ATOF_EXPONENT (1 << 19)
int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags);
/* this version accepts prec = BF_PREC_INF and returns the radix
exponent */
int bf_atof2(bf_t *r, slimb_t *pexponent,
const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags);
int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
slimb_t expn, limb_t prec, bf_flags_t flags);
/* Conversion of floating point number to string. Return a null
terminated string or NULL if memory error. *plen contains its
length if plen != NULL. The exponent letter is "e" for base 10,
"p" for bases 2, 8, 16 with a binary exponent and "@" for the other
bases. */
#define BF_FTOA_FORMAT_MASK (3 << 16)
/* fixed format: prec significant digits rounded with (flags &
BF_RND_MASK). Exponential notation is used if too many zeros are
needed.*/
#define BF_FTOA_FORMAT_FIXED (0 << 16)
/* fractional format: prec digits after the decimal point rounded with
(flags & BF_RND_MASK) */
#define BF_FTOA_FORMAT_FRAC (1 << 16)
/* free format:
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
number of digits to represent 'a'. The precision and the rounding
mode are ignored.
For the non binary radices with bf_ftoa(): use as many digits as
necessary so that bf_atof() return the same number when using
precision 'prec', rounding to nearest and the subnormal
configuration of 'flags'. The result is meaningful only if 'a' is
already rounded to 'prec' bits. If the subnormal flag is set, the
exponent in 'flags' must also be set to the desired exponent range.
*/
#define BF_FTOA_FORMAT_FREE (2 << 16)
/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
(takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
binary radices with bf_ftoa() and for bfdec_ftoa(). */
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
/* force exponential notation for fixed or free format */
#define BF_FTOA_FORCE_EXP (1 << 20)
/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
base 2 if non zero value */
#define BF_FTOA_ADD_PREFIX (1 << 21)
/* return "Infinity" instead of "Inf" and add a "+" for positive
exponents */
#define BF_FTOA_JS_QUIRKS (1 << 22)
char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
bf_flags_t flags);
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
#define BF_GET_INT_MOD (1 << 0)
int bf_get_int32(int *pres, const bf_t *a, int flags);
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
int bf_get_uint64(uint64_t *pres, const bf_t *a);
/* the following functions are exported for testing only. */
void mp_print_str(const char *str, const limb_t *tab, limb_t n);
void bf_print_str(const char *str, const bf_t *a);
int bf_resize(bf_t *r, limb_t len);
int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
int is_ceil1);
int mp_mul(bf_context_t *s, limb_t *result,
const limb_t *op1, limb_t op1_size,
const limb_t *op2, limb_t op2_size);
limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
limb_t n, limb_t carry);
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
limb_t bf_isqrt(limb_t a);
/* transcendental functions */
int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
limb_t prec, bf_flags_t flags);
int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
/* decimal floating point */
static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
{
bf_init(s, (bf_t *)r);
}
static inline void bfdec_delete(bfdec_t *r)
{
bf_delete((bf_t *)r);
}
static inline void bfdec_neg(bfdec_t *r)
{
r->sign ^= 1;
}
static inline int bfdec_is_finite(const bfdec_t *a)
{
return (a->expn < BF_EXP_INF);
}
static inline int bfdec_is_nan(const bfdec_t *a)
{
return (a->expn == BF_EXP_NAN);
}
static inline int bfdec_is_zero(const bfdec_t *a)
{
return (a->expn == BF_EXP_ZERO);
}
static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
{
bf_memcpy((bf_t *)r, (const bf_t *)a);
}
int bfdec_set_ui(bfdec_t *r, uint64_t a);
int bfdec_set_si(bfdec_t *r, int64_t a);
static inline void bfdec_set_nan(bfdec_t *r)
{
bf_set_nan((bf_t *)r);
}
static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
{
bf_set_zero((bf_t *)r, is_neg);
}
static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
{
bf_set_inf((bf_t *)r, is_neg);
}
static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
{
return bf_set((bf_t *)r, (bf_t *)a);
}
static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
{
bf_move((bf_t *)r, (bf_t *)a);
}
static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmpu((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmp((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) == 0;
}
static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) <= 0;
}
static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) < 0;
}
int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
limb_t prec, bf_flags_t flags, int rnd_mode);
int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
int bfdec_rint(bfdec_t *r, int rnd_mode);
int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
int bfdec_get_int32(int *pres, const bfdec_t *a);
int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
limb_t prec, bf_flags_t flags);
/* the following functions are exported for testing only. */
extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
void bfdec_print_str(const char *str, const bfdec_t *a);
static inline int bfdec_resize(bfdec_t *r, limb_t len)
{
return bf_resize((bf_t *)r, len);
}
int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
/* clang-format on */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_QUICKJS_LIBBF_H_ */

View file

@ -0,0 +1,60 @@
/*
* Regular Expression Engine
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* clang-format off */
#ifdef DEF
DEF(invalid, 1) /* never used */
DEF(char, 3)
DEF(char32, 5)
DEF(dot, 1)
DEF(any, 1) /* same as dot but match any character including line terminator */
DEF(line_start, 1)
DEF(line_end, 1)
DEF(goto, 5)
DEF(split_goto_first, 5)
DEF(split_next_first, 5)
DEF(match, 1)
DEF(save_start, 2) /* save start position */
DEF(save_end, 2) /* save end position, must come after saved_start */
DEF(save_reset, 3) /* reset save positions */
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
DEF(push_i32, 5) /* push integer on the stack */
DEF(drop, 1)
DEF(word_boundary, 1)
DEF(not_word_boundary, 1)
DEF(back_reference, 2)
DEF(backward_back_reference, 2) /* must come after back_reference */
DEF(range, 3) /* variable length */
DEF(range32, 3) /* variable length */
DEF(lookahead, 5)
DEF(negative_lookahead, 5)
DEF(push_char_pos, 1) /* push the character position on the stack */
DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character
position */
DEF(prev, 1) /* go to the previous char */
DEF(simple_greedy_quant, 17)
#endif /* DEF */

2617
third_party/quickjs/libregexp.c vendored Normal file

File diff suppressed because it is too large Load diff

72
third_party/quickjs/libregexp.h vendored Normal file
View file

@ -0,0 +1,72 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_QUICKJS_LIBREGEXP_H_
#define COSMOPOLITAN_THIRD_PARTY_QUICKJS_LIBREGEXP_H_
#include "third_party/quickjs/libunicode.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
#define LRE_BOOL int /* for documentation purposes */
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
#define LRE_FLAG_MULTILINE (1 << 2)
#define LRE_FLAG_DOTALL (1 << 3)
#define LRE_FLAG_UTF16 (1 << 4)
#define LRE_FLAG_STICKY (1 << 5)
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
const char *buf, size_t buf_len, int re_flags,
void *opaque);
int lre_get_capture_count(const uint8_t *bc_buf);
int lre_get_flags(const uint8_t *bc_buf);
const char *lre_get_groupnames(const uint8_t *bc_buf);
int lre_exec(uint8_t **capture,
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
LRE_BOOL lre_is_space(int c);
/* must be provided by the user */
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
/* JS identifier test */
extern uint32_t const lre_id_start_table_ascii[4];
extern uint32_t const lre_id_continue_table_ascii[4];
static inline int lre_js_is_ident_first(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_start(c);
#else
return !lre_is_space(c);
#endif
}
}
static inline int lre_js_is_ident_next(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
/* ZWNJ and ZWJ are accepted in identifiers */
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
#else
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
#endif
}
}
#undef LRE_BOOL
/* clang-format on */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_QUICKJS_LIBREGEXP_H_ */

4367
third_party/quickjs/libunicode-table.inc vendored Normal file

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more