mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-16 16:31:32 +00:00
srsly
This commit is contained in:
@ -42,6 +42,7 @@ function R(z: f64): f64 { // Rational approximation of (asin(x)-x)/x^3
|
||||
return p / q;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@inline function expo2(x: f64): f64 { // exp(x)/2 for x >= log(DBL_MAX)
|
||||
const // see: musl/src/math/__expo2.c
|
||||
k = <u32>2043,
|
||||
@ -50,11 +51,15 @@ function R(z: f64): f64 { // Rational approximation of (asin(x)-x)/x^3
|
||||
return NativeMath.exp(x - kln2) * scale * scale;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
// @ts-ignore: decorator
|
||||
@lazy var random_seeded = false;
|
||||
// @ts-ignore: decorator
|
||||
@lazy var random_state0_64: u64;
|
||||
// @ts-ignore: decorator
|
||||
@lazy var random_state1_64: u64;
|
||||
// @ts-ignore: decorator
|
||||
@lazy var random_state0_32: u32;
|
||||
// @ts-ignore: decorator
|
||||
@lazy var random_state1_32: u32;
|
||||
|
||||
function murmurHash3(h: u64): u64 { // Force all bits of a hash block to avalanche
|
||||
@ -75,17 +80,25 @@ function splitMix32(h: u32): u32 {
|
||||
|
||||
export namespace NativeMath {
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const E = reinterpret<f64>(0x4005BF0A8B145769); // 2.7182818284590452354
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LN2 = reinterpret<f64>(0x3FE62E42FEFA39EF); // 0.69314718055994530942
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LN10 = reinterpret<f64>(0x40026BB1BBB55516); // 2.30258509299404568402
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LOG2E = reinterpret<f64>(0x3FF71547652B82FE); // 1.4426950408889634074
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LOG10E = reinterpret<f64>(0x3FDBCB7B1526E50E); // 0.43429448190325182765
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const PI = reinterpret<f64>(0x400921FB54442D18); // 3.14159265358979323846
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const SQRT1_2 = reinterpret<f64>(0x3FE6A09E667F3BCD); // 0.70710678118654752440
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const SQRT2 = reinterpret<f64>(0x3FF6A09E667F3BCD); // 1.41421356237309504880
|
||||
|
||||
@inline
|
||||
export function abs(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function abs(x: f64): f64 {
|
||||
return builtin_abs<f64>(x);
|
||||
}
|
||||
|
||||
@ -346,8 +359,8 @@ export namespace NativeMath {
|
||||
return t;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function ceil(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function ceil(x: f64): f64 {
|
||||
return builtin_ceil<f64>(x);
|
||||
}
|
||||
|
||||
@ -497,13 +510,13 @@ export namespace NativeMath {
|
||||
return (x + y) * twopk;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function floor(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function floor(x: f64): f64 {
|
||||
return builtin_floor<f64>(x);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function fround(x: f64): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function fround(x: f64): f32 {
|
||||
return <f32>x;
|
||||
}
|
||||
|
||||
@ -763,13 +776,13 @@ export namespace NativeMath {
|
||||
return val_lo + val_hi;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function max(value1: f64, value2: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function max(value1: f64, value2: f64): f64 {
|
||||
return builtin_max<f64>(value1, value2);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function min(value1: f64, value2: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function min(value1: f64, value2: f64): f64 {
|
||||
return builtin_min<f64>(value1, value2);
|
||||
}
|
||||
|
||||
@ -997,13 +1010,13 @@ export namespace NativeMath {
|
||||
return reinterpret<f64>(r) - 1;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function round(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function round(x: f64): f64 {
|
||||
return builtin_copysign<f64>(builtin_floor<f64>(x + 0.5), x);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function sign(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function sign(x: f64): f64 {
|
||||
if (ASC_SHRINK_LEVEL > 0) {
|
||||
return builtin_abs(x) > 0 ? builtin_copysign<f64>(1, x) : x;
|
||||
} else {
|
||||
@ -1011,10 +1024,11 @@ export namespace NativeMath {
|
||||
}
|
||||
}
|
||||
|
||||
@inline
|
||||
export function signbit(x: f64): bool {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function signbit(x: f64): bool {
|
||||
// In ECMAScript all NaN values are indistinguishable from each other
|
||||
// so we need handle NaN and negative NaN in similar way
|
||||
// @ts-ignore: type
|
||||
return <bool>(<i32>(reinterpret<u64>(x) >>> 63) & (x == x));
|
||||
}
|
||||
|
||||
@ -1041,8 +1055,8 @@ export namespace NativeMath {
|
||||
return t;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function sqrt(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function sqrt(x: f64): f64 {
|
||||
return builtin_sqrt<f64>(x);
|
||||
}
|
||||
|
||||
@ -1074,8 +1088,8 @@ export namespace NativeMath {
|
||||
return builtin_copysign<f64>(t, x);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function trunc(x: f64): f64 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function trunc(x: f64): f64 {
|
||||
return builtin_trunc<f64>(x);
|
||||
}
|
||||
|
||||
@ -1232,8 +1246,9 @@ export namespace NativeMath {
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
// @ts-ignore: decorator
|
||||
@lazy var rempio2f_y: f64;
|
||||
// @ts-ignore: decorator
|
||||
@lazy const PIO2_TABLE: u64[] = [
|
||||
0xA2F9836E4E441529,
|
||||
0xFC2757D1F534DDC0,
|
||||
@ -1241,7 +1256,6 @@ export namespace NativeMath {
|
||||
0xFE5163ABDEBBC561
|
||||
];
|
||||
|
||||
/** @internal */
|
||||
function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3
|
||||
const // see: musl/src/math/asinf.c and SUN COPYRIGHT NOTICE above
|
||||
pS0 = reinterpret<f32>(0x3E2AAA75), // 1.6666586697e-01f
|
||||
@ -1253,6 +1267,7 @@ function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3
|
||||
return p / q;
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@inline function expo2f(x: f32): f32 { // exp(x)/2 for x >= log(DBL_MAX)
|
||||
const // see: musl/src/math/__expo2f.c
|
||||
k = <u32>235,
|
||||
@ -1261,8 +1276,8 @@ function Rf(z: f32): f32 { // Rational approximation of (asin(x)-x)/x^3
|
||||
return NativeMathf.exp(x - kln2) * scale * scale;
|
||||
}
|
||||
|
||||
@inline /** @internal */
|
||||
function pio2_large_quot(x: f32, u: i32): i32 { // see: jdh8/metallic/blob/master/src/math/float/rem_pio2f.c
|
||||
// @ts-ignore: decorator
|
||||
@inline function pio2_large_quot(x: f32, u: i32): i32 { // see: jdh8/metallic/blob/master/src/math/float/rem_pio2f.c
|
||||
const coeff = reinterpret<f64>(0x3BF921FB54442D18); // π * 0x1p-65 = 8.51530395021638647334e-20
|
||||
const bits = PIO2_TABLE;
|
||||
|
||||
@ -1291,8 +1306,8 @@ function pio2_large_quot(x: f32, u: i32): i32 { // see: jdh8/metallic/blob
|
||||
return q;
|
||||
}
|
||||
|
||||
@inline /** @internal */
|
||||
function rempio2f(x: f32, u: u32, sign: i32): i32 { // see: jdh8/metallic/blob/master/src/math/float/rem_pio2f.c
|
||||
// @ts-ignore: decorator
|
||||
@inline function rempio2f(x: f32, u: u32, sign: i32): i32 { // see: jdh8/metallic/blob/master/src/math/float/rem_pio2f.c
|
||||
const pi2hi = reinterpret<f64>(0x3FF921FB50000000); // 1.57079631090164184570
|
||||
const pi2lo = reinterpret<f64>(0x3E5110B4611A6263); // 1.58932547735281966916e-8
|
||||
const _2_pi = reinterpret<f64>(0x3FE45F306DC9C883); // 0.63661977236758134308
|
||||
@ -1308,8 +1323,8 @@ function rempio2f(x: f32, u: u32, sign: i32): i32 { // see: jdh8/metallic/blob
|
||||
}
|
||||
|
||||
/* |sin(x)/x - s(x)| < 2**-37.5 (~[-4.89e-12, 4.824e-12]). */
|
||||
@inline /** @internal */
|
||||
function sin_kernf(x: f64): f32 { // see: musl/tree/src/math/__sindf.c
|
||||
// @ts-ignore: decorator
|
||||
@inline function sin_kernf(x: f64): f32 { // see: musl/tree/src/math/__sindf.c
|
||||
const S1 = reinterpret<f64>(0xBFC5555554CBAC77); // -0x15555554cbac77.0p-55
|
||||
const S2 = reinterpret<f64>(0x3F811110896EFBB2); // 0x111110896efbb2.0p-59
|
||||
const S3 = reinterpret<f64>(0xBF2A00F9E2CAE774); // -0x1a00f9e2cae774.0p-65
|
||||
@ -1323,8 +1338,8 @@ function sin_kernf(x: f64): f32 { // see: musl/tree/src/math/__sindf.c
|
||||
}
|
||||
|
||||
/* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */
|
||||
@inline /** @internal */
|
||||
function cos_kernf(x: f64): f32 { // see: musl/tree/src/math/__cosdf.c
|
||||
// @ts-ignore: decorator
|
||||
@inline function cos_kernf(x: f64): f32 { // see: musl/tree/src/math/__cosdf.c
|
||||
const C0 = reinterpret<f64>(0xBFDFFFFFFD0C5E81); // -0x1ffffffd0c5e81.0p-54
|
||||
const C1 = reinterpret<f64>(0x3FA55553E1053A42); // 0x155553e1053a42.0p-57
|
||||
const C2 = reinterpret<f64>(0xBF56C087E80F1E27); // -0x16c087e80f1e27.0p-62
|
||||
@ -1337,8 +1352,8 @@ function cos_kernf(x: f64): f32 { // see: musl/tree/src/math/__cosdf.c
|
||||
}
|
||||
|
||||
/* |tan(x)/x - t(x)| < 2**-25.5 (~[-2e-08, 2e-08]). */
|
||||
@inline /** @internal */
|
||||
function tan_kernf(x: f64, odd: i32): f32 { // see: musl/tree/src/math/__tandf.c
|
||||
// @ts-ignore: decorator
|
||||
@inline function tan_kernf(x: f64, odd: i32): f32 { // see: musl/tree/src/math/__tandf.c
|
||||
|
||||
const T0 = reinterpret<f64>(0x3FD5554D3418C99F); /* 0x15554d3418c99f.0p-54 */
|
||||
const T1 = reinterpret<f64>(0x3FC112FD38999F72); /* 0x1112fd38999f72.0p-55 */
|
||||
@ -1360,21 +1375,31 @@ function tan_kernf(x: f64, odd: i32): f32 { // see: musl/tree/src/math/__tandf.c
|
||||
|
||||
export namespace NativeMathf {
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const E = <f32>NativeMath.E;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LN2 = <f32>NativeMath.LN2;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LN10 = <f32>NativeMath.LN10;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LOG2E = <f32>NativeMath.LOG2E;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const LOG10E = <f32>NativeMath.LOG10E;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const PI = <f32>NativeMath.PI;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const SQRT1_2 = <f32>NativeMath.SQRT1_2;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export const SQRT2 = <f32>NativeMath.SQRT2;
|
||||
|
||||
/** Used as return values from Mathf.sincos */
|
||||
// @ts-ignore: decorator
|
||||
@lazy export var sincos_sin: f32 = 0;
|
||||
// @ts-ignore: decorator
|
||||
@lazy export var sincos_cos: f32 = 0;
|
||||
|
||||
@inline
|
||||
export function abs(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function abs(x: f32): f32 {
|
||||
return builtin_abs<f32>(x);
|
||||
}
|
||||
|
||||
@ -1609,8 +1634,8 @@ export namespace NativeMathf {
|
||||
return <f32>t;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function ceil(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function ceil(x: f32): f32 {
|
||||
return builtin_ceil<f32>(x);
|
||||
}
|
||||
|
||||
@ -1685,8 +1710,8 @@ export namespace NativeMathf {
|
||||
return expo2f(x);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function floor(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function floor(x: f32): f32 {
|
||||
return builtin_floor<f32>(x);
|
||||
}
|
||||
|
||||
@ -1796,8 +1821,8 @@ export namespace NativeMathf {
|
||||
return (x + y) * twopk;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function fround(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function fround(x: f32): f32 {
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -1831,8 +1856,8 @@ export namespace NativeMathf {
|
||||
return z * builtin_sqrt<f32>(<f32>(<f64>x * x + <f64>y * y));
|
||||
}
|
||||
|
||||
@inline
|
||||
export function imul(x: f32, y: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function imul(x: f32, y: f32): f32 {
|
||||
/*
|
||||
* Wasm (MVP) and JS have different approaches for double->int conversions.
|
||||
*
|
||||
@ -2010,13 +2035,13 @@ export namespace NativeMathf {
|
||||
return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + dk;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function max(value1: f32, value2: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function max(value1: f32, value2: f32): f32 {
|
||||
return builtin_max<f32>(value1, value2);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function min(value1: f32, value2: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function min(value1: f32, value2: f32): f32 {
|
||||
return builtin_min<f32>(value1, value2);
|
||||
}
|
||||
|
||||
@ -2209,8 +2234,8 @@ export namespace NativeMathf {
|
||||
return sn * z;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function seedRandom(value: i64): void {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function seedRandom(value: i64): void {
|
||||
NativeMath.seedRandom(value);
|
||||
}
|
||||
|
||||
@ -2229,13 +2254,13 @@ export namespace NativeMathf {
|
||||
return reinterpret<f32>((r >> 9) | (127 << 23)) - 1.0;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function round(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function round(x: f32): f32 {
|
||||
return builtin_copysign<f32>(builtin_floor<f32>(x + 0.5), x);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function sign(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function sign(x: f32): f32 {
|
||||
if (ASC_SHRINK_LEVEL > 0) {
|
||||
return builtin_abs(x) > 0 ? builtin_copysign<f32>(1, x) : x;
|
||||
} else {
|
||||
@ -2243,8 +2268,9 @@ export namespace NativeMathf {
|
||||
}
|
||||
}
|
||||
|
||||
@inline
|
||||
export function signbit(x: f32): bool {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function signbit(x: f32): bool {
|
||||
// @ts-ignore: type
|
||||
return <bool>((reinterpret<u32>(x) >>> 31) & (x == x));
|
||||
}
|
||||
|
||||
@ -2308,8 +2334,8 @@ export namespace NativeMathf {
|
||||
return t;
|
||||
}
|
||||
|
||||
@inline
|
||||
export function sqrt(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function sqrt(x: f32): f32 {
|
||||
return builtin_sqrt<f32>(x);
|
||||
}
|
||||
|
||||
@ -2377,8 +2403,8 @@ export namespace NativeMathf {
|
||||
return builtin_copysign<f32>(t, x);
|
||||
}
|
||||
|
||||
@inline
|
||||
export function trunc(x: f32): f32 {
|
||||
// @ts-ignore: decorator
|
||||
@inline export function trunc(x: f32): f32 {
|
||||
return builtin_trunc<f32>(x);
|
||||
}
|
||||
|
||||
@ -2541,12 +2567,12 @@ export namespace NativeMathf {
|
||||
|
||||
if (ix <= 0x3f490fda) { /* |x| ~<= π/4 */
|
||||
if (ix < 0x39800000) { /* |x| < 2**-12 */
|
||||
sincos_s32 = x;
|
||||
sincos_c32 = 1;
|
||||
sincos_sin = x;
|
||||
sincos_cos = 1;
|
||||
return;
|
||||
}
|
||||
sincos_s32 = sin_kernf(x);
|
||||
sincos_c32 = cos_kernf(x);
|
||||
sincos_sin = sin_kernf(x);
|
||||
sincos_cos = cos_kernf(x);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2554,33 +2580,33 @@ export namespace NativeMathf {
|
||||
if (ix <= 0x407b53d1) { /* |x| ~<= 5π/4 */
|
||||
if (ix <= 0x4016cbe3) { /* |x| ~<= 3π/4 */
|
||||
if (sign) {
|
||||
sincos_s32 = -cos_kernf(x + s1pio2);
|
||||
sincos_c32 = sin_kernf(x + s1pio2);
|
||||
sincos_sin = -cos_kernf(x + s1pio2);
|
||||
sincos_cos = sin_kernf(x + s1pio2);
|
||||
} else {
|
||||
sincos_s32 = cos_kernf(s1pio2 - x);
|
||||
sincos_c32 = sin_kernf(s1pio2 - x);
|
||||
sincos_sin = cos_kernf(s1pio2 - x);
|
||||
sincos_cos = sin_kernf(s1pio2 - x);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* -sin(x + c) is not correct if x+c could be 0: -0 vs +0 */
|
||||
sincos_s32 = -sin_kernf(sign ? x + s2pio2 : x - s2pio2);
|
||||
sincos_c32 = -cos_kernf(sign ? x + s2pio2 : x - s2pio2);
|
||||
sincos_sin = -sin_kernf(sign ? x + s2pio2 : x - s2pio2);
|
||||
sincos_cos = -cos_kernf(sign ? x + s2pio2 : x - s2pio2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ix <= 0x40e231d5) { /* |x| ~<= 9π/4 */
|
||||
if (ix <= 0x40afeddf) { /* |x| ~<= 7π/4 */
|
||||
if (sign) {
|
||||
sincos_s32 = cos_kernf(x + s3pio2);
|
||||
sincos_c32 = -sin_kernf(x + s3pio2);
|
||||
sincos_sin = cos_kernf(x + s3pio2);
|
||||
sincos_cos = -sin_kernf(x + s3pio2);
|
||||
} else {
|
||||
sincos_s32 = -cos_kernf(x - s3pio2);
|
||||
sincos_c32 = sin_kernf(x - s3pio2);
|
||||
sincos_sin = -cos_kernf(x - s3pio2);
|
||||
sincos_cos = sin_kernf(x - s3pio2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
sincos_s32 = sin_kernf(sign ? x + s4pio2 : x - s4pio2);
|
||||
sincos_c32 = cos_kernf(sign ? x + s4pio2 : x - s4pio2);
|
||||
sincos_sin = sin_kernf(sign ? x + s4pio2 : x - s4pio2);
|
||||
sincos_cos = cos_kernf(sign ? x + s4pio2 : x - s4pio2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2588,8 +2614,8 @@ export namespace NativeMathf {
|
||||
/* sin(Inf or NaN) is NaN */
|
||||
if (ix >= 0x7f800000) {
|
||||
let xx = x - x;
|
||||
sincos_s32 = xx;
|
||||
sincos_c32 = xx;
|
||||
sincos_sin = xx;
|
||||
sincos_cos = xx;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2601,24 +2627,24 @@ export namespace NativeMathf {
|
||||
|
||||
switch (n & 3) {
|
||||
case 0: {
|
||||
sincos_s32 = s;
|
||||
sincos_c32 = c;
|
||||
sincos_sin = s;
|
||||
sincos_cos = c;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
sincos_s32 = c;
|
||||
sincos_c32 = -s;
|
||||
sincos_sin = c;
|
||||
sincos_cos = -s;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
sincos_s32 = -s;
|
||||
sincos_c32 = -c;
|
||||
sincos_sin = -s;
|
||||
sincos_cos = -c;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
default: {
|
||||
sincos_s32 = -c;
|
||||
sincos_c32 = s;
|
||||
sincos_sin = -c;
|
||||
sincos_cos = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user