Even more math (#56)

Remaining implementations of JavaScript's Math functions (except sin/cos/tan), both double (Math) and single (Mathf) precision, ported from musl incl. tests from libc-test, plus some changes to match JS semantics. Also binds fmod to `%` and pow to `**`.
This commit is contained in:
Daniel Wirtz 2018-03-30 17:25:54 +02:00 committed by GitHub
parent e47a130771
commit 164f134053
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 143290 additions and 15143 deletions

249
NOTICE
View File

@ -1,39 +1,248 @@
Copyright (c) 2017-2018 AssemblyScript authors. Copyright (c) 2017-2018 AssemblyScript authors.
The following authors have all licensed their contributions to AssemblyScript The following authors have all licensed their contributions to AssemblyScript
under the licensing terms detailed in LICENSE. under the licensing terms detailed in LICENSE:
* Daniel Wirtz <dcode@dcode.io> * Daniel Wirtz <dcode@dcode.io>
* Max Graey <maxgraey@gmail.com> * Max Graey <maxgraey@gmail.com>
* Igor Sbitnev <PinkaminaDianePie@gmail.com> * Igor Sbitnev <PinkaminaDianePie@gmail.com>
* Norton Wang <me@nortonwang.com> * Norton Wang <me@nortonwang.com>
================================================================================ Portions of this software are derived from third-party works licensed under
the following terms:
This program includes parts of TypeScript: * TypeScript: https://github.com/Microsoft/TypeScript
https://github.com/Microsoft/TypeScript
Copyright (c) Microsoft Corporation. All rights reserved. Copyright (c) Microsoft Corporation. All rights reserved.
Apache License, Version 2.0 Apache License, Version 2.0 (see LICENSE file)
https://www.apache.org/licenses/LICENSE-2.0
================================================================================ * Binaryen: https://github.com/WebAssembly/binaryen
This program includes parts of Binaryen:
https://github.com/WebAssembly/binaryen
Copyright 2015 WebAssembly Community Group participants Copyright 2015 WebAssembly Community Group participants
Apache License, Version 2.0 Apache License, Version 2.0 (see LICENSE file)
https://www.apache.org/licenses/LICENSE-2.0
================================================================================ * musl: http://www.musl-libc.org
This program includes parts of musl: musl as a whole is licensed under the following standard MIT license:
http://www.musl-libc.org
----------------------------------------------------------------------
Copyright © 2005-2014 Rich Felker, et al. Copyright © 2005-2014 Rich Felker, et al.
MIT License
https://opensource.org/licenses/MIT Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
Authors/contributors include:
Alex Dowad
Alexander Monakov
Anthony G. Basile
Arvid Picciani
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Denys Vlasenko
Emil Renner Berthing
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Josiah Worcester
Justin Cormack
Khem Raj
Kylie McClain
Luca Barbato
Luka Perkov
M Farkas-Dyck (Strake)
Mahesh Bodapati
Michael Forney
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Petr Hosek
Pierre Carrier
Rich Felker
Richard Pennington
Shiz
sin
Solar Designer
Stefan Kristiansson
Szabolcs Nagy
Timo Teräs
Trutz Behn
Valentin Ochs
William Haddon
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/* and src/complex/*) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Valentin Ochs and is licensed under an MIT-style license.
The BSD PRNG implementation (src/prng/random.c) and XSI search API
(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
licensed under following terms: "Permission to use, copy, modify,
and/or distribute this code for any purpose with or without fee is
hereby granted. There is no warranty."
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/* and arch/*/bits/*) and crt files intended to be linked into
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.
* V8: https://developers.google.com/v8/
This license applies to all parts of V8 that are not externally
maintained libraries. The externally maintained libraries used by V8
are:
- PCRE test suite, located in
test/mjsunit/third_party/regexp-pcre/regexp-pcre.js. This is based on the
test suite from PCRE-7.3, which is copyrighted by the University
of Cambridge and Google, Inc. The copyright notice and license
are embedded in regexp-pcre.js.
- Layout tests, located in test/mjsunit/third_party/object-keys. These are
based on layout tests from webkit.org which are copyrighted by
Apple Computer, Inc. and released under a 3-clause BSD license.
- Strongtalk assembler, the basis of the files assembler-arm-inl.h,
assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h,
assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h,
assembler-mips.cc, assembler-mips.h, assembler.cc and assembler.h.
This code is copyrighted by Sun Microsystems Inc. and released
under a 3-clause BSD license.
- Valgrind client API header, located at third_party/valgrind/valgrind.h
This is release under the BSD license.
These libraries have their own licenses; we recommend you read them,
as their terms may differ from the terms below.
Further license information can be found in LICENSE files located in
sub-directories.
Copyright 2014, the V8 project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -363,9 +363,12 @@ exports.main = function main(argv, options, callback) {
assemblyscript.setImportTable(compilerOptions, !!args.importTable); assemblyscript.setImportTable(compilerOptions, !!args.importTable);
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0); assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null); assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
// Add or override global aliases if specified // Initialize default aliases
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
assemblyscript.setGlobalAlias(compilerOptions, "Mathf", "NativeMathf");
// Add or override aliases if specified
var aliases = args.use; var aliases = args.use;
if (aliases != null) { if (aliases != null) {
if (typeof aliases === "string") aliases = aliases.split(","); if (typeof aliases === "string") aliases = aliases.split(",");

View File

@ -10,7 +10,8 @@
<p> <p>
<label for="f64"><input id="f64" name="precision" value="f64" type="radio" checked /> f64</label> <label for="f64"><input id="f64" name="precision" value="f64" type="radio" checked /> f64</label>
<label for="f32"><input id="f32" name="precision" value="f32" type="radio" /> f32</label> <label for="f32"><input id="f32" name="precision" value="f32" type="radio" /> f32</label>
<input id="name" type="text" value="test" /> <input id="pre" type="text" value="test(" />
<input id="post" type="text" value=");" />
<button>Convert</button> <button>Convert</button>
</p> </p>
<p><textarea cols="120" rows="20" id="input"></textarea></p> <p><textarea cols="120" rows="20" id="input"></textarea></p>
@ -21,17 +22,19 @@
<script> <script>
function convert(form) { function convert(form) {
var isF64 = document.getElementById("f64").checked; var isF64 = document.getElementById("f64").checked;
var name = document.getElementById("name").value; var pre = document.getElementById("pre").value;
var post = document.getElementById("post").value;
var input = document.getElementById("input").value; var input = document.getElementById("input").value;
document.getElementById("output").value = input document.getElementById("output").value = input
.replace(/\b(\-?0x[0-9a-fA-F]*(?:\.[0-9a-fA-F]+)?[pP][+-]?[0-9]+\b)/g, ($0, $1) => { .replace(/\b(\-?0x[0-9a-fA-F]*(?:\.[0-9a-fA-F]+)?[pP][+-]?[0-9]+\b)/g, ($0, $1) => {
var val = parse($1); var val = parse($1);
return val.toPrecision(isF64 ? 18 : 10); return val.toPrecision(isF64 ? 18 : 10);
}) })
.replace(/(\d\.[0-9])0+\b/g, "$1")
.replace(/\bnan\b/g, "NaN") .replace(/\bnan\b/g, "NaN")
.replace(/\binf\b/g, "Infinity") .replace(/\binf\b/g, "Infinity")
.replace(/^T\(R\w, */mg, name + "(") .replace(/^T\(R\w, */mg, pre)
.replace(/\)$/mg, ");") .replace(/\);?$/mg, post)
.replace(/ +/g, " "); .replace(/ +/g, " ");
} }
</script> </script>

