mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-12 22:41:27 +00:00
Move fmod/fmodf to builtins and bind them to the '%' operator
This commit is contained in:
4
std/assembly.d.ts
vendored
4
std/assembly.d.ts
vendored
@ -249,6 +249,10 @@ declare function parseI32(str: string, radix?: i32): i32;
|
||||
declare function parseI64(str: string, radix?: i32): i64;
|
||||
/** Parses a string to a 64-bit float. */
|
||||
declare function parseFloat(str: string): f64;
|
||||
/** Returns the 64-bit floating-point remainder of `x/y`. */
|
||||
declare function fmod(x: f64, y: f64): f64;
|
||||
/** Returns the 32-bit floating-point remainder of `x/y`. */
|
||||
declare function fmodf(x: f32, y: f32): f32;
|
||||
|
||||
// Standard library
|
||||
|
||||
|
@ -172,3 +172,123 @@ export namespace f64 {
|
||||
export declare const HEAP_BASE: usize;
|
||||
|
||||
export declare function start(): void;
|
||||
|
||||
export function fmod(x: f64, y: f64): f64 {
|
||||
// based on musl's implementation of fmod
|
||||
var ux = reinterpret<u64>(x);
|
||||
var uy = reinterpret<u64>(y);
|
||||
var ex = <i32>(ux >> 52 & 0x7ff);
|
||||
var ey = <i32>(uy >> 52 & 0x7ff);
|
||||
var sx = <i32>(ux >> 63);
|
||||
|
||||
if (uy << 1 == 0 || isNaN<f64>(y) || ex == 0x7ff) {
|
||||
return (x * y) / (x * y);
|
||||
}
|
||||
if (ux << 1 <= uy << 1) {
|
||||
if (ux << 1 == uy << 1) return 0 * x;
|
||||
return x;
|
||||
}
|
||||
|
||||
// normalize x and y
|
||||
var i: u64;
|
||||
if (!ex) {
|
||||
for (i = ux << 12; !(i >> 63); i <<= 1) --ex;
|
||||
ux <<= -ex + 1;
|
||||
} else {
|
||||
ux &= <u64>-1 >> 12;
|
||||
ux |= 1 << 52;
|
||||
}
|
||||
if (!ey) {
|
||||
for (i = uy << 12; !(i >> 63); i <<= 1) --ey;
|
||||
uy <<= -ey + 1;
|
||||
} else {
|
||||
uy &= <u64>-1 >> 12;
|
||||
uy |= 1 << 52;
|
||||
}
|
||||
|
||||
// x mod y
|
||||
for (; ex > ey; ex--) {
|
||||
i = ux - uy;
|
||||
if (!(i >> 63)) {
|
||||
if (!i) return 0 * x;
|
||||
ux = i;
|
||||
}
|
||||
ux <<= 1;
|
||||
}
|
||||
i = ux - uy;
|
||||
if (!(i >> 63)) {
|
||||
if (!i) return 0 * x;
|
||||
ux = i;
|
||||
}
|
||||
for (; !(ux >> 52); ux <<= 1) --ex;
|
||||
|
||||
// scale result
|
||||
if (ex > 0) {
|
||||
ux -= 1 << 52;
|
||||
ux |= <u64>ex << 52;
|
||||
} else {
|
||||
ux >>= -ex + 1;
|
||||
}
|
||||
ux |= <u64>sx << 63;
|
||||
return reinterpret<f64>(ux);
|
||||
}
|
||||
|
||||
export function fmodf(x: f32, y: f32): f32 {
|
||||
// based on musl's implementation of fmodf
|
||||
var ux = reinterpret<u32>(x);
|
||||
var uy = reinterpret<u32>(y);
|
||||
var ex = <i32>(ux >> 23 & 0xff);
|
||||
var ey = <i32>(uy >> 23 & 0xff);
|
||||
var sx = ux & 0x80000000;
|
||||
|
||||
if (uy << 1 == 0 || isNaN<f32>(y) || ex == 0xff) {
|
||||
return (x * y) / (x * y);
|
||||
}
|
||||
if (ux << 1 <= uy << 1) {
|
||||
if (ux << 1 == uy << 1) return 0 * x;
|
||||
return x;
|
||||
}
|
||||
|
||||
// normalize x and y
|
||||
var i: u32;
|
||||
if (!ex) {
|
||||
for (i = ux << 9; !(i >> 31); i <<= 1) --ex;
|
||||
ux <<= -ex + 1;
|
||||
} else {
|
||||
ux &= <u32>-1 >> 9;
|
||||
ux |= 1 << 23;
|
||||
}
|
||||
if (!ey) {
|
||||
for (i = uy << 9; !(i >> 31); i <<= 1) --ey;
|
||||
uy <<= -ey + 1;
|
||||
} else {
|
||||
uy &= <u32>-1 >> 9;
|
||||
uy |= 1 << 23;
|
||||
}
|
||||
|
||||
// x mod y
|
||||
for (; ex > ey; --ex) {
|
||||
i = ux - uy;
|
||||
if (!(i >> 31)) {
|
||||
if (!i) return 0 * x;
|
||||
ux = i;
|
||||
}
|
||||
ux <<= 1;
|
||||
}
|
||||
i = ux - uy;
|
||||
if (!(i >> 31)) {
|
||||
if (!i) return 0 * x;
|
||||
ux = i;
|
||||
}
|
||||
for (; !(ux >> 23); ux <<= 1) --ex;
|
||||
|
||||
// scale result
|
||||
if (ex > 0) {
|
||||
ux -= 1 << 23;
|
||||
ux |= <u32>ex << 23;
|
||||
} else {
|
||||
ux >>= -ex + 1;
|
||||
}
|
||||
ux |= sx;
|
||||
return reinterpret<f32>(ux);
|
||||
}
|
||||
|
95
std/portable.d.ts
vendored
95
std/portable.d.ts
vendored
@ -193,6 +193,10 @@ declare function parseInt(str: string, radix?: i32): f64;
|
||||
declare function parseI32(str: string, radix?: i32): i32;
|
||||
/** Parses a floating point string to a 64-bit float. */
|
||||
declare function parseFloat(str: string): f64;
|
||||
/** Returns the 64-bit floating-point remainder of `x/y`. */
|
||||
declare function fmod(x: f64, y: f64): f64;
|
||||
/** Returns the 32-bit floating-point remainder of `x/y`. */
|
||||
declare function fmodf(x: f32, y: f32): f32;
|
||||
|
||||
// Portable standard library
|
||||
// Everything marked @deprecated is a temporary filler. Do not use.
|
||||
@ -310,52 +314,55 @@ interface Iterable<T> {
|
||||
|
||||
interface Iterator<T> {}
|
||||
|
||||
declare namespace Math {
|
||||
export const E: f64;
|
||||
export const LN2: f64;
|
||||
export const LN10: f64;
|
||||
export const LOG2E: f64;
|
||||
export const LOG10E: f64;
|
||||
export const PI: f64;
|
||||
export const SQRT1_2: f64;
|
||||
export const SQRT2: f64;
|
||||
export function abs(x: f64): f64;
|
||||
export function acos(x: f64): f64;
|
||||
export function acosh(x: f64): f64;
|
||||
export function asin(x: f64): f64;
|
||||
export function asinh(x: f64): f64;
|
||||
export function atan(x: f64): f64;
|
||||
export function atan2(y: f64, x: f64): f64;
|
||||
export function atanh(x: f64): f64;
|
||||
export function cbrt(x: f64): f64;
|
||||
export function ceil(x: f64): f64;
|
||||
export function clz32(x: f64): i32;
|
||||
export function cos(x: f64): f64;
|
||||
export function cosh(x: f64): f64;
|
||||
export function exp(x: f64): f64;
|
||||
export function expm1(x: f64): f64;
|
||||
export function floor(x: f64): f64;
|
||||
export function fround(x: f64): f32;
|
||||
export function hypot(value1: f64, value2: f64): f64; // TODO: see std/math
|
||||
export function imul(a: f64, b: f64): i32;
|
||||
export function log(x: f64): f64;
|
||||
export function log10(x: f64): f64;
|
||||
export function log1p(x: f64): f64;
|
||||
export function log2(x: f64): f64;
|
||||
export function max(value1: f64, value2: f64): f64; // TODO: see std/math
|
||||
export function min(value1: f64, value2: f64): f64; // TODO: see std/math
|
||||
export function pow(base: f64, exponent: f64): f64;
|
||||
export function random(): f64;
|
||||
export function round(x: f64): f64;
|
||||
export function sign(x: f64): f64;
|
||||
export function sin(x: f64): f64;
|
||||
export function sinh(x: f64): f64;
|
||||
export function sqrt(x: f64): f64;
|
||||
export function tan(x: f64): f64;
|
||||
export function tanh(x: f64): f64;
|
||||
export function trunc(x: f64): f64;
|
||||
interface IMath {
|
||||
readonly E: f64;
|
||||
readonly LN2: f64;
|
||||
readonly LN10: f64;
|
||||
readonly LOG2E: f64;
|
||||
readonly LOG10E: f64;
|
||||
readonly PI: f64;
|
||||
readonly SQRT1_2: f64;
|
||||
readonly SQRT2: f64;
|
||||
abs(x: f64): f64;
|
||||
acos(x: f64): f64;
|
||||
acosh(x: f64): f64;
|
||||
asin(x: f64): f64;
|
||||
asinh(x: f64): f64;
|
||||
atan(x: f64): f64;
|
||||
atan2(y: f64, x: f64): f64;
|
||||
atanh(x: f64): f64;
|
||||
cbrt(x: f64): f64;
|
||||
ceil(x: f64): f64;
|
||||
clz32(x: f64): i32;
|
||||
cos(x: f64): f64;
|
||||
cosh(x: f64): f64;
|
||||
exp(x: f64): f64;
|
||||
expm1(x: f64): f64;
|
||||
floor(x: f64): f64;
|
||||
fround(x: f64): f32;
|
||||
hypot(value1: f64, value2: f64): f64; // TODO: see std/math
|
||||
imul(a: f64, b: f64): i32;
|
||||
log(x: f64): f64;
|
||||
log10(x: f64): f64;
|
||||
log1p(x: f64): f64;
|
||||
log2(x: f64): f64;
|
||||
max(value1: f64, value2: f64): f64; // TODO: see std/math
|
||||
min(value1: f64, value2: f64): f64; // TODO: see std/math
|
||||
pow(base: f64, exponent: f64): f64;
|
||||
random(): f64;
|
||||
round(x: f64): f64;
|
||||
sign(x: f64): f64;
|
||||
sin(x: f64): f64;
|
||||
sinh(x: f64): f64;
|
||||
sqrt(x: f64): f64;
|
||||
tan(x: f64): f64;
|
||||
tanh(x: f64): f64;
|
||||
trunc(x: f64): f64;
|
||||
}
|
||||
|
||||
declare const Math: IMath;
|
||||
declare const JSMath: IMath;
|
||||
|
||||
declare namespace console {
|
||||
/** @deprecated */
|
||||
function log(message: string): void;
|
||||
|
@ -169,4 +169,13 @@ globalScope["isString"] = function isString(arg) {
|
||||
|
||||
globalScope["isArray"] = Array.isArray;
|
||||
|
||||
require("./portable/memory");
|
||||
globalScope["fmod"] = function fmod(x, y) {
|
||||
return x % y;
|
||||
};
|
||||
|
||||
globalScope["fmodf"] = function fmodf(x, y) {
|
||||
return Math.fround(x % y);
|
||||
};
|
||||
|
||||
require("./portable/math")(globalScope);
|
||||
require("./portable/memory")(globalScope);
|
||||
|
3
std/portable/math.js
Normal file
3
std/portable/math.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = globalScope => {
|
||||
globalScope["JSMath"] = Math;
|
||||
};
|
@ -1,38 +1,38 @@
|
||||
var globalScope = typeof window !== "undefined" && window || typeof global !== "undefined" && global || self;
|
||||
module.exports = globalScope => {
|
||||
var HEAP = new Uint8Array(0);
|
||||
var HEAP_OFFSET = 0;
|
||||
|
||||
var HEAP = new Uint8Array(0);
|
||||
var HEAP_OFFSET = 0;
|
||||
globalScope["allocate_memory"] = function allocate_memory(size) {
|
||||
if (!(size >>>= 0))
|
||||
return 0;
|
||||
if (HEAP_OFFSET + size > HEAP.length) {
|
||||
var oldHeap = HEAP;
|
||||
HEAP = new Uint8Array(Math.max(65536, HEAP.length + size, HEAP.length * 2));
|
||||
HEAP.set(oldHeap);
|
||||
}
|
||||
var ptr = HEAP_OFFSET;
|
||||
if ((HEAP_OFFSET += size) & 7)
|
||||
HEAP_OFFSET = (HEAP_OFFSET | 7) + 1;
|
||||
return ptr;
|
||||
};
|
||||
|
||||
globalScope["allocate_memory"] = function allocate_memory(size) {
|
||||
if (!(size >>>= 0))
|
||||
return 0;
|
||||
if (HEAP_OFFSET + size > HEAP.length) {
|
||||
var oldHeap = HEAP;
|
||||
HEAP = new Uint8Array(Math.max(65536, HEAP.length + size, HEAP.length * 2));
|
||||
HEAP.set(oldHeap);
|
||||
}
|
||||
var ptr = HEAP_OFFSET;
|
||||
if ((HEAP_OFFSET += size) & 7)
|
||||
HEAP_OFFSET = (HEAP_OFFSET | 7) + 1;
|
||||
return ptr;
|
||||
};
|
||||
|
||||
globalScope["free_memory"] = function free_memory(ptr) {
|
||||
// TODO
|
||||
};
|
||||
|
||||
globalScope["move_memory"] = function move_memory(dest, src, n) {
|
||||
HEAP.copyWithin(dest, src, src + n);
|
||||
};
|
||||
|
||||
globalScope["store"] = function store(ptr, val, off) {
|
||||
if (typeof off === "number")
|
||||
ptr += off;
|
||||
HEAP[ptr] = val;
|
||||
};
|
||||
|
||||
globalScope["load"] = function load(ptr) {
|
||||
if (typeof off === "number")
|
||||
ptr += off;
|
||||
return HEAP[ptr];
|
||||
globalScope["free_memory"] = function free_memory(ptr) {
|
||||
// TODO
|
||||
};
|
||||
|
||||
globalScope["move_memory"] = function move_memory(dest, src, n) {
|
||||
HEAP.copyWithin(dest, src, src + n);
|
||||
};
|
||||
|
||||
globalScope["store"] = function store(ptr, val, off) {
|
||||
if (typeof off === "number")
|
||||
ptr += off;
|
||||
HEAP[ptr] = val;
|
||||
};
|
||||
|
||||
globalScope["load"] = function load(ptr) {
|
||||
if (typeof off === "number")
|
||||
ptr += off;
|
||||
return HEAP[ptr];
|
||||
};
|
||||
};
|
||||
|
Reference in New Issue
Block a user