math: core/math.nepl に関する機能を提供するライブラリ
- このモジュールの公開 API を提供します。
- 実装の変更時に最小限の doctest 実行経路を維持します。
- 利用時は各関数の「目的」「注意」「計算量」を確認してください。
#entry main
#target core
fn main <()*>i32> ():
()
0add: i32 の加算(mod 2^32)
- 2つの i32 を加算し、Wasm の i32 加算規則で結果を返します。
target=wasmではi32.addを直接実行します。target=llvmでは LLVM IR のadd i32に分岐します。
- オーバーフロー時は 2^32 でラップします。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 42 add 40 2;
assert_eq_i32 0 add -1 1;sub: i32 の減算(mod 2^32)
- 2つの i32 の差を計算します。
- wasm は
i32.sub、llvm はsub i32を使います。
- 符号付き/符号なしを問わず、ビット列として同じ減算を行います。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 5 sub 9 4;
assert_eq_i32 -5 sub 4 9;mul: i32 の乗算(mod 2^32)
- 2つの i32 の積を計算します。
- wasm は
i32.mul、llvm はmul i32を使います。
- 積が 32-bit 範囲を超える場合は下位 32-bit が残ります。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 42 mul 6 7;
assert_eq_i32 0 mul 0 12345;div_s: i32 の符号付き除算
- 符号付き整数として割り算を行います。
- wasm は
i32.div_s、llvm はsdiv i32を使います。
- 0 除算は未定義動作ではなくランタイム trap になります。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 -3 div_s -9 3;
assert_eq_i32 -3 div_s 10 -3;div_u: i32 の符号なし除算
- 符号なし整数として割り算を行います。
- wasm は
i32.div_u、llvm はudiv i32を使います。
- 引数が負に見える値でも、ビット列を符号なしとみなして計算します。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 3 div_u 11 3;
assert_eq_i32 2147483647 div_u -1 2;rem_s: i32 の符号付き剰余
- 符号付き除算の余りを計算します。
- wasm は
i32.rem_s、llvm はsrem i32を使います。
- 符号付き剰余の符号規則は Wasm/LLVM の仕様に従います。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 1 rem_s 10 3;
assert_eq_i32 -1 rem_s -10 3;mod_s: i32 の符号付き剰余(rem_s の別名)
rem_u: i32 の符号なし剰余
- 符号なし除算の余りを計算します。
- wasm は
i32.rem_u、llvm はurem i32を使います。
- 結果は常に 0 以上で、除数未満になります。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 2 rem_u 11 3;
assert_eq_i32 5 rem_u -1 10;and: i32 のビット AND
- i32 と i32 の各ビットに対して AND を取り、両方が 1 のビットだけを残します。
- wasm は
i32.and、llvm はand i32を使って同じ結果を返します。
- ビット演算なので符号は区別しません。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 2 and 6 3;
assert_eq_i32 7 or 6 3;
assert_eq_i32 5 xor 6 3;
assert_eq_i32 8 shl 1 3;
assert_eq_i32 -2 shr_s -8 2;
assert_eq_i32 1073741822 shr_u -8 2;
assert_eq_i32 2 rotl 1 1;
assert_eq_i32 1 rotr 2 1;or: i32 のビット OR
- i32 と i32 の各ビットに対して OR を取り、どちらかが 1 のビットを立てます。
- wasm は
i32.or、llvm はor i32を使います。
- ビット演算なので符号は区別しません。
- O(1)
xor: i32 のビット XOR
- i32 と i32 の各ビットに対して XOR を取り、異なるビットだけを 1 にします。
- wasm は
i32.xor、llvm はxor i32を使います。
- ビット演算なので符号は区別しません。
- O(1)
shl: i32 の左シフト
aのビット列をbだけ左にずらします。
- wasm は
i32.shl、llvm はshl i32を使います。
- シフト量は実行系の規則に従って下位ビットが使われます。
- O(1)
shr_s: i32 の算術右シフト
- 符号を保ちながら
aを右シフトします。
- wasm は
i32.shr_s、llvm はashr i32を使います。
- 負数のときは符号拡張されます。
- O(1)
shr_u: i32 の論理右シフト
- 上位を 0 で埋めながら
aを右シフトします。
- wasm は
i32.shr_u、llvm はlshr i32を使います。
- 符号なし値として扱いたいときに使います。
- O(1)
rotl: i32 の左ローテート
- i32 のビット列を左方向に循環回転します。
- wasm は
i32.rotl、llvm はllvm.fshl.i32intrinsic を使います。
- ローテートはシフトと異なり、あふれたビットが反対側に戻ります。
- O(1)
rotr: i32 の右ローテート
- i32 のビット列を右方向に循環回転します。
- wasm は
i32.rotr、llvm はllvm.fshr.i32intrinsic を使います。
- ローテートはシフトと異なり、あふれたビットが反対側に戻ります。
- O(1)
clz: 先頭ゼロビット数を数える
- i32 の上位側に連続する 0 ビット数を返します。
- wasm は
i32.clz、llvm はllvm.ctlz.i32intrinsic を使います。
- 入力が 0 の場合も実行系の規約に沿って定義されます。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert_eq_i32 31 clz 1;
assert_eq_i32 3 ctz 8;
assert_eq_i32 4 popcnt 15;ctz: 末尾ゼロビット数を数える
- i32 の下位側に連続する 0 ビット数を返します。
- wasm は
i32.ctz、llvm はllvm.cttz.i32intrinsic を使います。
- 入力が 0 の場合も実行系の規約に沿って定義されます。
- O(1)
popcnt: 1 ビットの個数を数える
- i32 のビット列に含まれる 1 の個数を返します。
- wasm は
i32.popcnt、llvm はllvm.ctpop.i32intrinsic を使います。
- 値の符号には依存しません。
- O(1)
eq: i32 の等値比較
- 2つの i32 が等しいとき true、異なるとき false を返します。
- wasm は
i32.eq、llvm はicmp eqを使います。
- 返り値は bool 型です。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
assert eq 7 7;
assert ne 7 8;
assert lt -1 0;
assert lt_u 0 -1;
assert le 7 7;
assert le_u 7 8;
assert gt 9 3;
assert gt_u -1 0;
assert ge 9 9;
assert ge_u -1 -1;ne: i32 の非等値比較
- 2つの i32 が異なるとき true を返します。
- wasm は
i32.ne、llvm はicmp neを使います。
- 返り値は bool 型です。
- O(1)
lt: i32 の符号付き小なり比較
- i32 を符号付き整数として比較し、
a < bを判定します。
- wasm は
i32.lt_s、llvm はicmp sltを使います。
- 返り値は bool 型です。
- O(1)
lt_u: i32 の符号なし小なり比較
- i32 を符号なし整数として比較し、
a < bを判定します。
- wasm は
i32.lt_u、llvm はicmp ultを使います。
- 返り値は bool 型です。
- O(1)
le: i32 の符号付き以下比較
- i32 を符号付き整数として比較し、
a <= bを判定します。
- wasm は
i32.le_s、llvm はicmp sleを使います。
- 返り値は bool 型です。
- O(1)
le_u: i32 の符号なし以下比較
- i32 を符号なし整数として比較し、
a <= bを判定します。
- wasm は
i32.le_u、llvm はicmp uleを使います。
- 返り値は bool 型です。
- O(1)
gt: i32 の符号付き大なり比較
- i32 を符号付き整数として比較し、
a > bを判定します。
- wasm は
i32.gt_s、llvm はicmp sgtを使います。
- 返り値は bool 型です。
- O(1)
gt_u: i32 の符号なし大なり比較
- i32 を符号なし整数として比較し、
a > bを判定します。
- wasm は
i32.gt_u、llvm はicmp ugtを使います。
- 返り値は bool 型です。
- O(1)
ge: i32 の符号付き以上比較
- i32 を符号付き整数として比較し、
a >= bを判定します。
- wasm は
i32.ge_s、llvm はicmp sgeを使います。
- 返り値は bool 型です。
- O(1)
ge_u: i32 の符号なし以上比較
- i32 を符号なし整数として比較し、
a >= bを判定します。
- wasm は
i32.ge_u、llvm はicmp ugeを使います。
- 返り値は bool 型です。
- O(1)
add_u8: u8 の加算(mod 2^8)
- u8 と u8 を加算します。
- i32 演算で加算した後、
0xffでマスクして下位 8-bit を残します。
- オーバーフロー時は 8-bit でラップします。
- O(1)
sub_u8: u8 の減算(mod 2^8)
- u8 から u8 を減算します。
- i32 演算で減算した後、
0xffでマスクして下位 8-bit を残します。
- 負の結果は 8-bit でラップします。
- O(1)
mul_u8: u8 の乗算(mod 2^8)
- u8 と u8 の積を計算します。
- i32 演算で乗算した後、
0xffでマスクして下位 8-bit を残します。
- 大きな積は 8-bit でラップします。
- O(1)
div_u_u8: u8 の符号なし除算
- u8 を符号なし整数として除算します。
- wasm は
i32.div_u、llvm はudiv i32を使います。
- 0 除算は trap になります。
- O(1)
rem_u_u8: u8 の符号なし剰余
- u8 を符号なし整数として剰余を計算します。
- wasm は
i32.rem_u、llvm はurem i32を使います。
- 0 除算は trap になります。
- O(1)
eq_u8: u8 の等値比較
- u8 の
a == bを判定します。
- wasm は
i32.eq、llvm はicmp eqを使います。
- 結果は bool(0/1)です。
- O(1)
ne_u8: u8 の非等値比較
- u8 の
a != bを判定します。
- wasm は
i32.ne、llvm はicmp neを使います。
- 結果は bool(0/1)です。
- O(1)
lt_u_u8: u8 の符号なし小なり比較
- u8 を符号なし整数として
a < bを判定します。
- wasm は
i32.lt_u、llvm はicmp ultを使います。
- 結果は bool(0/1)です。
- O(1)
le_u_u8: u8 の符号なし以下比較
- u8 を符号なし整数として
a <= bを判定します。
- wasm は
i32.le_u、llvm はicmp uleを使います。
- 結果は bool(0/1)です。
- O(1)
gt_u_u8: u8 の符号なし大なり比較
- u8 を符号なし整数として
a > bを判定します。
- wasm は
i32.gt_u、llvm はicmp ugtを使います。
- 結果は bool(0/1)です。
- O(1)
ge_u_u8: u8 の符号なし以上比較
- u8 を符号なし整数として
a >= bを判定します。
- wasm は
i32.ge_u、llvm はicmp ugeを使います。
- 結果は bool(0/1)です。
- O(1)
add: u8 の加算(mod 2^8)
sub: u8 の減算(mod 2^8)
mul: u8 の乗算(mod 2^8)
div_u: u8 の符号なし除算
rem_u: u8 の符号なし剰余
eq: u8 の等値比較
ne: u8 の非等値比較
lt_u: u8 の符号なし小なり比較
le_u: u8 の符号なし以下比較
gt_u: u8 の符号なし大なり比較
ge_u: u8 の符号なし以上比較
add: i64 の加算(mod 2^64)
- i64 と i64 を加算します。
- wasm は
i64.add、llvm はadd i64を使います。
- オーバーフロー時は下位 64-bit が残ります。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast 40;
let b <i64> cast 2;
let r0 <i64> add a b;
assert eq r0 <i64> cast 42;
let a <i64> cast 0;
let b <i64> cast 7;
let r1 <i64> add a b;
assert eq r1 b;sub: i64 の減算(mod 2^64)
- i64 から i64 を減算します。
- wasm は
i64.sub、llvm はsub i64を使います。
- 結果は 64-bit 符号付き値として解釈されますが、演算自体は 64-bit ラップです。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast 44;
let b <i64> cast 2;
let r0 <i64> sub a b;
assert eq r0 <i64> cast 42;
let z <i64> cast 0;
let one <i64> cast 1;
let r1 <i64> sub z one;
assert lt r1 z;mul: i64 の乗算(mod 2^64)
- i64 と i64 を乗算します。
- wasm は
i64.mul、llvm はmul i64を使います。
- 乗算結果が 64-bit を超える場合はラップします。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast 6;
let b <i64> cast 7;
let r0 <i64> mul a b;
assert eq r0 <i64> cast 42;
let z <i64> cast 0;
let n <i64> cast 999;
let r1 <i64> mul z n;
assert eq r1 z;div_s: i64 の符号付き除算
- i64 を符号付き整数として割り算します。
- wasm 命令
i64.div_sを直接実行します。
- 0 除算は trap します。
- 最小値
-2^63を-1で割るケースも trap します。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let n9 <i64> cast -9;
let p9 <i64> cast 9;
let p3 <i64> cast 3;
let n3 <i64> cast -3;
let p <i64> div_s n9 p3;
let q <i64> div_s p9 n3;
assert eq p <i64> cast -3;
assert eq q <i64> cast -3;div_u: i64 の符号なし除算
- i64 を符号なし整数として割り算します。
- wasm は
i64.div_u、llvm はudiv i64を使います。
- 0 除算は trap します。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast 100;
let b <i64> cast 9;
let r0 <i64> div_u a b;
assert eq r0 <i64> cast 11;
let a <i64> cast 9;
let b <i64> cast 10;
let r1 <i64> div_u a b;
assert eq r1 <i64> cast 0;rem_s: i64 の符号付き剰余
- i64 の符号付き剰余(余り)を計算します。
- wasm 命令
i64.rem_sを直接実行します。
- 余りの符号は被除数(左辺)に従います。
- 0 除算は trap します。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let n10 <i64> cast -10;
let p10 <i64> cast 10;
let p3 <i64> cast 3;
let a <i64> rem_s n10 p3;
let b <i64> rem_s p10 p3;
assert eq a <i64> cast -1;
assert eq b <i64> cast 1;rem_u: i64 の符号なし剰余
- i64 の符号なし剰余を計算します。
- wasm は
i64.rem_u、llvm はurem i64を使います。
- 戻り値は 0 以上かつ除数未満です。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast 100;
let b <i64> cast 9;
let r0 <i64> rem_u a b;
assert eq r0 <i64> cast 1;
let a <i64> cast 9;
let b <i64> cast 10;
let r1 <i64> rem_u a b;
assert eq r1 a;and: i64 のビット AND
- 2つの i64 の各ビットに AND を適用します。
- wasm 命令
i64.andを直接実行します。
- 演算は整数の符号とは無関係にビット単位で行われます。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast 14;
let b <i64> cast 11;
let r_and <i64> and a b;
let r_or <i64> or a b;
let r_xor <i64> xor a b;
assert eq r_and <i64> cast 10;
assert eq r_or <i64> cast 15;
assert eq r_xor <i64> cast 5;or: i64 のビット OR
- 2つの i64 の各ビットに OR を適用します。
- wasm 命令
i64.orを直接実行します。
- 真理値 OR ではなく、ビット論理和です。
- O(1)
xor: i64 のビット XOR
- 2つの i64 の各ビットに XOR を適用します。
- wasm 命令
i64.xorを直接実行します。
- 異なるビットのみ 1 になる排他的論理和です。
- O(1)
shl: i64 の左シフト
- i64 のビット列を左へシフトします。
- wasm 命令
i64.shlを直接実行します。
- シフト量は Wasm 仕様に従い下位 6 bit が使われます。
- O(1)
shr_s: i64 の算術右シフト
- i64 を符号付き整数として右へシフトします。
- wasm 命令
i64.shr_sを直接実行します。
- 最上位ビット(符号ビット)が埋め戻されます。
- O(1)
shr_u: i64 の論理右シフト
- i64 を符号なし整数として右へシフトします。
- wasm 命令
i64.shr_uを直接実行します。
- 上位ビットは 0 で埋められます。
- O(1)
rotl: i64 の左ローテート
- i64 のビット列を左へ循環シフトします。
- wasm 命令
i64.rotlを直接実行します。
- シフトで失われるビットは下位側へ回り込みます。
- O(1)
rotr: i64 の右ローテート
- i64 のビット列を右へ循環シフトします。
- wasm 命令
i64.rotrを直接実行します。
- シフトで失われるビットは上位側へ回り込みます。
- O(1)
clz: 先頭ゼロビット数の計算
- i64 の先頭側に連続する 0 bit の個数を返します。
- wasm 命令
i64.clzを直接実行します。
- 入力が 0 のときは 64 を返します。
- O(1)
ctz: 末尾ゼロビット数の計算
- i64 の末尾側に連続する 0 bit の個数を返します。
- wasm 命令
i64.ctzを直接実行します。
- 入力が 0 のときは 64 を返します。
- O(1)
popcnt: 1 ビット数の計算
- i64 に立っている 1 bit の個数を返します。
- wasm 命令
i64.popcntを直接実行します。
- ハミング重み(population count)として利用できます。
- O(1)
eq: i64 の等値比較
- 2つの i64 が等しいかを判定します。
- wasm 命令
i64.eqを直接実行します。
- 比較はビット列が一致するかで判定されます。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let a <i64> cast -1;
let b <i64> cast 1;
let c <i64> cast -2;
let d <i64> cast -1;
assert eq a d;
assert ne a b;
assert lt c d;
assert gt_u a b;ne: i64 の非等値比較
- 2つの i64 が異なるかを判定します。
- wasm 命令
i64.neを直接実行します。
eqの否定と同値です。
- O(1)
lt: i64 の符号付き小なり比較
- i64 を符号付き整数として
a < bを判定します。
- wasm 命令
i64.lt_sを直接実行します。
- 負数を含む順序関係を使うときはこちらを使います。
- O(1)
lt_u: i64 の符号なし小なり比較
- i64 を符号なし整数として
a < bを判定します。
- wasm 命令
i64.lt_uを直接実行します。
- 上位ビットが立っている値は大きな正数として扱われます。
- O(1)
le: i64 の符号付き以下比較
- i64 を符号付き整数として
a <= bを判定します。
- wasm 命令
i64.le_sを直接実行します。
ltとeqの和集合と同じ真理値になります。
- O(1)
le_u: i64 の符号なし以下比較
- i64 を符号なし整数として
a <= bを判定します。
- wasm 命令
i64.le_uを直接実行します。
- 符号付き比較とは結果が異なる場合があります。
- O(1)
gt: i64 の符号付き大なり比較
- i64 を符号付き整数として
a > bを判定します。
- wasm 命令
i64.gt_sを直接実行します。
- 負数を含む大小比較に使用します。
- O(1)
gt_u: i64 の符号なし大なり比較
- i64 を符号なし整数として
a > bを判定します。
- wasm 命令
i64.gt_uを直接実行します。
- 上位ビットが立つ値は大きい値として判定されます。
- O(1)
ge: i64 の符号付き以上比較
- i64 を符号付き整数として
a >= bを判定します。
- wasm 命令
i64.ge_sを直接実行します。
gtまたはeqが真なら真になります。
- O(1)
ge_u: i64 の符号なし以上比較
- i64 を符号なし整数として
a >= bを判定します。
- wasm 命令
i64.ge_uを直接実行します。
gt_uまたはeqが真なら真になります。
- O(1)
add: f32 の加算
- 2つの f32 を加算します。
- wasm は
f32.add、llvm はfadd floatを実行します。
- 丸め・NaN・±∞の扱いは IEEE 754 と各 backend の仕様に従います。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let x <f32> add 1.5 2.25;
let y <f32> sub x 1.25;
assert eq x 3.75;
assert eq y 2.5;sub: f32 の減算
- 2つの f32 の差を計算します。
- wasm は
f32.sub、llvm はfsub floatを実行します。
- NaN が関与する場合は比較で偽になる点に注意してください。
- O(1)
mul: f32 の乗算
- 2つの f32 の積を計算します。
- wasm は
f32.mul、llvm はfmul floatを実行します。
- 大きな値同士では
+∞や-∞へ飽和することがあります。
- O(1)
div: f32 の除算
- 2つの f32 の商を計算します。
- wasm は
f32.div、llvm はfdiv floatを実行します。
- 整数除算と異なり、0 除算は trap せず ±∞ / NaN になります。
- O(1)
sqrt_f32: f32 の平方根
- f32 の平方根を返します。
- wasm は
f32.sqrtを実行します。 - llvm は
llvm.sqrt.f32intrinsic を呼びます。
- 負数入力は NaN になります。
- O(1)
abs_f32: f32 の絶対値
- f32 の符号を取り除いた絶対値を返します。
- wasm は
f32.absを使います。 - llvm は
bitcast -> and mask -> bitcastで符号ビットのみを落とします。
- NaN の payload は backend の仕様に従います。
- O(1)
neg: f32 の符号反転
- f32 の符号を反転した値
-aを返します。
- wasm は
f32.neg、llvm はfneg floatを使います。
-0.0と+0.0は符号が反転します。
- O(1)
ceil_f32: f32 の切り上げ
- f32 を「以上の最小整数値」へ切り上げます。
- wasm は
f32.ceil、llvm はllvm.ceil.f32を使います。
- 戻り値の型は f32 のままです。
- O(1)
floor_f32: f32 の切り下げ
- f32 を「以下の最大整数値」へ切り下げます。
- wasm は
f32.floor、llvm はllvm.floor.f32を使います。
- 戻り値の型は f32 のままです。
- O(1)
trunc_f32: f32 の小数部切り捨て
- f32 の小数部を 0 方向へ切り捨てます。
- wasm は
f32.trunc、llvm はllvm.trunc.f32を使います。
- 負数では切り下げではなく 0 方向へ寄ります。
- O(1)
nearest_f32: f32 の最近接整数丸め
- f32 を最近接整数へ丸めます。
- wasm は
f32.nearest、llvm はllvm.nearbyint.f32を使います。
- 中間値(x.5)は backend の丸め規則に従います。
- O(1)
min_f32: f32 の最小値
- 2つの f32 から小さい方を返します。
- wasm は
f32.min、llvm はllvm.minimum.f32を使います。
- NaN 入力時の振る舞いは backend 仕様に従います。
- O(1)
max_f32: f32 の最大値
- 2つの f32 から大きい方を返します。
- wasm は
f32.max、llvm はllvm.maximum.f32を使います。
- NaN 入力時の振る舞いは backend 仕様に従います。
- O(1)
copysign_f32: f32 の符号コピー
- 第1引数の絶対値に、第2引数の符号ビットを適用した値を返します。
- wasm は
f32.copysign、llvm はllvm.copysign.f32を使います。
- 値の大きさは第1引数、符号のみ第2引数から採用されます。
- O(1)
eq: f32 の等値比較
- 2つの f32 が等しいかを判定します。
- wasm は
f32.eq、llvm はfcmp oeqを使います。
- NaN を含む比較は false になります。
- O(1)
ne: f32 の非等値比較
- 2つの f32 が異なるかを判定します。
- wasm は
f32.ne、llvm はfcmp uneを使います。
- NaN を含む比較は true になります。
- O(1)
lt: f32 の小なり比較
a < bを判定します。
- wasm は
f32.lt、llvm はfcmp oltを使います。
- NaN を含むと false です。
- O(1)
le: f32 の以下比較
a <= bを判定します。
- wasm は
f32.le、llvm はfcmp oleを使います。
- NaN を含むと false です。
- O(1)
gt: f32 の大なり比較
a > bを判定します。
- wasm は
f32.gt、llvm はfcmp ogtを使います。
- NaN を含むと false です。
- O(1)
ge: f32 の以上比較
a >= bを判定します。
- wasm は
f32.ge、llvm はfcmp ogeを使います。
- NaN を含むと false です。
- O(1)
add: f64 の加算
- 2つの f64 を加算します。
- wasm は
f64.add、llvm はfadd doubleを実行します。
- 丸め誤差や NaN の伝播は IEEE 754 の規則に従います。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let one <f64> cast 1;
let two <f64> cast 2;
let three <f64> cast 3;
let six <f64> cast 6;
let x <f64> add one two;
let y <f64> mul x two;
assert eq x three;
assert eq y six;sub: f64 の減算
- 2つの f64 の差を計算します。
- wasm は
f64.sub、llvm はfsub doubleを実行します。
- 丸めの影響で
(a - b) + bが常にaになるとは限りません。
- O(1)
mul: f64 の乗算
- 2つの f64 の積を計算します。
- wasm は
f64.mul、llvm はfmul doubleを実行します。
- 大きい値では ±∞、非数値入力では NaN になります。
- O(1)
div: f64 の除算
- 2つの f64 の商を計算します。
- wasm は
f64.div、llvm はfdiv doubleを実行します。
- 整数演算とは異なり 0 除算で trap せず、±∞ や NaN が返ります。
- O(1)
sqrt_f64: f64 の平方根
- f64 の平方根を返します。
- wasm は
f64.sqrtを実行します。 - llvm は
llvm.sqrt.f64intrinsic を呼びます。
- 負数入力は NaN になります。
- O(1)
abs_f64: f64 の絶対値
- f64 の符号を取り除いた絶対値を返します。
- wasm は
f64.absを使います。 - llvm は
bitcast -> and mask -> bitcastで符号ビットのみを落とします。
- NaN の payload は backend の仕様に従います。
- O(1)
neg: f64 の符号反転
- f64 の符号を反転した値
-aを返します。
- wasm は
f64.neg、llvm はfneg doubleを使います。
-0.0と+0.0は区別されるため、符号反転で相互変換されます。
- O(1)
ceil_f64: f64 の切り上げ
- f64 を「以上の最小整数値」へ切り上げます。
- wasm は
f64.ceil、llvm はllvm.ceil.f64を使います。
- 戻り値の型は f64 のままです。
- O(1)
floor_f64: f64 の切り下げ
- f64 を「以下の最大整数値」へ切り下げます。
- wasm は
f64.floor、llvm はllvm.floor.f64を使います。
- 戻り値の型は f64 のままです。
- O(1)
trunc_f64: f64 の小数部切り捨て
- f64 の小数部を 0 方向へ切り捨てます。
- wasm は
f64.trunc、llvm はllvm.trunc.f64を使います。
- 負数では切り下げではなく 0 方向へ寄ります。
- O(1)
nearest_f64: f64 の最近接整数丸め
- f64 を最近接整数へ丸めます。
- wasm は
f64.nearest、llvm はllvm.nearbyint.f64を使います。
- 中間値(x.5)は backend の丸め規則に従います。
- O(1)
min_f64: f64 の最小値
- 2つの f64 から小さい方を返します。
- wasm は
f64.min、llvm はllvm.minimum.f64を使います。
- NaN 入力時の振る舞いは backend 仕様に従います。
- O(1)
max_f64: f64 の最大値
- 2つの f64 から大きい方を返します。
- wasm は
f64.max、llvm はllvm.maximum.f64を使います。
- NaN 入力時の振る舞いは backend 仕様に従います。
- O(1)
copysign_f64: f64 の符号コピー
- 第1引数の絶対値に、第2引数の符号ビットを適用した値を返します。
- wasm は
f64.copysign、llvm はllvm.copysign.f64を使います。
- 値の大きさは第1引数、符号のみ第2引数から採用されます。
- O(1)
eq: f64 の等値比較
- 2つの f64 が等しいかを判定します。
- wasm は
f64.eq、llvm はfcmp oeqを使います。
- NaN を含む比較は false です。
- O(1)
ne: f64 の非等値比較
- 2つの f64 が異なるかを判定します。
- wasm は
f64.ne、llvm はfcmp uneを使います。
- NaN を含む比較は true です。
- O(1)
lt: f64 の小なり比較
a < bを判定します。
- wasm は
f64.lt、llvm はfcmp oltを使います。
- NaN を含む比較は false です。
- O(1)
le: f64 の以下比較
a <= bを判定します。
- wasm は
f64.le、llvm はfcmp oleを使います。
- NaN を含む比較は false です。
- O(1)
gt: f64 の大なり比較
a > bを判定します。
- wasm は
f64.gt、llvm はfcmp ogtを使います。
- NaN を含む比較は false です。
- O(1)
ge: f64 の以上比較
a >= bを判定します。
- wasm は
f64.ge、llvm はfcmp ogeを使います。
- NaN を含む比較は false です。
- O(1)
extend8_s_i32: i8 相当値の符号拡張
- i32 下位 8 bit を符号付き値として i32 へ拡張します。
- wasm は
i32.extend8_sを使います。 - llvm は
shl 24後にashr 24で符号拡張します。
- 上位 24 bit は入力の符号に応じて埋められます。
- O(1)
extend16_s_i32: i16 相当値の符号拡張
- i32 下位 16 bit を符号付き値として i32 へ拡張します。
- wasm は
i32.extend16_sを使います。 - llvm は
shl 16後にashr 16で符号拡張します。
- 上位 16 bit は入力の符号に応じて埋められます。
- O(1)
<i64> cast: i32 を符号拡張して i64 へ変換する
- i32 の符号を保ったまま i64 に拡張します。
- wasm は
i64.extend_i32_s、llvm はsext i32 to i64を使います。
- 負値は上位ビットが 1 で埋められます。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let v <i64> cast -1;
assert lt v <i64> cast 0;
let v <i64> cast 123;
assert eq v <i64> cast 123;<i64> cast: i32 をゼロ拡張して i64 へ変換する
- i32 を符号なし値として i64 に拡張します。
- wasm は
i64.extend_i32_u、llvm はzext i32 to i64を使います。
- 32-bit 上位は必ず 0 になります。
- O(1)
#entry main
#target core
#import "core/test" as *
#import "core/cast" as *
#import "core/math" as *
fn main <()*>()> ():
let v <i64> cast -1;
assert gt_u v <i64> cast 0;
let v <i64> cast 1;
assert eq v <i64> cast 1;wrap_i64_to_i32: i64 を i32 へ切り詰める
- i64 の下位 32 bit を取り出して i32 として返します。
- wasm は
i32.wrap_i64、llvm はtrunc i64 to i32を使います。
- 上位 32 bit は破棄されます。
- O(1)
convert_s_i32_to_f32: i32(符号付き) を f32 へ変換
- 符号付き i32 を f32 に変換します。
- wasm は
f32.convert_i32_s、llvm はsitofp i32 to floatを使います。
- 大きい整数は f32 で正確に表現できない場合があります。
- O(1)
convert_u_i32_to_f32: i32(符号なし) を f32 へ変換
- 符号なし i32 を f32 に変換します。
- wasm は
f32.convert_i32_u、llvm はuitofp i32 to floatを使います。
- 符号付き値としては負に見えるビット列も、大きな正数として解釈されます。
- O(1)
convert_s_i64_to_f32: i64(符号付き) を f32 へ変換
- 符号付き i64 を f32 に変換します。
- wasm は
f32.convert_i64_s、llvm はsitofp i64 to floatを使います。
- 表現可能桁数を超える場合は丸めが発生します。
- O(1)
convert_u_i64_to_f32: i64(符号なし) を f32 へ変換
- 符号なし i64 を f32 に変換します。
- wasm は
f32.convert_i64_u、llvm はuitofp i64 to floatを使います。
- 非常に大きな値では丸め誤差が大きくなることがあります。
- O(1)
trunc_s_f32_to_i32: f32 を i32(符号付き)へ切り捨て変換
- f32 を 0 方向へ切り捨てて符号付き i32 に変換します。
- wasm は
i32.trunc_f32_s、llvm はfptosi float to i32を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_u_f32_to_i32: f32 を i32(符号なし)へ切り捨て変換
- f32 を 0 方向へ切り捨てて符号なし i32 に変換します。
- wasm は
i32.trunc_f32_u、llvm はfptoui float to i32を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_sat_s_f32_to_i32: f32 を i32(符号付き)へ飽和変換
- f32 を i32 に変換し、範囲外は最小値/最大値に丸めます。
- wasm は
i32.trunc_sat_f32_sを使います。 - llvm は
llvm.fptosi.sat.i32.f32intrinsic を使います。
- NaN は 0 になります。
- O(1)
trunc_sat_u_f32_to_i32: f32 を i32(符号なし)へ飽和変換
- f32 を i32 に変換し、範囲外は 0 か最大値に丸めます。
- wasm は
i32.trunc_sat_f32_uを使います。 - llvm は
llvm.fptoui.sat.i32.f32intrinsic を使います。
- NaN は 0 になります。
- O(1)
trunc_s_f32_to_i64: f32 を i64(符号付き)へ切り捨て変換
- f32 を 0 方向へ切り捨てて i64 に変換します。
- wasm は
i64.trunc_f32_s、llvm はfptosi float to i64を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_u_f32_to_i64: f32 を i64(符号なし)へ切り捨て変換
- f32 を 0 方向へ切り捨てて i64 に変換します。
- wasm は
i64.trunc_f32_u、llvm はfptoui float to i64を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_sat_s_f32_to_i64: f32 を i64(符号付き)へ飽和変換
- f32 を i64 に変換し、範囲外は最小値/最大値へ丸めます。
- wasm は
i64.trunc_sat_f32_sを使います。 - llvm は
llvm.fptosi.sat.i64.f32intrinsic を使います。
- NaN は 0 になります。
- O(1)
trunc_sat_u_f32_to_i64: f32 を i64(符号なし)へ飽和変換
- f32 を i64 に変換し、範囲外は 0 か最大値へ丸めます。
- wasm は
i64.trunc_sat_f32_uを使います。 - llvm は
llvm.fptoui.sat.i64.f32intrinsic を使います。
- NaN は 0 になります。
- O(1)
<f64> cast: i32(符号付き) を f64 へ変換
- 符号付き i32 を f64 に変換します。
- wasm は
f64.convert_i32_s、llvm はsitofp i32 to doubleを使います。
- 大きな整数でも f32 より高い精度で保持できます。
- O(1)
convert_u_i32_to_f64: i32(符号なし) を f64 へ変換
- 符号なし i32 を f64 に変換します。
- wasm は
f64.convert_i32_u、llvm はuitofp i32 to doubleを使います。
- 符号付き値として負に見えるビット列も大きな正数として扱われます。
- O(1)
convert_s_i64_to_f64: i64(符号付き) を f64 へ変換
- 符号付き i64 を f64 に変換します。
- wasm は
f64.convert_i64_s、llvm はsitofp i64 to doubleを使います。
- 2^53 を超える整数は厳密には表現できず丸めが入ります。
- O(1)
convert_u_i64_to_f64: i64(符号なし) を f64 へ変換
- 符号なし i64 を f64 に変換します。
- wasm は
f64.convert_i64_u、llvm はuitofp i64 to doubleを使います。
- 大きな値では下位ビットが丸められます。
- O(1)
trunc_s_f64_to_i32: f64 を i32(符号付き)へ切り捨て変換
- f64 を 0 方向へ切り捨てて i32 に変換します。
- wasm は
i32.trunc_f64_s、llvm はfptosi double to i32を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_u_f64_to_i32: f64 を i32(符号なし)へ切り捨て変換
- f64 を 0 方向へ切り捨てて i32 に変換します。
- wasm は
i32.trunc_f64_u、llvm はfptoui double to i32を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_sat_s_f64_to_i32: f64 を i32(符号付き)へ飽和変換
- f64 を i32 に変換し、範囲外は最小値/最大値へ丸めます。
- wasm は
i32.trunc_sat_f64_sを使います。 - llvm は
llvm.fptosi.sat.i32.f64intrinsic を使います。
- NaN は 0 になります。
- O(1)
trunc_sat_u_f64_to_i32: f64 を i32(符号なし)へ飽和変換
- f64 を i32 に変換し、範囲外は 0 か最大値へ丸めます。
- wasm は
i32.trunc_sat_f64_uを使います。 - llvm は
llvm.fptoui.sat.i32.f64intrinsic を使います。
- NaN は 0 になります。
- O(1)
trunc_s_f64_to_i64: f64 を i64(符号付き)へ切り捨て変換
- f64 を 0 方向へ切り捨てて i64 に変換します。
- wasm は
i64.trunc_f64_s、llvm はfptosi double to i64を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_u_f64_to_i64: f64 を i64(符号なし)へ切り捨て変換
- f64 を 0 方向へ切り捨てて i64 に変換します。
- wasm は
i64.trunc_f64_u、llvm はfptoui double to i64を使います。
- NaN や範囲外値は trap(未定義変換)になります。
- O(1)
trunc_sat_s_f64_to_i64: f64 を i64(符号付き)へ飽和変換
- f64 を i64 に変換し、範囲外は最小値/最大値へ丸めます。
- wasm は
i64.trunc_sat_f64_sを使います。 - llvm は
llvm.fptosi.sat.i64.f64intrinsic を使います。
- NaN は 0 になります。
- O(1)
trunc_sat_u_f64_to_i64: f64 を i64(符号なし)へ飽和変換
- f64 を i64 に変換し、範囲外は 0 か最大値へ丸めます。
- wasm は
i64.trunc_sat_f64_uを使います。 - llvm は
llvm.fptoui.sat.i64.f64intrinsic を使います。
- NaN は 0 になります。
- O(1)
promote_f32_to_f64: f32 を f64 へ拡張変換
- f32 値を精度の高い f64 へ拡張します。
- wasm は
f64.promote_f32、llvm はfpext float to doubleを使います。
- 値は厳密に保持されます(f32 から f64 への拡張で情報は失われません)。
- O(1)
demote_f64_to_f32: f64 を f32 へ縮小変換
- f64 値を f32 へ縮小します。
- wasm は
f32.demote_f64、llvm はfptrunc double to floatを使います。
- 精度は失われる可能性があります。
- O(1)
reinterpret_i32_to_f32: i32 のビット列を f32 として再解釈
- 32-bit のビット列を変更せずに f32 として扱います。
- wasm は
f32.reinterpret_i32、llvm はbitcast i32 to floatを使います。
- 数値変換ではなくビット再解釈です。
- O(1)
reinterpret_f32_to_i32: f32 のビット列を i32 として再解釈
- f32 のビット表現をそのまま i32 として読み取ります。
- wasm は
i32.reinterpret_f32、llvm はbitcast float to i32を使います。
- 数値変換ではなくビット再解釈です。
- O(1)
reinterpret_i64_to_f64: i64 のビット列を f64 として再解釈
- 64-bit のビット列を変更せずに f64 として扱います。
- wasm は
f64.reinterpret_i64、llvm はbitcast i64 to doubleを使います。
- 数値変換ではなくビット再解釈です。
- O(1)
reinterpret_f64_to_i64: f64 のビット列を i64 として再解釈
- f64 のビット表現をそのまま i64 として読み取ります。
- wasm は
i64.reinterpret_f64、llvm はbitcast double to i64を使います。
- 数値変換ではなくビット再解釈です。
- O(1)
extend_s: 符号拡張を行う
- 型名 prefix を使わずに符号拡張を呼び出せるようにします。
wrap: i64 を i32 へ切り詰める
- 型名 prefix を使わずに切り詰め変換を呼び出せるようにします。
convert_s: 符号付き整数を浮動小数へ変換する
- 変換関数を型オーバーロードで統一します。
trunc_s: 浮動小数を符号付き整数へ切り捨て変換する
- 切り捨て変換を型オーバーロードで統一します。
promote: f32 を f64 に拡張する
demote: f64 を f32 に縮小する
and: bool の論理積
- bool の
a && b相当を計算します。
- wasm は
i32.and、llvm はand i32を使います。
- bool は 0/1 前提です。
- O(1)
or: bool の論理和
- bool の
a || b相当を計算します。
- wasm は
i32.or、llvm はor i32を使います。
- bool は 0/1 前提です。
- O(1)
not: bool の否定
- bool の
!aを計算します。
- wasm は
i32.eqz、llvm はicmp eqを使います。
- bool は 0/1 前提です。
- O(1)
追加整数型 API(u32/u64/u128/i128)
- WASM ネイティブの
i32/i64を土台に、符号なし整数および 128-bit 相当の基本演算を提供します。
u32/u64はadd/sub/mul/div_u/rem_uとlt_u/le_u/gt_u/ge_uを使います。u128/i128はi642 ワード(上位/下位)で構成し、加減算と比較を実装します。
u128/i128の除算・乗算は未提供です(今後拡張)。
#entry main
#target core
#import "core/test" as *
#import "core/math" as *
#import "core/cast" as *
fn main <()*>()> ():
assert_eq_i32 3 add 1 2;
assert lt_u <i64> cast 9 <i64> cast 10;u128: u128 相当(上位/下位 64-bit)
new: hi/lo から u128 値を構築する
to_u128: u64 値から u128 値を作る
add: u128 の加算(mod 2^128)
sub: u128 の減算(mod 2^128)
lt: u128 の大小比較(a < b)
i128: i128 相当(上位/下位 64-bit, 2 の補数)
new: hi/lo から i128 値を構築する
to_i128: i64 値を符号拡張して i128 に変換する
add: i128 の加算(mod 2^128)
sub: i128 の減算(mod 2^128)
mul_wide: u64 × u64 の 128-bit 積を返す
- 64-bit 乗算の上位 64-bit と下位 64-bit を同時に求めます。
- 入力を 32-bit 上位/下位に分割し、部分積を合成します。
- 途中の加算では
lt_uでキャリーを検出します。
- 符号なし演算として扱います。
- O(1)
mul: i128 の乗算(mod 2^128)
- i128 同士の積の下位 128-bit を返します。
a = a_hi*2^64 + a_lo,b = b_hi*2^64 + b_loとみなし、
a_lo*b_lo の 128-bit 積と交差項 a_hi*b_lo, a_lo*b_hi を合成します。
- 2 の補数表現の mod 2^128 乗算です(オーバーフローはラップ)。
- O(1)
lt: i128 の大小比較(a < b)