View File

@ -2316,6 +2316,11 @@ export class Compiler extends DiagnosticEmitter {
return this.compileExpression(expression.expression, toType, ConversionKind.EXPLICIT); return this.compileExpression(expression.expression, toType, ConversionKind.EXPLICIT);
} }
private f32ModInstance: Function | null = null;
private f64ModInstance: Function | null = null;
private f32PowInstance: Function | null = null;
private f64PowInstance: Function | null = null;
compileBinaryExpression( compileBinaryExpression(
expression: BinaryExpression, expression: BinaryExpression,
contextualType: Type, contextualType: Type,
@ -3078,6 +3083,88 @@ export class Compiler extends DiagnosticEmitter {
} }
break; break;
} }
case Token.ASTERISK_ASTERISK_EQUALS: compound = true;
case Token.ASTERISK_ASTERISK: {
leftExpr = this.compileExpressionRetainType(
left,
contextualType,
true // must be wrapped
);
let instance: Function | null;
// Mathf.pow if lhs is f32 (result is f32)
if (this.currentType == Type.f32) {
rightExpr = this.compileExpression(
right,
this.currentType
);
if (!(instance = this.f32PowInstance)) {
let namespace = this.program.elementsLookup.get("Mathf");
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
expression.range, "Mathf"
);
expr = module.createUnreachable();
break;
}
let prototype = namespace.members ? namespace.members.get("pow") : null;
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
expression.range, "Mathf.pow"
);
expr = module.createUnreachable();
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f32PowInstance = instance = (<FunctionPrototype>prototype).resolve();
}
// Math.pow otherwise (result is f64)
// TODO: should the result be converted back?
} else {
leftExpr = this.convertExpression(
leftExpr,
this.currentType,
Type.f64,
ConversionKind.IMPLICIT,
left
);
rightExpr = this.compileExpression(
right,
Type.f64
);
if (!(instance = this.f64PowInstance)) {
let namespace = this.program.elementsLookup.get("Math");
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
expression.range, "Math"
);
expr = module.createUnreachable();
break;
}
let prototype = namespace.members ? namespace.members.get("pow") : null;
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
expression.range, "Math.pow"
);
expr = module.createUnreachable();
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f64PowInstance = instance = (<FunctionPrototype>prototype).resolve();
}
}
if (!(instance && this.compileFunction(instance))) {
expr = module.createUnreachable();
} else {
expr = this.makeCallDirect(instance, [ leftExpr, rightExpr ]);
}
break;
}
case Token.SLASH_EQUALS: compound = true; case Token.SLASH_EQUALS: compound = true;
case Token.SLASH: { case Token.SLASH: {
leftExpr = this.compileExpressionRetainType( leftExpr = this.compileExpressionRetainType(
@ -3269,40 +3356,64 @@ export class Compiler extends DiagnosticEmitter {
break; break;
} }
case TypeKind.F32: { case TypeKind.F32: {
let fmodPrototype = this.program.elementsLookup.get("fmodf"); let instance = this.f32ModInstance;
if (!fmodPrototype) { if (!instance) {
let namespace = this.program.elementsLookup.get("Mathf");
if (!namespace) {
this.error( this.error(
DiagnosticCode.Cannot_find_name_0, DiagnosticCode.Cannot_find_name_0,
expression.range, "fmod" expression.range, "Mathf"
); );
expr = module.createUnreachable(); expr = module.createUnreachable();
break; break;
} }
assert(fmodPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); let prototype = namespace.members ? namespace.members.get("mod") : null;
let fmodInstance = (<FunctionPrototype>fmodPrototype).resolve(); if (!prototype) {
if (!(fmodInstance && this.compileFunction(fmodInstance))) { this.error(
DiagnosticCode.Cannot_find_name_0,
expression.range, "Mathf.mod"
);
expr = module.createUnreachable();
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f32ModInstance = instance = (<FunctionPrototype>prototype).resolve();
}
if (!(instance && this.compileFunction(instance))) {
expr = module.createUnreachable(); expr = module.createUnreachable();
} else { } else {
expr = this.makeCallDirect(fmodInstance, [ leftExpr, rightExpr ]); expr = this.makeCallDirect(instance, [ leftExpr, rightExpr ]);
} }
break; break;
} }
case TypeKind.F64: { case TypeKind.F64: {
let fmodPrototype = this.program.elementsLookup.get("fmod"); let instance = this.f64ModInstance;
if (!fmodPrototype) { if (!instance) {
let namespace = this.program.elementsLookup.get("Math");
if (!namespace) {
this.error( this.error(
DiagnosticCode.Cannot_find_name_0, DiagnosticCode.Cannot_find_name_0,
expression.range, "fmod" expression.range, "Math"
); );
expr = module.createUnreachable(); expr = module.createUnreachable();
break; break;
} }
assert(fmodPrototype.kind == ElementKind.FUNCTION_PROTOTYPE); let prototype = namespace.members ? namespace.members.get("mod") : null;
let fmodInstance = (<FunctionPrototype>fmodPrototype).resolve(); if (!prototype) {
if (!(fmodInstance && this.compileFunction(fmodInstance))) { this.error(
DiagnosticCode.Cannot_find_name_0,
expression.range, "Math.mod"
);
expr = module.createUnreachable();
break;
}
assert(prototype.kind == ElementKind.FUNCTION_PROTOTYPE);
this.f64ModInstance = instance = (<FunctionPrototype>prototype).resolve();
}
if (!(instance && this.compileFunction(instance))) {
expr = module.createUnreachable(); expr = module.createUnreachable();
} else { } else {
expr = this.makeCallDirect(fmodInstance, [ leftExpr, rightExpr ]); expr = this.makeCallDirect(instance, [ leftExpr, rightExpr ]);
} }
break; break;
} }

18
std/assembly.d.ts vendored
View File

@ -135,6 +135,10 @@ declare namespace f32 {
export const MAX_SAFE_INTEGER: f32; export const MAX_SAFE_INTEGER: f32;
/** Difference between 1 and the smallest representable value greater than 1. */ /** Difference between 1 and the smallest representable value greater than 1. */
export const EPSILON: f32; export const EPSILON: f32;
/** Returns the floating-point remainder of `x / y` (rounded towards zero). */
export function mod(x: f32, y: f32): f32;
/** Returns the floating-point remainder of `x / y` (rounded to nearest). */
export function rem(x: f32, y: f32): f32;
} }
/** Converts any other numeric value to a 64-bit float. */ /** Converts any other numeric value to a 64-bit float. */
declare function f64(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): f64; declare function f64(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): f64;
@ -391,7 +395,7 @@ interface IMath<T> {
/** Returns the smallest integer greater than or equal to `x`. */ /** Returns the smallest integer greater than or equal to `x`. */
ceil(x: T): T; ceil(x: T): T;
/** Returns the number of leading zero bits in the 32-bit binary representation of `x`. */ /** Returns the number of leading zero bits in the 32-bit binary representation of `x`. */
clz32(x: T): i32; clz32(x: T): T;
/** Returns the cosine (in radians) of `x`. */ /** Returns the cosine (in radians) of `x`. */
cos(x: T): T; cos(x: T): T;
/** Returns the hyperbolic cosine of `x`. */ /** Returns the hyperbolic cosine of `x`. */
@ -407,7 +411,7 @@ interface IMath<T> {
/** Returns the square root of the sum of squares of its arguments. */ /** Returns the square root of the sum of squares of its arguments. */
hypot(value1: T, value2: T): T; // TODO: rest hypot(value1: T, value2: T): T; // TODO: rest
/** Returns the result of the C-like 32-bit multiplication of `a` and `b`. */ /** Returns the result of the C-like 32-bit multiplication of `a` and `b`. */
imul(a: T, b: T): i32; imul(a: T, b: T): T;
/** Returns the natural logarithm (base e) of `x`. */ /** Returns the natural logarithm (base e) of `x`. */
log(x: T): T; log(x: T): T;
/** Returns the base 10 logarithm of `x`. */ /** Returns the base 10 logarithm of `x`. */
@ -442,17 +446,21 @@ interface IMath<T> {
trunc(x: T): T; trunc(x: T): T;
} }
interface ISeedRandom { interface INativeMath<T> extends IMath<T> {
/** Seeds the random number generator. */ /** Seeds the random number generator. */
seedRandom(value: i64): void; seedRandom(value: i64): void;
/** Returns the floating-point remainder of `x / y` (rounded towards zero). */
mod(x: T, y: T): T;
/** Returns the floating-point remainder of `x / y` (rounded to nearest). */
rem(x: T, y: T): T;
} }
/** Double precision math imported from JavaScript. */ /** Double precision math imported from JavaScript. */
declare const JSMath: IMath<f64>; declare const JSMath: IMath<f64>;
/** Double precision math implemented natively. */ /** Double precision math implemented natively. */
declare const NativeMath: IMath<f64> & ISeedRandom; declare const NativeMath: INativeMath<f64>;
/** Single precision math implemented natively. */ /** Single precision math implemented natively. */
declare const NativeMathf: IMath<f32>; declare const NativeMathf: INativeMath<f32>;
/** Alias of {@link NativeMath} or {@link JSMath} respectively. Defaults to `NativeMath`. */ /** Alias of {@link NativeMath} or {@link JSMath} respectively. Defaults to `NativeMath`. */
declare const Math: IMath<f64>; declare const Math: IMath<f64>;

View File

@ -151,144 +151,24 @@ export namespace bool {
export declare function f32(value: void): f32; export declare function f32(value: void): f32;
export namespace f32 { export namespace f32 {
export const MIN_VALUE: f32 = -3.40282347e+38; export const MIN_VALUE = reinterpret<f32>(0xFF7FFFFF); // -0x1.fffffep+127f
export const MAX_VALUE: f32 = 3.40282347e+38; export const MAX_VALUE = reinterpret<f32>(0x7F7FFFFF); // 0x1.fffffep+127f
export const MIN_POSITIVE_VALUE: f32 = 1.175494351e-38; export const MIN_POSITIVE_VALUE = reinterpret<f32>(0x00800000); // 0x1p-126f
export const MIN_SAFE_INTEGER: f32 = -16777215; export const MIN_SAFE_INTEGER: f32 = -16777215;
export const MAX_SAFE_INTEGER: f32 = 16777215; export const MAX_SAFE_INTEGER: f32 = 16777215;
export const EPSILON: f32 = 1.19209290e-07; export const EPSILON = reinterpret<f32>(0x34000000); // 0x1p-23f
} }
export declare function f64(value: void): f64; export declare function f64(value: void): f64;
export namespace f64 { export namespace f64 {
export const MIN_VALUE: f64 = -1.7976931348623157e+308; export const MIN_VALUE = reinterpret<f64>(0xFFEFFFFFFFFFFFFF); // -0x1.fffffffffffffp+1023
export const MAX_VALUE: f64 = 1.7976931348623157e+308; export const MAX_VALUE = reinterpret<f64>(0x7FEFFFFFFFFFFFFF); // 0x1.fffffffffffffp+1023
export const MIN_POSITIVE_VALUE: f64 = 2.2250738585072014e-308; export const MIN_POSITIVE_VALUE = reinterpret<f64>(0x0010000000000000); // 0x1p-1022
export const MIN_SAFE_INTEGER: f64 = -9007199254740991; export const MIN_SAFE_INTEGER: f64 = -9007199254740991;
export const MAX_SAFE_INTEGER: f64 = 9007199254740991; export const MAX_SAFE_INTEGER: f64 = 9007199254740991;
export const EPSILON: f64 = 2.2204460492503131e-16; export const EPSILON = reinterpret<f64>(0x3CB0000000000000); // 0x1p-52
} }
export declare const HEAP_BASE: usize; export declare const HEAP_BASE: usize;
export declare function start(): void; 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);
}

File diff suppressed because it is too large Load Diff

View File

@ -444,6 +444,7 @@ function parse<T>(str: String, radix: i32 = 0): T {
return sign * num; return sign * num;
} }
// FIXME: naive implementation
export function parseFloat(str: String): f64 { export function parseFloat(str: String): f64 {
var len: i32 = str.length; var len: i32 = str.length;
if (!len) { if (!len) {

View File

@ -113,7 +113,7 @@ tests.forEach(filename => {
let exports = new WebAssembly.Instance(new WebAssembly.Module(stdout.toBuffer()), { let exports = new WebAssembly.Instance(new WebAssembly.Module(stdout.toBuffer()), {
env: { env: {
abort: function(msg, file, line, column) { abort: function(msg, file, line, column) {
// TODO console.log("abort called at " + line + ":" + column);
}, },
externalFunction: function() { }, externalFunction: function() { },
externalConstant: 1, externalConstant: 1,
@ -124,6 +124,9 @@ tests.forEach(filename => {
externalFunction: function() { }, externalFunction: function() { },
externalConstant: 2 externalConstant: 2
}, },
JSOp: {
mod: function(a, b) { return a % b; }
},
JSMath: Math JSMath: Math
}); });
}); });

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ i - 1;
i * 1; i * 1;
i / 1; i / 1;
i % 1; i % 1;
i ** 1;
i << 1; i << 1;
i >> 1; i >> 1;
i >>> 1; i >>> 1;
@ -31,6 +32,7 @@ i = i - 1;
i = i * 1; i = i * 1;
i = i / 1; i = i / 1;
i = i % 1; i = i % 1;
i = <i32>(i ** 1);
i = i << 1; i = i << 1;
i = i >> 1; i = i >> 1;
i = i >>> 1; i = i >>> 1;
@ -42,6 +44,7 @@ i += 1;
i -= 1; i -= 1;
i *= 1; i *= 1;
i %= 1; i %= 1;
// i **= 1;
i <<= 1; i <<= 1;
i >>= 1; i >>= 1;
i >>>= 1; i >>>= 1;
@ -62,6 +65,7 @@ I - 1;
I * 1; I * 1;
I / 1; I / 1;
I % 1; I % 1;
<f64>I ** 1;
I << 1; I << 1;
I >> 1; I >> 1;
I >>> 1; I >>> 1;
@ -80,6 +84,7 @@ I = I - 1;
I = I * 1; I = I * 1;
I = I / 1; I = I / 1;
I = I % 1; I = I % 1;
I = <i64>(<f64>I ** 1);
I = I << 1; I = I << 1;
I = I >> 1; I = I >> 1;
I = I >>> 1; I = I >>> 1;
@ -91,6 +96,7 @@ I += 1;
I -= 1; I -= 1;
I *= 1; I *= 1;
I %= 1; I %= 1;
// I **= 1;
I <<= 1; I <<= 1;
I >>= 1; I >>= 1;
I >>>= 1; I >>>= 1;
@ -110,7 +116,8 @@ f + 1;
f - 1; f - 1;
f * 1; f * 1;
f / 1; f / 1;
// f % 1; f % 1;
f ** 1;
b = f < 1; b = f < 1;
b = f > 1; b = f > 1;
@ -122,12 +129,14 @@ f = f + 1;
f = f - 1; f = f - 1;
f = f * 1; f = f * 1;
f = f / 1; f = f / 1;
// f = f % 1; f = f % 1;
f = f ** 1;
f += 1; f += 1;
f -= 1; f -= 1;
f *= 1; f *= 1;
// f %= 1; f %= 1;
f **= 1;
var F: f64 = 0; var F: f64 = 0;
@ -141,7 +150,8 @@ F + 1;
F - 1; F - 1;
F * 1; F * 1;
F / 1; F / 1;
// f % 1; F % 1;
F ** 1;
b = F < 1; b = F < 1;
b = F > 1; b = F > 1;
@ -153,9 +163,11 @@ F = F + 1;
F = F - 1; F = F - 1;
F = F * 1; F = F * 1;
F = F / 1; F = F / 1;
// F = F % 1; F = F % 1;
F = F ** 1;
F += 1; F += 1;
F -= 1; F -= 1;
F *= 1; F *= 1;
// F %= 1; F %= 1;
F **= 1;

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,6 @@
(module (module
(type $iiiiv (func (param i32 i32 i32 i32))) (type $iiiiv (func (param i32 i32 i32 i32)))
(type $v (func)) (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))) (import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $builtins/b (mut i32) (i32.const 0)) (global $builtins/b (mut i32) (i32.const 0))
(global $builtins/i (mut i32) (i32.const 0)) (global $builtins/i (mut i32) (i32.const 0))
@ -21,731 +19,7 @@
(func $builtins/test (; 1 ;) (type $v) (func $builtins/test (; 1 ;) (type $v)
(nop) (nop)
) )
(func $fmod (; 2 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64) (func $start (; 2 ;) (type $v)
(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 $0 f32)
(local $1 f64) (local $1 f64)
(local $2 i32) (local $2 i32)
@ -1566,209 +840,5 @@
(unreachable) (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)
)
)
) )
) )

View File

@ -292,21 +292,6 @@ assert(f64.MIN_SAFE_INTEGER == -9007199254740991);
assert(f64.MAX_SAFE_INTEGER == 9007199254740991); assert(f64.MAX_SAFE_INTEGER == 9007199254740991);
assert(f64.EPSILON == 2.2204460492503131e-16); assert(f64.EPSILON == 2.2204460492503131e-16);
assert(isNaN<f64>(fmod(1, NaN))); // should be importable
assert(fmod(1.5, 1.0) == 0.5); // exactly 0.5 (as in C) import { isNaN as isItNaN } from "builtins";
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";
isItNaN(1); isItNaN(1);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

144
tests/compiler/std/libm.ts Normal file
View File

@ -0,0 +1,144 @@
export const E = Math.E;
export const LN10 = Math.LN10;
export const LN2 = Math.LN2;
export const LOG10E = Math.LOG10E;
export const LOG2E = Math.LOG2E;
export const PI = Math.PI;
export const SQRT1_2 = Math.SQRT1_2;
export const SQRT2 = Math.SQRT2;
export function abs(x: f64): f64 {
return Math.abs(x);
}
export function acos(x: f64): f64 {
return Math.acos(x);
}
export function acosh(x: f64): f64 {
return Math.acosh(x);
}
export function asin(x: f64): f64 {
return Math.asin(x);
}
export function asinh(x: f64): f64 {
return Math.asinh(x);
}
export function atan(x: f64): f64 {
return Math.atan(x);
}
export function atanh(x: f64): f64 {
return Math.atanh(x);
}
export function atan2(y: f64, x: f64): f64 {
return Math.atan2(y, x);
}
export function cbrt(x: f64): f64 {
return Math.cbrt(x);
}
export function ceil(x: f64): f64 {
return Math.ceil(x);
}
export function clz32(x: f64): f64 {
return Math.clz32(x);
}
export function cos(x: f64): f64 {
return Math.cos(x);
}
export function cosh(x: f64): f64 {
return Math.cosh(x);
}
export function exp(x: f64): f64 {
return Math.exp(x);
}
export function expm1(x: f64): f64 {
return Math.expm1(x);
}
export function floor(x: f64): f64 {
return Math.floor(x);
}
export function fround(x: f64): f32 {
return Math.fround(x);
}
export function hypot(a: f64, b: f64): f64 {
return Math.hypot(a, b);
}
export function imul(a: f64, b: f64): f64 {
return Math.imul(a, b);
}
export function log(x: f64): f64 {
return Math.log(x);
}
export function log10(x: f64): f64 {
return Math.log10(x);
}
export function log1p(x: f64): f64 {
return Math.log1p(x);
}
export function log2(x: f64): f64 {
return Math.log2(x);
}
export function max(a: f64, b: f64): f64 {
return Math.max(a, b);
}
export function min(a: f64, b: f64): f64 {
return Math.min(a, b);
}
export function pow(x: f64, y: f64): f64 {
return Math.pow(x, y);
}
export function round(x: f64): f64 {
return Math.round(x);
}
export function sign(x: f64): f64 {
return Math.sign(x);
}
export function sin(x: f64): f64 {
return Math.sin(x);
}
export function sinh(x: f64): f64 {
return Math.sinh(x);
}
export function sqrt(x: f64): f64 {
return Math.sqrt(x);
}
export function tan(x: f64): f64 {
return Math.tan(x);
}
export function tanh(x: f64): f64 {
return Math.tanh(x);
}
export function trunc(x: f64): f64 {
return Math.trunc(x);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

167
tests/compiler/std/mod.ts Normal file
View File

@ -0,0 +1,167 @@
const js = true;
declare namespace JSOp {
export function mod(x: f64, y: f64): f64;
}
function check<T>(actual: T, expected: T): bool {
if (isNaN(expected)) return isNaN(actual);
if (expected == 0) return 1 / expected == 1 / actual;
return actual == expected;
}
// === f64 % f64 ================================
function test_fmod(left: f64, right: f64, expected: f64): bool {
return check<f64>( left % right , expected) &&
(!js || check<f64>(JSOp.mod(left , right), expected));
}
// sanity
assert(test_fmod(3.0, 2.0, 1.0));
assert(test_fmod(3.0, -2.0, 1.0));
assert(test_fmod(-3.0, 2.0, -1.0));
assert(test_fmod(-3.0, -2.0, -1.0));
assert(test_fmod(3.5, 2.0, 1.5));
assert(test_fmod(3.5, -2.0, 1.5));
assert(test_fmod(-3.5, 2.0, -1.5));
assert(test_fmod(-3.5, -2.0, -1.5));
assert(test_fmod(3.0, 2.5, 0.5));
assert(test_fmod(3.0, -2.5, 0.5));
assert(test_fmod(-3.0, 2.5, -0.5));
assert(test_fmod(-3.0, -2.5, -0.5));
assert(test_fmod(0.5, 1.0, 0.5));
assert(test_fmod(0.5, -1.0, 0.5));
assert(test_fmod(-0.5, 1.0, -0.5));
assert(test_fmod(-0.5, -1.0, -0.5));
assert(test_fmod(1.5, 1.0, 0.5));
assert(test_fmod(1.5, -1.0, 0.5));
assert(test_fmod(-1.5, 1.0, -0.5));
assert(test_fmod(-1.5, -1.0, -0.5));
assert(test_fmod(1.25, 1.0, 0.25));
assert(test_fmod(1.25, -1.0, 0.25));
assert(test_fmod(-1.25, 1.0, -0.25));
assert(test_fmod(-1.25, -1.0, -0.25));
assert(test_fmod(1.0, 1.25, 1.0));
assert(test_fmod(1.0, -1.25, 1.0));
assert(test_fmod(-1.0, 1.25, -1.0));
assert(test_fmod(-1.0, -1.25, -1.0));
assert(test_fmod(-13, 64, -13));
// special
assert(test_fmod(0.0, 0.0, NaN));
assert(test_fmod(-0.0, 0.0, NaN));
assert(test_fmod(0.0, -0.0, NaN));
assert(test_fmod(-0.0, -0.0, NaN));
assert(test_fmod(0.0, 1.0, 0.0));
assert(test_fmod(-0.0, 1.0, -0.0));
assert(test_fmod(0.0, -1.0, 0.0));
assert(test_fmod(-0.0, -1.0, -0.0));
assert(test_fmod(1.0, 0.0, NaN));
assert(test_fmod(-1.0, 0.0, NaN));
assert(test_fmod(1.0, -0.0, NaN));
assert(test_fmod(-1.0, -0.0, NaN));
assert(test_fmod(NaN, 0.0, NaN));
assert(test_fmod(NaN, -0.0, NaN));
assert(test_fmod(NaN, 1.0, NaN));
assert(test_fmod(NaN, -1.0, NaN));
assert(test_fmod(NaN, 0.0, NaN));
assert(test_fmod(NaN, -0.0, NaN));
assert(test_fmod(NaN, 1.0, NaN));
assert(test_fmod(NaN, -1.0, NaN));
assert(test_fmod(NaN, NaN, NaN));
assert(test_fmod(0.0, Infinity, 0.0));
assert(test_fmod(-0.0, Infinity, -0.0));
assert(test_fmod(0.0, -Infinity, 0.0));
assert(test_fmod(-0.0, -Infinity, -0.0));
assert(test_fmod(1.0, Infinity, 1.0));
assert(test_fmod(-1.0, Infinity, -1.0));
assert(test_fmod(1.0, -Infinity, 1.0));
assert(test_fmod(-1.0, -Infinity, -1.0));
assert(test_fmod(Infinity, 0.0, NaN));
assert(test_fmod(Infinity, -0.0, NaN));
assert(test_fmod(-Infinity, 0.0, NaN));
assert(test_fmod(-Infinity, -0.0, NaN));
assert(test_fmod(Infinity, 1.0, NaN));
assert(test_fmod(Infinity, -1.0, NaN));
assert(test_fmod(-Infinity, 1.0, NaN));
assert(test_fmod(-Infinity, -1.0, NaN));
assert(test_fmod(Infinity, Infinity, NaN));
assert(test_fmod(-Infinity, Infinity, NaN));
assert(test_fmod(Infinity, -Infinity, NaN));
assert(test_fmod(-Infinity, -Infinity, NaN));
assert(test_fmod(Infinity, NaN, NaN));
assert(test_fmod(-Infinity, NaN, NaN));
assert(test_fmod(NaN, Infinity, NaN));
assert(test_fmod(NaN, -Infinity, NaN));
// === f32 % f32 ================================
function test_fmodf(left: f32, right: f32, expected: f32): bool {
return check<f32>(left % right, expected);
}
// sanity
assert(test_fmodf(3.0, 2.0, 1.0));
assert(test_fmodf(3.0, -2.0, 1.0));
assert(test_fmodf(-3.0, 2.0, -1.0));
assert(test_fmodf(-3.0, -2.0, -1.0));
assert(test_fmodf(3.5, 2.0, 1.5));
assert(test_fmodf(3.5, -2.0, 1.5));
assert(test_fmodf(-3.5, 2.0, -1.5));
assert(test_fmodf(-3.5, -2.0, -1.5));
assert(test_fmodf(3.0, 2.5, 0.5));
assert(test_fmodf(3.0, -2.5, 0.5));
assert(test_fmodf(-3.0, 2.5, -0.5));
assert(test_fmodf(-3.0, -2.5, -0.5));
assert(test_fmodf(0.5, 1.0, 0.5));
assert(test_fmodf(0.5, -1.0, 0.5));
assert(test_fmodf(-0.5, 1.0, -0.5));
assert(test_fmodf(-0.5, -1.0, -0.5));
assert(test_fmodf(1.5, 1.0, 0.5));
assert(test_fmodf(1.5, -1.0, 0.5));
assert(test_fmodf(-1.5, 1.0, -0.5));
assert(test_fmodf(-1.5, -1.0, -0.5));
// special
assert(test_fmodf(0.0, 0.0, NaN));
assert(test_fmodf(-0.0, 0.0, NaN));
assert(test_fmodf(0.0, -0.0, NaN));
assert(test_fmodf(-0.0, -0.0, NaN));
assert(test_fmodf(1.0, 0.0, NaN));
assert(test_fmodf(-1.0, 0.0, NaN));
assert(test_fmodf(1.0, -0.0, NaN));
assert(test_fmodf(-1.0, -0.0, NaN));
assert(test_fmodf(NaN, 0.0, NaN));
assert(test_fmodf(NaN, -0.0, NaN));
assert(test_fmodf(NaN, 1.0, NaN));
assert(test_fmodf(NaN, -1.0, NaN));
assert(test_fmodf(NaN, 0.0, NaN));
assert(test_fmodf(NaN, -0.0, NaN));
assert(test_fmodf(NaN, 1.0, NaN));
assert(test_fmodf(NaN, -1.0, NaN));
assert(test_fmodf(NaN, NaN, NaN));
assert(test_fmodf(0.0, Infinity, 0.0));
assert(test_fmodf(-0.0, Infinity, -0.0));
assert(test_fmodf(0.0, -Infinity, 0.0));
assert(test_fmodf(-0.0, -Infinity, -0.0));
assert(test_fmodf(1.0, Infinity, 1.0));
assert(test_fmodf(-1.0, Infinity, -1.0));
assert(test_fmodf(1.0, -Infinity, 1.0));
assert(test_fmodf(-1.0, -Infinity, -1.0));
assert(test_fmodf(Infinity, 0.0, NaN));
assert(test_fmodf(Infinity, -0.0, NaN));
assert(test_fmodf(-Infinity, 0.0, NaN));
assert(test_fmodf(-Infinity, -0.0, NaN));
assert(test_fmodf(Infinity, 1.0, NaN));
assert(test_fmodf(Infinity, -1.0, NaN));
assert(test_fmodf(-Infinity, 1.0, NaN));
assert(test_fmodf(-Infinity, -1.0, NaN));
assert(test_fmodf(Infinity, Infinity, NaN));
assert(test_fmodf(-Infinity, Infinity, NaN));
assert(test_fmodf(Infinity, -Infinity, NaN));
assert(test_fmodf(-Infinity, -Infinity, NaN));
assert(test_fmodf(Infinity, NaN, NaN));
assert(test_fmodf(-Infinity, NaN, NaN));
assert(test_fmodf(NaN, Infinity, NaN));
assert(test_fmodf(NaN, -Infinity, NaN));

File diff suppressed because it is too large Load Diff

View File

@ -1134,7 +1134,7 @@
(call $abort (call $abort
(i32.const 0) (i32.const 0)
(i32.const 72) (i32.const 72)
(i32.const 483) (i32.const 484)
(i32.const 10) (i32.const 10)
) )
(unreachable) (unreachable)

View File

@ -1313,7 +1313,7 @@
(call $abort (call $abort
(i32.const 0) (i32.const 0)
(i32.const 72) (i32.const 72)
(i32.const 483) (i32.const 484)
(i32.const 10) (i32.const 10)
) )
(unreachable) (unreachable)

View File

@ -52,6 +52,9 @@ const bin = {
globalObject: "typeof self !== 'undefined' ? self : this" globalObject: "typeof self !== 'undefined' ? self : this"
}, },
devtool: "source-map", devtool: "source-map",
performance: {
hints : false
},
plugins: [ plugins: [
new webpack.DefinePlugin({ new webpack.DefinePlugin({
BUNDLE_VERSION: JSON.stringify(require("./package.json").version), BUNDLE_VERSION: JSON.stringify(require("./package.json").version),