mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Move fmod/fmodf to builtins and bind them to the '%' operator
This commit is contained in:
parent
721d77012b
commit
c80bf35747
2
dist/asc.js
vendored
2
dist/asc.js
vendored
File diff suppressed because one or more lines are too long
2
dist/asc.js.map
vendored
2
dist/asc.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js
vendored
2
dist/assemblyscript.js
vendored
File diff suppressed because one or more lines are too long
2
dist/assemblyscript.js.map
vendored
2
dist/assemblyscript.js.map
vendored
File diff suppressed because one or more lines are too long
@ -821,7 +821,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
/** Compiles a readily resolved function instance. */
|
||||
compileFunction(instance: Function): bool {
|
||||
if (instance.is(CommonFlags.COMPILED)) return true;
|
||||
assert(!instance.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN) || instance.simpleName == "abort");
|
||||
assert(!instance.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN) || instance.internalName == "abort");
|
||||
instance.set(CommonFlags.COMPILED);
|
||||
|
||||
// check that modifiers are matching but still compile as-is
|
||||
@ -3227,16 +3227,44 @@ export class Compiler extends DiagnosticEmitter {
|
||||
expr = module.createBinary(BinaryOp.RemU64, leftExpr, rightExpr);
|
||||
break;
|
||||
}
|
||||
case TypeKind.F32:
|
||||
case TypeKind.F64: {
|
||||
// TODO: internal fmod, possibly simply imported from JS
|
||||
case TypeKind.F32: {
|
||||
let fmodPrototype = this.program.elementsLookup.get("fmodf");
|
||||
if (!fmodPrototype) {
|
||||
this.error(
|
||||
DiagnosticCode.Operation_not_supported,
|
||||
expression.range
|
||||
DiagnosticCode.Cannot_find_name_0,
|
||||
expression.range, "fmod"
|
||||
);
|
||||
expr = module.createUnreachable();
|
||||
break;
|
||||
}
|
||||
assert(fmodPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
let fmodInstance = (<FunctionPrototype>fmodPrototype).resolve();
|
||||
if (!(fmodInstance && this.compileFunction(fmodInstance))) {
|
||||
expr = module.createUnreachable();
|
||||
} else {
|
||||
expr = this.makeCallDirect(fmodInstance, [ leftExpr, rightExpr ]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TypeKind.F64: {
|
||||
let fmodPrototype = this.program.elementsLookup.get("fmod");
|
||||
if (!fmodPrototype) {
|
||||
this.error(
|
||||
DiagnosticCode.Cannot_find_name_0,
|
||||
expression.range, "fmod"
|
||||
);
|
||||
expr = module.createUnreachable();
|
||||
break;
|
||||
}
|
||||
assert(fmodPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
let fmodInstance = (<FunctionPrototype>fmodPrototype).resolve();
|
||||
if (!(fmodInstance && this.compileFunction(fmodInstance))) {
|
||||
expr = module.createUnreachable();
|
||||
} else {
|
||||
expr = this.makeCallDirect(fmodInstance, [ leftExpr, rightExpr ]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
this.error(
|
||||
|
@ -2514,7 +2514,7 @@ export class Function extends Element {
|
||||
this.signature = signature;
|
||||
this.memberOf = memberOf;
|
||||
this.flags = prototype.flags;
|
||||
if (!(prototype.is(CommonFlags.BUILTIN) || prototype.is(CommonFlags.DECLARE))) {
|
||||
if (!(prototype.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN) || prototype.is(CommonFlags.DECLARE))) {
|
||||
let localIndex = 0;
|
||||
if (memberOf && memberOf.kind == ElementKind.CLASS) {
|
||||
assert(this.is(CommonFlags.INSTANCE));
|
||||
|
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,9 +1,8 @@
|
||||
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) {
|
||||
globalScope["allocate_memory"] = function allocate_memory(size) {
|
||||
if (!(size >>>= 0))
|
||||
return 0;
|
||||
if (HEAP_OFFSET + size > HEAP.length) {
|
||||
@ -15,24 +14,25 @@ globalScope["allocate_memory"] = function allocate_memory(size) {
|
||||
if ((HEAP_OFFSET += size) & 7)
|
||||
HEAP_OFFSET = (HEAP_OFFSET | 7) + 1;
|
||||
return ptr;
|
||||
};
|
||||
};
|
||||
|
||||
globalScope["free_memory"] = function free_memory(ptr) {
|
||||
globalScope["free_memory"] = function free_memory(ptr) {
|
||||
// TODO
|
||||
};
|
||||
};
|
||||
|
||||
globalScope["move_memory"] = function move_memory(dest, src, n) {
|
||||
globalScope["move_memory"] = function move_memory(dest, src, n) {
|
||||
HEAP.copyWithin(dest, src, src + n);
|
||||
};
|
||||
};
|
||||
|
||||
globalScope["store"] = function store(ptr, val, off) {
|
||||
globalScope["store"] = function store(ptr, val, off) {
|
||||
if (typeof off === "number")
|
||||
ptr += off;
|
||||
HEAP[ptr] = val;
|
||||
};
|
||||
};
|
||||
|
||||
globalScope["load"] = function load(ptr) {
|
||||
globalScope["load"] = function load(ptr) {
|
||||
if (typeof off === "number")
|
||||
ptr += off;
|
||||
return HEAP[ptr];
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
(module
|
||||
(type $iiiiv (func (param i32 i32 i32 i32)))
|
||||
(type $v (func))
|
||||
(type $FFF (func (param f64 f64) (result f64)))
|
||||
(type $fff (func (param f32 f32) (result f32)))
|
||||
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
|
||||
(global $builtins/b (mut i32) (i32.const 0))
|
||||
(global $builtins/i (mut i32) (i32.const 0))
|
||||
@ -19,7 +21,731 @@
|
||||
(func $builtins/test (; 1 ;) (type $v)
|
||||
(nop)
|
||||
)
|
||||
(func $start (; 2 ;) (type $v)
|
||||
(func $fmod (; 2 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
|
||||
(local $2 i64)
|
||||
(local $3 i32)
|
||||
(local $4 i64)
|
||||
(local $5 i64)
|
||||
(local $6 i32)
|
||||
(local $7 i32)
|
||||
(local $8 f64)
|
||||
(block $folding-inner0
|
||||
(set_local $3
|
||||
(i32.wrap/i64
|
||||
(i64.and
|
||||
(i64.shr_u
|
||||
(tee_local $2
|
||||
(i64.reinterpret/f64
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(i64.const 52)
|
||||
)
|
||||
(i64.const 2047)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $6
|
||||
(i32.wrap/i64
|
||||
(i64.and
|
||||
(i64.shr_u
|
||||
(tee_local $5
|
||||
(i64.reinterpret/f64
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(i64.const 52)
|
||||
)
|
||||
(i64.const 2047)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $7
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $7
|
||||
(i64.eq
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 1)
|
||||
)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
(get_local $7)
|
||||
(f64.ne
|
||||
(tee_local $8
|
||||
(get_local $1)
|
||||
)
|
||||
(get_local $8)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $7)
|
||||
(i32.eq
|
||||
(get_local $3)
|
||||
(i32.const 2047)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(return
|
||||
(f64.div
|
||||
(f64.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(f64.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i64.le_u
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i64.eq
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $7
|
||||
(i32.wrap/i64
|
||||
(i64.shr_u
|
||||
(get_local $2)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(if (result i64)
|
||||
(get_local $3)
|
||||
(i64.or
|
||||
(i64.and
|
||||
(get_local $2)
|
||||
(i64.const 4503599627370495)
|
||||
)
|
||||
(i64.const 4503599627370496)
|
||||
)
|
||||
(block (result i64)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 12)
|
||||
)
|
||||
)
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(get_local $4)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $3
|
||||
(i32.sub
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $4)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.extend_u/i32
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $5
|
||||
(if (result i64)
|
||||
(get_local $6)
|
||||
(i64.or
|
||||
(i64.and
|
||||
(get_local $5)
|
||||
(i64.const 4503599627370495)
|
||||
)
|
||||
(i64.const 4503599627370496)
|
||||
)
|
||||
(block (result i64)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 12)
|
||||
)
|
||||
)
|
||||
(loop $continue|1
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(get_local $4)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $6
|
||||
(i32.sub
|
||||
(get_local $6)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $4)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.extend_u/i32
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $6)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|2
|
||||
(if
|
||||
(i32.gt_s
|
||||
(get_local $3)
|
||||
(get_local $6)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(tee_local $4
|
||||
(i64.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i64.eqz
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $3
|
||||
(i32.sub
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(tee_local $4
|
||||
(i64.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i64.eqz
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|3
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(get_local $2)
|
||||
(i64.const 52)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $3
|
||||
(i32.sub
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(f64.reinterpret/i64
|
||||
(i64.or
|
||||
(tee_local $2
|
||||
(select
|
||||
(i64.or
|
||||
(i64.sub
|
||||
(get_local $2)
|
||||
(i64.const 4503599627370496)
|
||||
)
|
||||
(i64.shl
|
||||
(i64.extend_u/i32
|
||||
(get_local $3)
|
||||
)
|
||||
(i64.const 52)
|
||||
)
|
||||
)
|
||||
(i64.shr_u
|
||||
(get_local $2)
|
||||
(i64.extend_u/i32
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $3)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.shl
|
||||
(i64.extend_u/i32
|
||||
(get_local $7)
|
||||
)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(f64.mul
|
||||
(f64.const 0)
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $fmodf (; 3 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||
(local $2 i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(local $5 i32)
|
||||
(local $6 i32)
|
||||
(local $7 f32)
|
||||
(local $8 i32)
|
||||
(block $folding-inner0
|
||||
(set_local $4
|
||||
(i32.and
|
||||
(i32.shr_u
|
||||
(tee_local $2
|
||||
(i32.reinterpret/f32
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(i32.const 23)
|
||||
)
|
||||
(i32.const 255)
|
||||
)
|
||||
)
|
||||
(set_local $6
|
||||
(i32.and
|
||||
(i32.shr_u
|
||||
(tee_local $5
|
||||
(i32.reinterpret/f32
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(i32.const 23)
|
||||
)
|
||||
(i32.const 255)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $3
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $3
|
||||
(i32.eqz
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $3)
|
||||
(f32.ne
|
||||
(tee_local $7
|
||||
(get_local $1)
|
||||
)
|
||||
(get_local $7)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $3)
|
||||
(i32.eq
|
||||
(get_local $4)
|
||||
(i32.const 255)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(return
|
||||
(f32.div
|
||||
(f32.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(f32.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i32.eq
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $8
|
||||
(i32.and
|
||||
(get_local $2)
|
||||
(i32.const -2147483648)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(if (result i32)
|
||||
(get_local $4)
|
||||
(i32.or
|
||||
(i32.and
|
||||
(get_local $2)
|
||||
(i32.const 8388607)
|
||||
)
|
||||
(i32.const 8388608)
|
||||
)
|
||||
(block (result i32)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 9)
|
||||
)
|
||||
)
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(get_local $3)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $4
|
||||
(i32.sub
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $5
|
||||
(if (result i32)
|
||||
(get_local $6)
|
||||
(i32.or
|
||||
(i32.and
|
||||
(get_local $5)
|
||||
(i32.const 8388607)
|
||||
)
|
||||
(i32.const 8388608)
|
||||
)
|
||||
(block (result i32)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 9)
|
||||
)
|
||||
)
|
||||
(loop $continue|1
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(get_local $3)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $6
|
||||
(i32.sub
|
||||
(get_local $6)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $6)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|2
|
||||
(if
|
||||
(i32.gt_s
|
||||
(get_local $4)
|
||||
(get_local $6)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(tee_local $3
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i32.eqz
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i32.sub
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(tee_local $3
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i32.eqz
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|3
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(get_local $2)
|
||||
(i32.const 23)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $4
|
||||
(i32.sub
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(f32.reinterpret/i32
|
||||
(i32.or
|
||||
(tee_local $2
|
||||
(select
|
||||
(i32.or
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 8388608)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $4)
|
||||
(i32.const 23)
|
||||
)
|
||||
)
|
||||
(i32.shr_u
|
||||
(get_local $2)
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $4)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $8)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(f32.mul
|
||||
(f32.const 0)
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $start (; 4 ;) (type $v)
|
||||
(local $0 f32)
|
||||
(local $1 f64)
|
||||
(local $2 i32)
|
||||
@ -840,5 +1566,209 @@
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f64.eq
|
||||
(tee_local $1
|
||||
(call $fmod
|
||||
(f64.const 1)
|
||||
(f64.const nan:0x8000000000000)
|
||||
)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 295)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f64.ne
|
||||
(call $fmod
|
||||
(f64.const 1.5)
|
||||
(f64.const 1)
|
||||
)
|
||||
(f64.const 0.5)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 296)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f64.lt
|
||||
(f64.sub
|
||||
(call $fmod
|
||||
(f64.const 9.2)
|
||||
(f64.const 2)
|
||||
)
|
||||
(f64.const 1.2)
|
||||
)
|
||||
(f64.const 2.220446049250313e-16)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 297)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f64.lt
|
||||
(f64.sub
|
||||
(call $fmod
|
||||
(f64.const 9.2)
|
||||
(f64.const 3.7)
|
||||
)
|
||||
(f64.const 1.8)
|
||||
)
|
||||
(f64.const 2.220446049250313e-16)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 298)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f32.eq
|
||||
(tee_local $0
|
||||
(call $fmodf
|
||||
(f32.const 1)
|
||||
(f32.const nan:0x400000)
|
||||
)
|
||||
)
|
||||
(get_local $0)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 300)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f32.ne
|
||||
(call $fmodf
|
||||
(f32.const 1.5)
|
||||
(f32.const 1)
|
||||
)
|
||||
(f32.const 0.5)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 301)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f32.lt
|
||||
(f32.sub
|
||||
(call $fmodf
|
||||
(f32.const 9.199999809265137)
|
||||
(f32.const 2)
|
||||
)
|
||||
(f32.const 1.2000000476837158)
|
||||
)
|
||||
(f32.const 1.1920928955078125e-07)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 302)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f32.lt
|
||||
(f32.sub
|
||||
(call $fmodf
|
||||
(f32.const 9.199999809265137)
|
||||
(f32.const 3.700000047683716)
|
||||
)
|
||||
(f32.const 1.7999999523162842)
|
||||
)
|
||||
(f32.const 1.1920928955078125e-07)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 303)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f64.ne
|
||||
(call $fmod
|
||||
(f64.const 1.5)
|
||||
(f64.const 1)
|
||||
)
|
||||
(f64.const 0.5)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 305)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f32.ne
|
||||
(call $fmodf
|
||||
(f32.const 1.5)
|
||||
(f32.const 1)
|
||||
)
|
||||
(f32.const 0.5)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 306)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -292,6 +292,19 @@ assert(f64.MIN_SAFE_INTEGER == -9007199254740991);
|
||||
assert(f64.MAX_SAFE_INTEGER == 9007199254740991);
|
||||
assert(f64.EPSILON == 2.2204460492503131e-16);
|
||||
|
||||
assert(isNaN<f64>(fmod(1, NaN)));
|
||||
assert(fmod(1.5, 1.0) == 0.5); // exactly 0.5 (as in C)
|
||||
assert(fmod(9.2, 2.0) - 1.2 < f64.EPSILON); // not exactly 1.2 (as in C)
|
||||
assert(fmod(9.2, 3.7) - 1.8 < f64.EPSILON); // not exactly 1.8 (as in C)
|
||||
|
||||
assert(isNaN<f32>(fmodf(1, NaN)));
|
||||
assert(fmodf(1.5, 1.0) == 0.5);
|
||||
assert(fmodf(9.2, 2.0) - 1.2 < f32.EPSILON);
|
||||
assert(fmodf(9.2, 3.7) - 1.8 < f32.EPSILON);
|
||||
|
||||
assert(1.5 % 1.0 == 0.5); // should implicitly call fmod
|
||||
assert(<f32>1.5 % 1.0 == 0.5); // should implicitly call fmodf
|
||||
|
||||
import {
|
||||
isNaN as isItNaN
|
||||
} from "builtins";
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,909 +0,0 @@
|
||||
(module
|
||||
(type $FFF (func (param f64 f64) (result f64)))
|
||||
(type $iiiiv (func (param i32 i32 i32 i32)))
|
||||
(type $fff (func (param f32 f32) (result f32)))
|
||||
(type $v (func))
|
||||
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
|
||||
(memory $0 1)
|
||||
(data (i32.const 4) "\07\00\00\00f\00m\00o\00d\00.\00t\00s")
|
||||
(export "fmod" (func $fmod/fmod))
|
||||
(export "fmodf" (func $fmod/fmodf))
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $fmod/fmod (; 1 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
|
||||
(local $2 i64)
|
||||
(local $3 i32)
|
||||
(local $4 i64)
|
||||
(local $5 i64)
|
||||
(local $6 i32)
|
||||
(local $7 i32)
|
||||
(local $8 f64)
|
||||
(block $folding-inner0
|
||||
(set_local $3
|
||||
(i32.wrap/i64
|
||||
(i64.and
|
||||
(i64.shr_u
|
||||
(tee_local $2
|
||||
(i64.reinterpret/f64
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(i64.const 52)
|
||||
)
|
||||
(i64.const 2047)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $6
|
||||
(i32.wrap/i64
|
||||
(i64.and
|
||||
(i64.shr_u
|
||||
(tee_local $5
|
||||
(i64.reinterpret/f64
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(i64.const 52)
|
||||
)
|
||||
(i64.const 2047)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $7
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $7
|
||||
(i64.eq
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 1)
|
||||
)
|
||||
(i64.const 0)
|
||||
)
|
||||
)
|
||||
(get_local $7)
|
||||
(f64.ne
|
||||
(tee_local $8
|
||||
(get_local $1)
|
||||
)
|
||||
(get_local $8)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $7)
|
||||
(i32.eq
|
||||
(get_local $3)
|
||||
(i32.const 2047)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(return
|
||||
(f64.div
|
||||
(f64.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(f64.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i64.le_u
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i64.eq
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $7
|
||||
(i32.wrap/i64
|
||||
(i64.shr_u
|
||||
(get_local $2)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(if (result i64)
|
||||
(get_local $3)
|
||||
(i64.or
|
||||
(i64.and
|
||||
(get_local $2)
|
||||
(i64.const 4503599627370495)
|
||||
)
|
||||
(i64.const 4503599627370496)
|
||||
)
|
||||
(block (result i64)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 12)
|
||||
)
|
||||
)
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(get_local $4)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $3
|
||||
(i32.sub
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $4)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.extend_u/i32
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $5
|
||||
(if (result i64)
|
||||
(get_local $6)
|
||||
(i64.or
|
||||
(i64.and
|
||||
(get_local $5)
|
||||
(i64.const 4503599627370495)
|
||||
)
|
||||
(i64.const 4503599627370496)
|
||||
)
|
||||
(block (result i64)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.const 12)
|
||||
)
|
||||
)
|
||||
(loop $continue|1
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(get_local $4)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $6
|
||||
(i32.sub
|
||||
(get_local $6)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i64.shl
|
||||
(get_local $4)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.shl
|
||||
(get_local $5)
|
||||
(i64.extend_u/i32
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $6)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|2
|
||||
(if
|
||||
(i32.gt_s
|
||||
(get_local $3)
|
||||
(get_local $6)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(tee_local $4
|
||||
(i64.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i64.eqz
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $3
|
||||
(i32.sub
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(tee_local $4
|
||||
(i64.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i64.eqz
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|3
|
||||
(if
|
||||
(i64.eqz
|
||||
(i64.shr_u
|
||||
(get_local $2)
|
||||
(i64.const 52)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $3
|
||||
(i32.sub
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i64.shl
|
||||
(get_local $2)
|
||||
(i64.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(f64.reinterpret/i64
|
||||
(i64.or
|
||||
(tee_local $2
|
||||
(select
|
||||
(i64.or
|
||||
(i64.sub
|
||||
(get_local $2)
|
||||
(i64.const 4503599627370496)
|
||||
)
|
||||
(i64.shl
|
||||
(i64.extend_u/i32
|
||||
(get_local $3)
|
||||
)
|
||||
(i64.const 52)
|
||||
)
|
||||
)
|
||||
(i64.shr_u
|
||||
(get_local $2)
|
||||
(i64.extend_u/i32
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $3)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.shl
|
||||
(i64.extend_u/i32
|
||||
(get_local $7)
|
||||
)
|
||||
(i64.const 63)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(f64.mul
|
||||
(f64.const 0)
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $fmod/fmodf (; 2 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||
(local $2 i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(local $5 i32)
|
||||
(local $6 i32)
|
||||
(local $7 f32)
|
||||
(local $8 i32)
|
||||
(block $folding-inner0
|
||||
(set_local $4
|
||||
(i32.and
|
||||
(i32.shr_u
|
||||
(tee_local $2
|
||||
(i32.reinterpret/f32
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(i32.const 23)
|
||||
)
|
||||
(i32.const 255)
|
||||
)
|
||||
)
|
||||
(set_local $6
|
||||
(i32.and
|
||||
(i32.shr_u
|
||||
(tee_local $5
|
||||
(i32.reinterpret/f32
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(i32.const 23)
|
||||
)
|
||||
(i32.const 255)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $3
|
||||
(i32.and
|
||||
(if (result i32)
|
||||
(tee_local $3
|
||||
(i32.eqz
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $3)
|
||||
(f32.ne
|
||||
(tee_local $7
|
||||
(get_local $1)
|
||||
)
|
||||
(get_local $7)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $3)
|
||||
(i32.eq
|
||||
(get_local $4)
|
||||
(i32.const 255)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(return
|
||||
(f32.div
|
||||
(f32.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(f32.mul
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i32.eq
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $8
|
||||
(i32.and
|
||||
(get_local $2)
|
||||
(i32.const -2147483648)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(if (result i32)
|
||||
(get_local $4)
|
||||
(i32.or
|
||||
(i32.and
|
||||
(get_local $2)
|
||||
(i32.const 8388607)
|
||||
)
|
||||
(i32.const 8388608)
|
||||
)
|
||||
(block (result i32)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 9)
|
||||
)
|
||||
)
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(get_local $3)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $4
|
||||
(i32.sub
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $5
|
||||
(if (result i32)
|
||||
(get_local $6)
|
||||
(i32.or
|
||||
(i32.and
|
||||
(get_local $5)
|
||||
(i32.const 8388607)
|
||||
)
|
||||
(i32.const 8388608)
|
||||
)
|
||||
(block (result i32)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.const 9)
|
||||
)
|
||||
)
|
||||
(loop $continue|1
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(get_local $3)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $6
|
||||
(i32.sub
|
||||
(get_local $6)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $3
|
||||
(i32.shl
|
||||
(get_local $3)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $5)
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $6)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|2
|
||||
(if
|
||||
(i32.gt_s
|
||||
(get_local $4)
|
||||
(get_local $6)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(tee_local $3
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i32.eqz
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i32.sub
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(tee_local $3
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(i32.const 31)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(br_if $folding-inner0
|
||||
(i32.eqz
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|3
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.shr_u
|
||||
(get_local $2)
|
||||
(i32.const 23)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $4
|
||||
(i32.sub
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.shl
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(f32.reinterpret/i32
|
||||
(i32.or
|
||||
(tee_local $2
|
||||
(select
|
||||
(i32.or
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 8388608)
|
||||
)
|
||||
(i32.shl
|
||||
(get_local $4)
|
||||
(i32.const 23)
|
||||
)
|
||||
)
|
||||
(i32.shr_u
|
||||
(get_local $2)
|
||||
(i32.sub
|
||||
(i32.const 1)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(i32.gt_s
|
||||
(get_local $4)
|
||||
(i32.const 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $8)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(f32.mul
|
||||
(f32.const 0)
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(func $start (; 3 ;) (type $v)
|
||||
(local $0 f64)
|
||||
(local $1 f32)
|
||||
(if
|
||||
(f64.eq
|
||||
(tee_local $0
|
||||
(call $fmod/fmod
|
||||
(f64.const 1)
|
||||
(f64.const nan:0x8000000000000)
|
||||
)
|
||||
)
|
||||
(get_local $0)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 65)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f64.ne
|
||||
(call $fmod/fmod
|
||||
(f64.const 1.5)
|
||||
(f64.const 1)
|
||||
)
|
||||
(f64.const 0.5)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 66)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f64.lt
|
||||
(f64.sub
|
||||
(call $fmod/fmod
|
||||
(f64.const 9.2)
|
||||
(f64.const 2)
|
||||
)
|
||||
(f64.const 1.2)
|
||||
)
|
||||
(f64.const 2.220446049250313e-16)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 67)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f64.lt
|
||||
(f64.sub
|
||||
(call $fmod/fmod
|
||||
(f64.const 9.2)
|
||||
(f64.const 3.7)
|
||||
)
|
||||
(f64.const 1.8)
|
||||
)
|
||||
(f64.const 2.220446049250313e-16)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 68)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f32.eq
|
||||
(tee_local $1
|
||||
(call $fmod/fmodf
|
||||
(f32.const 1)
|
||||
(f32.const nan:0x400000)
|
||||
)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 134)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(f32.ne
|
||||
(call $fmod/fmodf
|
||||
(f32.const 1.5)
|
||||
(f32.const 1)
|
||||
)
|
||||
(f32.const 0.5)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 135)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f32.lt
|
||||
(f32.sub
|
||||
(call $fmod/fmodf
|
||||
(f32.const 9.199999809265137)
|
||||
(f32.const 2)
|
||||
)
|
||||
(f32.const 1.2000000476837158)
|
||||
)
|
||||
(f32.const 1.1920928955078125e-07)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 136)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(f32.lt
|
||||
(f32.sub
|
||||
(call $fmod/fmodf
|
||||
(f32.const 9.199999809265137)
|
||||
(f32.const 3.700000047683716)
|
||||
)
|
||||
(f32.const 1.7999999523162842)
|
||||
)
|
||||
(f32.const 1.1920928955078125e-07)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(call $abort
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
(i32.const 137)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
@ -1,137 +0,0 @@
|
||||
export function fmod(x: f64, y: f64): f64 {
|
||||
// the following is 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
|
||||
if (!ex) {
|
||||
for (var 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);
|
||||
}
|
||||
|
||||
assert(isNaN<f64>(fmod(1, NaN)));
|
||||
assert(fmod(1.5, 1.0) == 0.5); // exactly 0.5 (as in C)
|
||||
assert(fmod(9.2, 2.0) - 1.2 < f64.EPSILON); // not exactly 1.2 (as in C)
|
||||
assert(fmod(9.2, 3.7) - 1.8 < f64.EPSILON); // not exactly 1.8 (as in C)
|
||||
|
||||
export function fmodf(x: f32, y: f32): f32 {
|
||||
// the following is 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
|
||||
if (!ex) {
|
||||
for (var 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);
|
||||
}
|
||||
|
||||
assert(isNaN<f32>(fmodf(1, NaN)));
|
||||
assert(fmodf(1.5, 1.0) == 0.5);
|
||||
assert(fmodf(9.2, 2.0) - 1.2 < f32.EPSILON);
|
||||
assert(fmodf(9.2, 3.7) - 1.8 < f32.EPSILON);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -85,7 +85,6 @@ export function anExportedFunction(): void { }
|
||||
// be implemented already. Here are a few more sophisitcated examples of code that'll most likely
|
||||
// make it into the standard library eventually:
|
||||
import "./memcpy"; // until replaced by the proposed `move_memory` intrinsic (sic.)
|
||||
import "./fmod"; // for floating point modulus support, e.g., `1.5 % 1.0`
|
||||
|
||||
// Speaking of classes: Some preliminary work has already been done, so while we can't properly
|
||||
// instantiate them yet, we can point them at some raw memory
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user