porffor 0.2.0-fdf0fc5 → 0.14.0-0ad2c8a7c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +12 -7
- package/README.md +18 -15
- package/asur/index.js +1 -1
- package/byg/index.js +3 -24
- package/compiler/2c.js +69 -55
- package/compiler/assemble.js +51 -11
- package/compiler/builtins/annexb_string.js +10 -10
- package/compiler/builtins/annexb_string.ts +4 -3
- package/compiler/builtins/array.ts +85 -9
- package/compiler/builtins/base64.ts +2 -1
- package/compiler/builtins/boolean.ts +2 -2
- package/compiler/builtins/console.ts +4 -0
- package/compiler/builtins/crypto.ts +2 -1
- package/compiler/builtins/date.ts +2 -3
- package/compiler/builtins/error.js +22 -0
- package/compiler/builtins/escape.ts +2 -3
- package/compiler/builtins/function.ts +1 -1
- package/compiler/builtins/int.ts +1 -1
- package/compiler/builtins/math.ts +410 -0
- package/compiler/builtins/number.ts +4 -7
- package/compiler/builtins/object.ts +1 -1
- package/compiler/builtins/porffor.d.ts +9 -8
- package/compiler/builtins/set.ts +197 -3
- package/compiler/builtins/string.ts +2 -1
- package/compiler/builtins/symbol.ts +62 -0
- package/compiler/builtins.js +30 -15
- package/compiler/codegen.js +641 -365
- package/compiler/decompile.js +7 -3
- package/compiler/embedding.js +2 -2
- package/compiler/encoding.js +0 -14
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +781 -187
- package/compiler/index.js +5 -11
- package/compiler/opt.js +7 -7
- package/compiler/parse.js +2 -4
- package/compiler/precompile.js +18 -25
- package/compiler/prefs.js +6 -2
- package/compiler/prototype.js +185 -162
- package/compiler/wasmSpec.js +5 -0
- package/compiler/wrap.js +150 -90
- package/package.json +1 -1
- package/runner/compare.js +0 -1
- package/runner/debug.js +1 -6
- package/runner/index.js +5 -4
- package/runner/profiler.js +15 -42
- package/runner/repl.js +20 -10
- package/runner/sizes.js +2 -2
- package/runner/version.js +10 -8
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import type {} from './porffor.d.ts';
|
2
2
|
|
3
3
|
export const __Array_isArray = (x: unknown): boolean =>
|
4
4
|
// Porffor.wasm`local.get ${x+1}` == Porffor.TYPES.array;
|
@@ -29,14 +29,16 @@ export const __Array_prototype_slice = (_this: any[], start: number, end: number
|
|
29
29
|
let outPtr: i32 = Porffor.wasm`local.get ${out}`;
|
30
30
|
let thisPtr: i32 = Porffor.wasm`local.get ${_this}`;
|
31
31
|
|
32
|
-
const thisPtrEnd: i32 = thisPtr + end *
|
32
|
+
const thisPtrEnd: i32 = thisPtr + end * 9;
|
33
33
|
|
34
|
-
thisPtr += start *
|
34
|
+
thisPtr += start * 9;
|
35
35
|
|
36
36
|
while (thisPtr < thisPtrEnd) {
|
37
37
|
Porffor.wasm.f64.store(outPtr, Porffor.wasm.f64.load(thisPtr, 0, 4), 0, 4);
|
38
|
-
thisPtr
|
39
|
-
|
38
|
+
Porffor.wasm.i32.store8(outPtr + 8, Porffor.wasm.i32.load8_u(thisPtr + 8, 0, 4), 0, 4);
|
39
|
+
|
40
|
+
thisPtr += 9;
|
41
|
+
outPtr += 9;
|
40
42
|
}
|
41
43
|
|
42
44
|
out.length = end - start;
|
@@ -91,14 +93,12 @@ export const __Array_prototype_with = (_this: any[], index: number, value: any)
|
|
91
93
|
if (index < 0) {
|
92
94
|
index = len + index;
|
93
95
|
if (index < 0) {
|
94
|
-
|
95
|
-
return null;
|
96
|
+
throw new RangeError('Invalid index');
|
96
97
|
}
|
97
98
|
}
|
98
99
|
|
99
100
|
if (index > len) {
|
100
|
-
|
101
|
-
return null;
|
101
|
+
throw new RangeError('Invalid index');
|
102
102
|
}
|
103
103
|
|
104
104
|
// todo: allocator is bad here?
|
@@ -146,4 +146,80 @@ export const __Array_prototype_toReversed = (_this: any[]) => {
|
|
146
146
|
|
147
147
|
export const __Array_prototype_valueOf = (_this: any[]) => {
|
148
148
|
return _this;
|
149
|
+
};
|
150
|
+
|
151
|
+
|
152
|
+
export const __Array_prototype_forEach = (_this: any[], callbackFn: any) => {
|
153
|
+
const len: i32 = _this.length;
|
154
|
+
let i: i32 = 0;
|
155
|
+
while (i < len) {
|
156
|
+
callbackFn(_this[i], i++, _this);
|
157
|
+
}
|
158
|
+
};
|
159
|
+
|
160
|
+
export const __Array_prototype_filter = (_this: any[], callbackFn: any) => {
|
161
|
+
const out: any[] = [];
|
162
|
+
|
163
|
+
const len: i32 = _this.length;
|
164
|
+
let i: i32 = 0;
|
165
|
+
while (i < len) {
|
166
|
+
const el: any = _this[i];
|
167
|
+
if (Boolean(callbackFn(el, i++, _this))) out.push(el);
|
168
|
+
}
|
169
|
+
|
170
|
+
return out;
|
171
|
+
};
|
172
|
+
|
173
|
+
export const __Array_prototype_map = (_this: any[], callbackFn: any) => {
|
174
|
+
const out: any[] = [];
|
175
|
+
|
176
|
+
const len: i32 = _this.length;
|
177
|
+
let i: i32 = 0;
|
178
|
+
while (i < len) {
|
179
|
+
out.push(callbackFn(_this[i], i++, _this));
|
180
|
+
}
|
181
|
+
|
182
|
+
return out;
|
183
|
+
};
|
184
|
+
|
185
|
+
export const __Array_prototype_find = (_this: any[], callbackFn: any) => {
|
186
|
+
const len: i32 = _this.length;
|
187
|
+
let i: i32 = 0;
|
188
|
+
while (i < len) {
|
189
|
+
const el: any = _this[i];
|
190
|
+
if (Boolean(callbackFn(el, i++, _this))) return el;
|
191
|
+
}
|
192
|
+
};
|
193
|
+
|
194
|
+
export const __Array_prototype_findLast = (_this: any[], callbackFn: any) => {
|
195
|
+
let i: i32 = _this.length;
|
196
|
+
while (i > 0) {
|
197
|
+
const el: any = _this[--i];
|
198
|
+
if (Boolean(callbackFn(el, i, _this))) return el;
|
199
|
+
}
|
200
|
+
};
|
201
|
+
|
202
|
+
export const __Array_prototype_findIndex = (_this: any[], callbackFn: any) => {
|
203
|
+
const len: i32 = _this.length;
|
204
|
+
let i: i32 = 0;
|
205
|
+
while (i < len) {
|
206
|
+
if (Boolean(callbackFn(_this[i], i++, _this))) return i;
|
207
|
+
}
|
208
|
+
};
|
209
|
+
|
210
|
+
export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any) => {
|
211
|
+
let i: i32 = _this.length;
|
212
|
+
while (i > 0) {
|
213
|
+
if (Boolean(callbackFn(_this[--i], i, _this))) return i;
|
214
|
+
}
|
215
|
+
};
|
216
|
+
|
217
|
+
export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
|
218
|
+
const len: i32 = _this.length;
|
219
|
+
let i: i32 = 0;
|
220
|
+
while (i < len) {
|
221
|
+
if (!Boolean(callbackFn(_this[i], i++, _this))) return false;
|
222
|
+
}
|
223
|
+
|
224
|
+
return true;
|
149
225
|
};
|
@@ -1,4 +1,5 @@
|
|
1
|
-
// @porf --
|
1
|
+
// @porf --valtype=i32
|
2
|
+
import type {} from './porffor.d.ts';
|
2
3
|
|
3
4
|
export const btoa = (input: bytestring): bytestring => {
|
4
5
|
const keyStr: bytestring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import type {} from './porffor.d.ts';
|
2
2
|
|
3
3
|
// 20.3.3.2 Boolean.prototype.toString ()
|
4
4
|
// https://tc39.es/ecma262/#sec-boolean.prototype.tostring
|
@@ -17,4 +17,4 @@ export const __Boolean_prototype_toString = (_this: boolean) => {
|
|
17
17
|
export const __Boolean_prototype_valueOf = (_this: boolean) => {
|
18
18
|
// 1. Return ? ThisBooleanValue(this value).
|
19
19
|
return _this;
|
20
|
-
};
|
20
|
+
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import type {} from './porffor.d.ts';
|
2
2
|
|
3
3
|
// 21.4.1.3 Day (t)
|
4
4
|
// https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-day
|
@@ -1774,8 +1774,7 @@ export const __Date_prototype_toISOString = (_this: Date) => {
|
|
1774
1774
|
|
1775
1775
|
// 4. If tv is NaN, throw a RangeError exception.
|
1776
1776
|
if (Number.isNaN(tv)) {
|
1777
|
-
|
1778
|
-
return;
|
1777
|
+
throw new RangeError('Invalid time value');
|
1779
1778
|
}
|
1780
1779
|
|
1781
1780
|
// 5. Assert: tv is an integral Number.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
export default () => {
|
2
|
+
let out = '';
|
3
|
+
|
4
|
+
const error = name => out += `export const ${name} = (message: bytestring) => {
|
5
|
+
return {};
|
6
|
+
};
|
7
|
+
|
8
|
+
export const ${name}$constructor = (message: bytestring) => {
|
9
|
+
return {};
|
10
|
+
};`;
|
11
|
+
|
12
|
+
error('Error');
|
13
|
+
error('AggregateError');
|
14
|
+
error('TypeError');
|
15
|
+
error('ReferenceError');
|
16
|
+
error('SyntaxError');
|
17
|
+
error('RangeError');
|
18
|
+
error('EvalError');
|
19
|
+
error('URIError');
|
20
|
+
|
21
|
+
return out;
|
22
|
+
};
|
@@ -1,6 +1,5 @@
|
|
1
|
-
// @porf --
|
2
|
-
|
3
|
-
import type {} from './porffor';
|
1
|
+
// @porf --valtype=i32
|
2
|
+
import type {} from './porffor.d.ts';
|
4
3
|
|
5
4
|
export const escape = (input: string|bytestring): bytestring => {
|
6
5
|
// we have no byte array yet so use bytestring with 0x00 and 0x01 via escape characters
|
package/compiler/builtins/int.ts
CHANGED
@@ -0,0 +1,410 @@
|
|
1
|
+
import type {} from './porffor.d.ts';
|
2
|
+
|
3
|
+
// todo: use any and Number(x) in all these later
|
4
|
+
// todo: specify the rest of this file later
|
5
|
+
// todo/perf: make i32 variants later
|
6
|
+
// todo/perf: add a compiler pref for accuracy vs perf (epsilion?)
|
7
|
+
|
8
|
+
export const __Math_exp = (x: number): number => {
|
9
|
+
if (!Number.isFinite(x)) {
|
10
|
+
if (x == -Infinity) return 0;
|
11
|
+
return x;
|
12
|
+
}
|
13
|
+
|
14
|
+
if (x < 0) {
|
15
|
+
// exp(-x) = 1 / exp(+x)
|
16
|
+
return 1 / Math.exp(-x);
|
17
|
+
}
|
18
|
+
|
19
|
+
const k: number = Math.floor(x / Math.LN2);
|
20
|
+
const r: number = x - k * Math.LN2;
|
21
|
+
|
22
|
+
// Taylor series via Horner's method
|
23
|
+
let term: number = r;
|
24
|
+
let sum: number = 1 + r;
|
25
|
+
let i: number = 2;
|
26
|
+
|
27
|
+
while (Math.abs(term) > 1e-15) {
|
28
|
+
term *= r / i;
|
29
|
+
sum += term;
|
30
|
+
i++;
|
31
|
+
}
|
32
|
+
|
33
|
+
return sum * (1 << k);
|
34
|
+
};
|
35
|
+
|
36
|
+
export const __Math_log2 = (y: number): number => {
|
37
|
+
if (y <= 0) return NaN;
|
38
|
+
if (!Number.isFinite(y)) return y;
|
39
|
+
|
40
|
+
// approx using log knowledge
|
41
|
+
let x: number = y;
|
42
|
+
let exponent: number = 0;
|
43
|
+
|
44
|
+
while (x >= 2) {
|
45
|
+
x /= 2;
|
46
|
+
exponent++;
|
47
|
+
}
|
48
|
+
|
49
|
+
while (x < 1) {
|
50
|
+
x *= 2;
|
51
|
+
exponent--;
|
52
|
+
}
|
53
|
+
|
54
|
+
// 1 <= x < 2 -> 0 <= x < 1
|
55
|
+
x -= 1;
|
56
|
+
|
57
|
+
// refine with Newton-Raphson method
|
58
|
+
let delta: number;
|
59
|
+
do {
|
60
|
+
const e_x: number = Math.exp(x * Math.LN2);
|
61
|
+
delta = (e_x - y) / (e_x * Math.LN2);
|
62
|
+
x -= delta;
|
63
|
+
} while (Math.abs(delta) > 1e-15);
|
64
|
+
|
65
|
+
return x + exponent;
|
66
|
+
};
|
67
|
+
|
68
|
+
export const __Math_log = (y: number): number => {
|
69
|
+
if (y <= 0) {
|
70
|
+
if (y == 0) return -Infinity;
|
71
|
+
return NaN;
|
72
|
+
}
|
73
|
+
if (!Number.isFinite(y)) return y;
|
74
|
+
|
75
|
+
// guess using log knowledge
|
76
|
+
let x: number = y > 1 ? Math.log2(y) : 0;
|
77
|
+
|
78
|
+
// refine with Newton-Raphson method
|
79
|
+
let delta: number;
|
80
|
+
do {
|
81
|
+
const e_x: number = Math.exp(x);
|
82
|
+
delta = (e_x - y) / e_x;
|
83
|
+
x -= delta;
|
84
|
+
} while (Math.abs(delta) > 1e-15);
|
85
|
+
|
86
|
+
return x;
|
87
|
+
};
|
88
|
+
|
89
|
+
export const __Math_log10 = (x: number): number => {
|
90
|
+
if (x <= 0) {
|
91
|
+
if (x == 0) return -Infinity;
|
92
|
+
return NaN;
|
93
|
+
}
|
94
|
+
if (!Number.isFinite(x)) return x;
|
95
|
+
|
96
|
+
return Math.log(x) / Math.LN10;
|
97
|
+
};
|
98
|
+
|
99
|
+
// 21.3.2.26 Math.pow (base, exponent)
|
100
|
+
// https://tc39.es/ecma262/#sec-math.pow
|
101
|
+
export const __Math_pow = (base: number, exponent: number): number => {
|
102
|
+
// 1. Set base to ? ToNumber(base).
|
103
|
+
// 2. Set exponent to ? ToNumber(exponent).
|
104
|
+
// todo
|
105
|
+
|
106
|
+
// 3. Return Number::exponentiate(base, exponent).
|
107
|
+
|
108
|
+
// Number::exponentiate (base, exponent)
|
109
|
+
// https://tc39.es/ecma262/#sec-numeric-types-number-exponentiate
|
110
|
+
// 1. If exponent is NaN, return NaN.
|
111
|
+
if (Number.isNaN(exponent)) return NaN;
|
112
|
+
|
113
|
+
// 2. If exponent is either +0𝔽 or -0𝔽, return 1𝔽.
|
114
|
+
if (exponent == 0) return 1;
|
115
|
+
|
116
|
+
if (!Number.isFinite(base)) {
|
117
|
+
// 3. If base is NaN, return NaN.
|
118
|
+
if (Number.isNaN(base)) return base;
|
119
|
+
|
120
|
+
// 4. If base is +∞𝔽, then
|
121
|
+
if (base == Infinity) {
|
122
|
+
// a. If exponent > +0𝔽, return +∞𝔽. Otherwise, return +0𝔽.
|
123
|
+
if (exponent > 0) return base;
|
124
|
+
return 0;
|
125
|
+
}
|
126
|
+
|
127
|
+
// 5. If base is -∞𝔽, then
|
128
|
+
const isOdd = exponent % 2 == 1;
|
129
|
+
|
130
|
+
// a. If exponent > +0𝔽, then
|
131
|
+
if (exponent > 0) {
|
132
|
+
// i. If exponent is an odd integral Number, return -∞𝔽. Otherwise, return +∞𝔽.
|
133
|
+
if (isOdd) return -Infinity;
|
134
|
+
return Infinity;
|
135
|
+
}
|
136
|
+
|
137
|
+
// b. Else,
|
138
|
+
// i. If exponent is an odd integral Number, return -0𝔽. Otherwise, return +0𝔽.
|
139
|
+
if (isOdd) return -0;
|
140
|
+
return 0;
|
141
|
+
}
|
142
|
+
|
143
|
+
if (base == 0) {
|
144
|
+
// 6. If base is +0𝔽, then
|
145
|
+
if (1 / base == Infinity) {
|
146
|
+
// a. If exponent > +0𝔽, return +0𝔽. Otherwise, return +∞𝔽.
|
147
|
+
if (exponent > 0) return 0;
|
148
|
+
return Infinity;
|
149
|
+
}
|
150
|
+
|
151
|
+
// 7. If base is -0𝔽, then
|
152
|
+
const isOdd = exponent % 2 == 1;
|
153
|
+
|
154
|
+
// a. If exponent > +0𝔽, then
|
155
|
+
if (exponent > 0) {
|
156
|
+
// i. If exponent is an odd integral Number, return -0𝔽. Otherwise, return +0𝔽.
|
157
|
+
if (isOdd) return -0;
|
158
|
+
return 0;
|
159
|
+
}
|
160
|
+
|
161
|
+
// b. Else,
|
162
|
+
// i. If exponent is an odd integral Number, return -∞𝔽. Otherwise, return +∞𝔽.
|
163
|
+
if (isOdd) return -Infinity;
|
164
|
+
return Infinity;
|
165
|
+
}
|
166
|
+
|
167
|
+
// 8. Assert: base is finite and is neither +0𝔽 nor -0𝔽.
|
168
|
+
// todo
|
169
|
+
|
170
|
+
// 9. If exponent is +∞𝔽, then
|
171
|
+
if (exponent == Infinity) {
|
172
|
+
const abs = Math.abs(base);
|
173
|
+
|
174
|
+
// a. If abs(ℝ(base)) > 1, return +∞𝔽.
|
175
|
+
if (abs > 1) return Infinity;
|
176
|
+
|
177
|
+
// b. If abs(ℝ(base)) = 1, return NaN.
|
178
|
+
if (abs == 1) return NaN;
|
179
|
+
|
180
|
+
// c. If abs(ℝ(base)) < 1, return +0𝔽.
|
181
|
+
return 0;
|
182
|
+
}
|
183
|
+
|
184
|
+
// 10. If exponent is -∞𝔽, then
|
185
|
+
if (exponent == -Infinity) {
|
186
|
+
const abs = Math.abs(base);
|
187
|
+
|
188
|
+
// a. If abs(ℝ(base)) > 1, return +0𝔽.
|
189
|
+
if (abs > 1) return 0;
|
190
|
+
|
191
|
+
// b. If abs(ℝ(base)) = 1, return NaN.
|
192
|
+
if (abs == 1) return NaN;
|
193
|
+
|
194
|
+
// c. If abs(ℝ(base)) < 1, return +∞𝔽.
|
195
|
+
return Infinity;
|
196
|
+
}
|
197
|
+
|
198
|
+
// 11. Assert: exponent is finite and is neither +0𝔽 nor -0𝔽.
|
199
|
+
// todo
|
200
|
+
|
201
|
+
// 12. If base < -0𝔽 and exponent is not an integral Number, return NaN.
|
202
|
+
if (base < 0) if (!Number.isInteger(exponent)) return NaN;
|
203
|
+
|
204
|
+
// 13. Return an implementation-approximated Number value representing the result of raising ℝ(base) to the ℝ(exponent) power.
|
205
|
+
return Math.exp(exponent * Math.log(base));
|
206
|
+
};
|
207
|
+
|
208
|
+
|
209
|
+
export const __Math_expm1 = (x: number): number => {
|
210
|
+
if (!Number.isFinite(x)) {
|
211
|
+
if (x == -Infinity) return -1;
|
212
|
+
return x;
|
213
|
+
}
|
214
|
+
|
215
|
+
// use exp(x) - 1 for large x (perf)
|
216
|
+
if (Math.abs(x) > 1e-5) return Math.exp(x) - 1;
|
217
|
+
|
218
|
+
// Taylor series
|
219
|
+
let sum: number = x;
|
220
|
+
let term: number = x;
|
221
|
+
let i: number = 2;
|
222
|
+
|
223
|
+
while (Math.abs(term) > 1e-15) {
|
224
|
+
term *= x / i;
|
225
|
+
sum += term;
|
226
|
+
i++;
|
227
|
+
}
|
228
|
+
|
229
|
+
return sum;
|
230
|
+
};
|
231
|
+
|
232
|
+
export const __Math_log1p = (x: number): number => {
|
233
|
+
if (x == -1) return -Infinity; // log(0) = -inf
|
234
|
+
if (!Number.isFinite(x)) return x;
|
235
|
+
|
236
|
+
// use exp(x) - 1 for large x (perf)
|
237
|
+
if (Math.abs(x) > 1e-5) return Math.log(1 + x);
|
238
|
+
|
239
|
+
// Taylor series
|
240
|
+
let sum: number = 0;
|
241
|
+
let term: number = x;
|
242
|
+
let i: number = 2;
|
243
|
+
|
244
|
+
while (Math.abs(term) > 1e-15) {
|
245
|
+
term *= -x / i;
|
246
|
+
sum += term;
|
247
|
+
i++;
|
248
|
+
}
|
249
|
+
|
250
|
+
return sum;
|
251
|
+
};
|
252
|
+
|
253
|
+
|
254
|
+
export const __Math_sqrt = (y: number): number => {
|
255
|
+
if (y <= 0) {
|
256
|
+
if (y == 0) return 0;
|
257
|
+
return NaN;
|
258
|
+
}
|
259
|
+
if (!Number.isFinite(y)) return y;
|
260
|
+
|
261
|
+
// Babylonian method
|
262
|
+
let x: number = y;
|
263
|
+
let prev: number;
|
264
|
+
|
265
|
+
do {
|
266
|
+
prev = x;
|
267
|
+
x = 0.5 * (x + y / x);
|
268
|
+
} while (Math.abs(prev - x) > 1e-15);
|
269
|
+
|
270
|
+
return x;
|
271
|
+
};
|
272
|
+
|
273
|
+
export const __Math_cbrt = (y: number): number => {
|
274
|
+
if (y == 0) return 0; // cbrt(0) = 0
|
275
|
+
if (!Number.isFinite(y)) return y;
|
276
|
+
|
277
|
+
// Babylonian method
|
278
|
+
let x = Math.abs(y);
|
279
|
+
|
280
|
+
let prev: number;
|
281
|
+
|
282
|
+
do {
|
283
|
+
prev = x;
|
284
|
+
x = (2 * x + y / (x * x)) / 3;
|
285
|
+
} while (Math.abs(prev - x) > 1e-15);
|
286
|
+
|
287
|
+
return y < 0 ? -x : x;
|
288
|
+
};
|
289
|
+
|
290
|
+
|
291
|
+
// todo: varargs
|
292
|
+
export const __Math_hypot = (x: number, y: number): number => Math.sqrt(x * x + y * y);
|
293
|
+
|
294
|
+
export const __Math_sin = (x: number): number => {
|
295
|
+
// -inf <= x <= inf -> 0 <= x <= 2pi
|
296
|
+
const piX2: number = Math.PI * 2;
|
297
|
+
x %= piX2;
|
298
|
+
if (x < 0) x += piX2;
|
299
|
+
|
300
|
+
const x2: number = x * x;
|
301
|
+
|
302
|
+
return x * (
|
303
|
+
1 + x2 * (
|
304
|
+
-1.66666666666666307295e-1 + x2 * (
|
305
|
+
8.33333333332211858878e-3 + x2 * (
|
306
|
+
-1.98412698295895385996e-4 + x2 * (
|
307
|
+
2.75573136213857245213e-6 + x2 * (
|
308
|
+
-2.50507477628578072866e-8 + x2 * (
|
309
|
+
1.58962301576546568060e-10
|
310
|
+
)
|
311
|
+
)
|
312
|
+
)
|
313
|
+
)
|
314
|
+
)
|
315
|
+
)
|
316
|
+
);
|
317
|
+
|
318
|
+
// todo: investigate which is better (consider perf and accuracy)
|
319
|
+
// const x2 = x * x;
|
320
|
+
// const x4 = x2 * x2;
|
321
|
+
// const x6 = x4 * x2;
|
322
|
+
// const x8 = x4 * x4;
|
323
|
+
// const x10 = x6 * x4;
|
324
|
+
// const x12 = x6 * x6;
|
325
|
+
// const x14 = x12 * x2;
|
326
|
+
|
327
|
+
// return x * (
|
328
|
+
// 1 - x2 / 6 + x4 / 120 - x6 / 5040 + x8 / 362880 - x10 / 39916800 + x12 / 6227020800 - x14 / 1307674368000
|
329
|
+
// );
|
330
|
+
};
|
331
|
+
|
332
|
+
export const __Math_cos = (x: number): number => Math.sin(x - Math.PI / 2);
|
333
|
+
export const __Math_tan = (x: number): number => Math.sin(x) / Math.cos(x);
|
334
|
+
|
335
|
+
export const __Math_sinh = (x: number): number => (Math.exp(x) - Math.exp(-x)) / 2;
|
336
|
+
export const __Math_cosh = (x: number): number => (Math.exp(x) + Math.exp(-x)) / 2;
|
337
|
+
export const __Math_tanh = (x: number): number => Math.sinh(x) / Math.cosh(x);
|
338
|
+
|
339
|
+
|
340
|
+
export const __Math_asinh = (x: number): number => Math.log(x + Math.sqrt(x * x + 1));
|
341
|
+
export const __Math_acosh = (x: number): number => {
|
342
|
+
if (x < 1) return NaN;
|
343
|
+
return Math.log(x + Math.sqrt(x * x - 1));
|
344
|
+
};
|
345
|
+
export const __Math_atanh = (x: number): number => {
|
346
|
+
if (Math.abs(x) >= 1) return NaN;
|
347
|
+
return 0.5 * Math.log((1 + x) / (1 - x));
|
348
|
+
};
|
349
|
+
|
350
|
+
|
351
|
+
export const __Math_asin = (x: number): number => {
|
352
|
+
if (x <= -1) {
|
353
|
+
if (x == -1) return -Math.PI / 2;
|
354
|
+
return NaN;
|
355
|
+
}
|
356
|
+
if (x >= 1) {
|
357
|
+
if (x == 1) return Math.PI / 2;
|
358
|
+
return NaN;
|
359
|
+
}
|
360
|
+
|
361
|
+
// Taylor series
|
362
|
+
let sum: number = x;
|
363
|
+
let term: number = x;
|
364
|
+
let n: number = 1;
|
365
|
+
|
366
|
+
while (Math.abs(term) > 1e-15) {
|
367
|
+
term *= x * x * (2 * n - 1) * (2 * n - 1) / ((2 * n) * (2 * n + 1));
|
368
|
+
sum += term / (2 * n + 1);
|
369
|
+
n++;
|
370
|
+
}
|
371
|
+
|
372
|
+
return sum;
|
373
|
+
};
|
374
|
+
|
375
|
+
export const __Math_acos = (x: number): number => Math.asin(x) - Math.PI / 2;
|
376
|
+
|
377
|
+
export const __Math_atan = (x: number): number => {
|
378
|
+
if (x == Infinity) return Math.PI / 2
|
379
|
+
if (x == -Infinity) return -Math.PI / 2;
|
380
|
+
|
381
|
+
// Taylor series
|
382
|
+
let sum: number = x;
|
383
|
+
let term: number = x;
|
384
|
+
let n: number = 1;
|
385
|
+
|
386
|
+
while (Math.abs(term) > 1e-15) {
|
387
|
+
term *= -x * x * (2 * n - 1) / ((2 * n) * (2 * n + 1));
|
388
|
+
sum += term;
|
389
|
+
n++;
|
390
|
+
}
|
391
|
+
|
392
|
+
return sum;
|
393
|
+
};
|
394
|
+
|
395
|
+
export const __Math_atan2 = (y: number, x: number): number => {
|
396
|
+
if (x == 0) {
|
397
|
+
if (y > 0) return Math.PI / 2;
|
398
|
+
if (y < 0) return -Math.PI / 2;
|
399
|
+
|
400
|
+
return NaN;
|
401
|
+
}
|
402
|
+
|
403
|
+
const ratio = y / x;
|
404
|
+
if (x > 0) {
|
405
|
+
return Math.atan(ratio);
|
406
|
+
}
|
407
|
+
|
408
|
+
if (y >= 0) return Math.atan(ratio) + Math.PI;
|
409
|
+
return Math.atan(ratio) - Math.PI;
|
410
|
+
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
import type {} from './porffor.d.ts';
|
2
2
|
|
3
3
|
// radix: number|any for rawType check
|
4
4
|
export const __Number_prototype_toString = (_this: number, radix: number|any) => {
|
@@ -20,8 +20,7 @@ export const __Number_prototype_toString = (_this: number, radix: number|any) =>
|
|
20
20
|
|
21
21
|
radix |= 0;
|
22
22
|
if (radix < 2 || radix > 36) {
|
23
|
-
|
24
|
-
return out;
|
23
|
+
throw new RangeError('toString() radix argument must be between 2 and 36');
|
25
24
|
}
|
26
25
|
|
27
26
|
if (_this == 0) {
|
@@ -254,8 +253,7 @@ export const __Number_prototype_toFixed = (_this: number, fractionDigits: number
|
|
254
253
|
|
255
254
|
fractionDigits |= 0;
|
256
255
|
if (fractionDigits < 0 || fractionDigits > 100) {
|
257
|
-
|
258
|
-
return out;
|
256
|
+
throw new RangeError('toFixed() fractionDigits argument must be between 0 and 100');
|
259
257
|
}
|
260
258
|
|
261
259
|
// if negative value
|
@@ -349,8 +347,7 @@ export const __Number_prototype_toExponential = (_this: number, fractionDigits:
|
|
349
347
|
} else {
|
350
348
|
fractionDigits |= 0;
|
351
349
|
if (fractionDigits < 0 || fractionDigits > 100) {
|
352
|
-
|
353
|
-
return out;
|
350
|
+
throw new RangeError('toExponential() fractionDigits argument must be between 0 and 100');
|
354
351
|
}
|
355
352
|
}
|
356
353
|
|