オフィスアワーがそろそろ始まるよ!()

math

数学関数と定数が定義されています。

定数

  • e: ネイピア数 (comptime_float)
  • pi: 円周率 (comptime_float)
  • tau: τ (2 * pi)
  • nan(T): 浮動小数点のNaN (Not a Number) 。Tf16/f32/f64/f128のいずれかです。
  • snan(T): 浮動小数点のSNaN (Signaling NaN) 。Tf16/f32/f64/f128のいずれかです。
  • inf(T): 浮動小数点のInfinity。Tf16/f32/f64/f128のいずれかです。

整数型の最大値/最小値

これらの値はコンパイル時定数です。

  • maxInt(T): 任意整数型の最大値を取得します。
  • minInt(T): 任意整数型の最小値を取得します。

浮動小数点型のビット数

これらの値はコンパイル時定数です。

  • floatMantissaBits(comptime T: type) comptime_int: 浮動小数点型の仮数部が占めるビット数を返します。Tf16/f32/f64/f128のいずれかです。
  • floatExponentBits(comptime T: type) comptime_int: 浮動小数点型の指数部が占めるビット数を返します。Tf16/f32/f64/f128のいずれかです。

関数

ジェネリック関数

整数型および浮動小数点型でジェネリックに利用できる関数です。

最小値を求める
fn min(x: anytype, y: anytype) Min(@TypeOf(x), @TypeOf(y))

2つの数値 (x / y) のうち、最小値を返します。

戻り値型は、以下のように決まります。

  • 符号なし整数型: ビット幅が小さい方の型になります。
  • その他の型: ビット幅が大きい方の型になります。

examples/ch09-std/math/src/generic.zen:4:29

const math = std.math;
test "math.min" {
    ok(math.min( @to(i32, -1), @to(i32, 2) ) == -1 );

    // 符号付き/符号なし同士であれば、異なる数値型同士も比較可能
    {
        var a: u16 = 16;
        var b: u32 = 1;
        ok(math.min( a, b ) == 1 );
        // 符号なし整数同士の場合、よりビット幅の少ない型が戻り値型になる
        ok(@TypeOf(math.min( a, b )) == u16 );
    }
    {
        var a: i16 = -16;
        var b: i32 = -1;
        ok(math.min( a, b ) == -16 );
        // 符号付き整数同士の場合、よりビット幅の多い型が戻り値型になる
        ok(@TypeOf(math.min( a, b )) == i32 );
    }
    {
        var a: f64 = 12.34;
        var b: f32 = 43.21;
        ok(math.min( a, b ) == 12.34 );
        ok(@TypeOf(math.min( a, b )) == f64 );
    }
}

ノート: math.Min 関数はコンパイル時に実行される関数で、2つの数値型について、符号なし整数型の場合はビット幅が小さい方の型を、それ以外の型の場合はビット幅が大きい方の型を返します。 この関数も pub なので、アプリケーションから利用することができます。

最大値を求める
fn max(x: anytype, y: anytype) @TypeOf(x + y)

2つの数値 (x / y) のうち、最大値を返します。戻り値型は、よりビット幅の大きい型になります。

ノート: @TypeOf(x + y)により、より数値の表現幅が広い型に解決されます。

累乗を求める
fn pow(comptime T: type, x: T, y: T) T

xy乗を計算します。現在浮動小数点型は、f32f64だけが利用できます。

整数型だけに使えるpowiもあります。

ゼロ除算/オーバーフロー検出機能付き除算/剰余

次の5つの関数は、整数と浮動小数点、両方に使用できる除算/剰余です。ゼロ除算を行おうとした時はerror.DivisionByZeroが、オーバーフロー発生時はerror.Overflowが返ります。

  • divTrunc
fn divTrunc(comptime T: type, numerator: T, denominator: T) !T

divTrunc0方向に丸める切り捨て除算を行います。

examples/ch09-std/math/src/generic.zen:31:44

test "divTrunc" {
    var result_i32 = try math.divTrunc(i32, 5, 3);
    ok(result_i32 == 1);
    result_i32 = try math.divTrunc(i32, -5, 3);
    ok(result_i32 == -1);

    err(error.DivisionByZero, math.divTrunc(i8, -5, 0));
    err(error.Overflow, math.divTrunc(i8, -128, -1));

    var result_f32 = try math.divTrunc(f32, 5.0, 3.0);
    ok(result_f32 == 1.0);
    result_f32 = try math.divTrunc(f32, -5.0, 3.0);
    ok(result_f32 == -1.0);
}
  • divFloor
fn divFloor(comptime T: type, numerator: T, denominator: T) !T

divFloorは負の無限大へ向かって丸めるフロア除算を行います。

examples/ch09-std/math/src/generic.zen:46:56

test "divFloor" {
    var result_i32 = try math.divFloor(i32, 5, 3);
    ok(result_i32 == 1);
    result_i32 = try math.divFloor(i32, -5, 3);
    ok(result_i32 == -2);

    var result_f32 = try math.divFloor(f32, 5.0, 3.0);
    ok(result_f32 == 1.0);
    result_f32 = try math.divFloor(f32, -5.0, 3.0);
    ok(result_f32 == -2.0);
}
  • divExact
fn divExact(comptime T: type, numerator: T, denominator: T) !T

divExactは割り切れる除算を行います。ゼロ除算、オーバーフローに加えて、余りが発生した場合error.UnexpectedRemainderを返します。

  • mod
fn mod(comptime T: type, numerator: T, denominator: T) !T

modは剰余を計算します。剰余は 0 または正数になります。ゼロ除算に加えて、除数が負数の場合error.NegativeDenominatorを返します。

  • rem
fn rem(comptime T: type, numerator: T, denominator: T) !T

remは剰余を計算します。剰余は被除数と同じ符号になります。ゼロ除算に加えて、除数が負数の場合error.NegativeDenominatorを返します。

modremの違いは、次の通りです。また、divFloordivTrunc との関係も記しています。

examples/ch09-std/math/src/generic.zen:58:76

test "mod vs rem" {
    const mod = try math.mod(i32, -5, 3);
    ok(mod == 1);

    const rem = try math.rem(i32, -5, 3);
    ok(rem == -2);

    const divfloor = try math.divFloor(i32, -5, 3);
    ok(divfloor == -2);

    const divtrunc = try math.divTrunc(i32, -5, 3);
    ok(divtrunc == -1);

    // divFloor(x, y) * y + mod(x, y) = x
    ok(divfloor * 3 + mod == -5);

    // divTrunc(x, y) * y + rem(x, y) = x
    ok(divtrunc * 3 + rem == -5);
}

対数を計算する

  • ln(x: anytype) @TypeOf(x): xの自然対数を計算します。
  • log(comptime T: type, base: T, x: T) T: baseを底とするxの対数を計算します。

整数演算

オーバーフロー検出機能付き演算
  • mul(comptime T: type, a: T, b: T) !T: 整数型Ta * bを計算します。オーバーフロー発生時は、error.Overflowが返ります。
  • add(comptime T: type, a: T, b: T) !T: 整数型Ta + bを計算します。オーバーフロー発生時は、error.Overflowが返ります。
  • sub(comptime T: type, a: T, b: T) !T: 整数型Ta - bを計算します。オーバーフロー発生時は、error.Overflowが返ります。
  • negate(x: anytype) !@TypeOf(x): -xを計算します。オーバーフロー発生時は、error.Overflowが返ります。
  • powi(comptime T: type, x: T, y: T) !T: 整数型Txy乗を計算します。オーバーフロー発生時はerror.Overflowが、アンダーフロー発生時はerror.Underflowが返ります。
ビットを回転する
  • rotr(comptime T: type, x: T, r: anytype) T: 右に回転します。Tは符号なし整数でなければなりません。
  • rotl(comptime T: type, x: T, r: anytype) T: 左に回転します。Tは符号なし整数でなければなりません。

型変換

  • negateCast
fn negateCast(x: anytype) !Int(true, @TypeOf(x).bit_count)

negateCastは、-xを計算します。xの型が符号なし整数型の場合、戻り値型は符号付き整数型に型変換されます。型変換の結果、オーバーフローが発生した場合、error.Overflowが返ります。

  • cast
fn cast(comptime T: type, x: anytype) (error{Overflow}!T)

castは整数型同士を型変換します。変換先の型の範囲内で、変換する値が表現できない場合、error.Overflowが返ります。

2の累乗

  • isPowerOfTwo(v: anytype) bool: vが2の累乗であればtrueを、そうでなければfalseを返します。
  • floorPowerOfTwo(comptime T: type, value: T) T: value以下の最大の2の累乗を返します。
  • ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T): value以上の最小の2の累乗を返します。Tは符号なし整数型でなければなりません。戻り値がTで表現できない値の場合、error.Overflowが返ります。
  • ceilPowerOfTwoPromote(comptime T: type, value: T) T+1ビット幅の整数型: value以上の最小の2の累乗を返します。Tは符号なし整数型でなければなりません。戻り値型は、T + 1ビットの整数型になるため、オーバーフローは発生しません。

examples/ch09-std/math/src/power_of_two.zen:6:28

test "powerOfTwo" {
    // 2の累乗であれば`true`、そうでなければ`false`
    ok(math.isPowerOfTwo(2) == true);
    ok(math.isPowerOfTwo(3) == false);

    // 引数以下の最大の2の累乗を返す
    ok(math.floorPowerOfTwo(u32, 63) == 32);
    ok(math.floorPowerOfTwo(u32, 64) == 64);
    ok(math.floorPowerOfTwo(u32, 65) == 64);

    // 引数以上の最小の2の累乗を返す
    ok(( try math.ceilPowerOfTwo(u32, 63) ) == 64);
    ok(( try math.ceilPowerOfTwo(u32, 64) ) == 64);
    ok(( try math.ceilPowerOfTwo(u32, 65) ) == 128);
    // `256`は`u8`では表現できないため、オーバーフロー
    err(error.Overflow, math.ceilPowerOfTwo(u8, 255));
    // 戻り値型は、引数型と同じ
    ok(@TypeOf(try math.ceilPowerOfTwo(u32, 63)) == u32);

    // 戻り値型は、`引数型+1ビットの整数型`になる
    ok(math.ceilPowerOfTwoPromote(u8, 255) == 256);
    ok(@TypeOf(math.ceilPowerOfTwoPromote(u8, 255)) == u9);
}

浮動小数点

  • isNan(x: anytype) bool: xがNaNならtrue、そうでなければfalseを返します。
  • isSignalNan(x: anytype) bool: xがSignalling NaNならtrue、そうでなければfalseを返します。
  • isFinite(x: anytype) bool: xが有限値であればtrue、そうでなければfalseを返します。
  • isInf(x: anytype) bool: xが無限大であればtrue、そうでなければfalseを返します。符号は考慮しません。
  • isPositiveInf(x: anytype) bool: xが正の無限大であればtrue、そうでなければfalseを返します。
  • isNegativeInf(x: anytype) bool: xが負の無限大であればtrue、そうでなければfalseを返します。
  • isNormal(x: anytype) bool: xが正規化数 (仮数部が1) であればtrue、そうでなければfalseを返します。
  • signbit(x: anytype) bool: xが負数か負の0であればtrue、そうでなければfalseを返します。

浮動小数点演算

  • approxEq(comptime T: type, x: T, y: T, epsilon: T) bool: xyの差がepsilonより小さければtrue、そうでなければfalseを返します。
  • copysign(comptime T: type, x: T, y: T) T: xの指数部と仮数部に、yの符号ビットを付けた数値を返します。

examples/ch09-std/math/src/floats.zen:6:9

test "math.copysign" {
    ok(math.copysign(f64, 5.0, -1.0) == -5.0);
    ok(math.copysign(f64, -5.0, 1.0) == 5.0);
}
  • modf(x: anytype) modf_result(@TypeOf(x)): xを整数部と小数部に分割します。結果はstruct { fpart: T, ipart: T}に格納されます。

examples/ch09-std/math/src/floats.zen:11:16

test "math.modf" {
    const epsilon = 0.000001;
    var r = math.modf(@to(f64, 2.545));
    ok(math.approxEq(f64, r.ipart, 2.0, epsilon));
    ok(math.approxEq(f64, r.fpart, 0.545, epsilon));
}
  • scalbn(x: anytype, n: i32) @TypeOf(x): x * 2^nを計算します。

examples/ch09-std/math/src/floats.zen:18:21

test "math.scalbn" {
    // 1.5 * 16
    ok(math.scalbn(@to(f64, 1.5), @to(f64, 4)) == 24.0);
}
  • cbrt(x: anytype) @TypeOf(x): xの立方根を計算します。
  • hypot(comptime T: type, x: T, y: T) T: 2辺の長さが x, y の直角三角形の斜辺の長さを計算します。 (sqrt(x * x + y * y) )
  • fma(comptime T: type, x: T, y: T, z: T) T: x, y, z の積和演算 (x * y + z) を行います。

絶対値を計算する

  • absInt(x: anytype) !@TypeOf(x): 整数xの絶対値を計算します。xは符号付き整数型の値でなければなりません。xの絶対値が、xの型で表現できる範囲内に収まらない場合、error.Overflowが返ります。
  • absFloat(x: anytype) @TypeOf(x): 浮動小数点xの絶対値を計算します。
  • absCast(x: anytype) (comptime_intかx+1ビットの整数型): 整数xの絶対値を計算します。戻り値型は、comptime_intか、xの型 + 1ビットの整数型です。

三角関数

  • sin(x: anytype) @TypeOf(x)
  • sinh(x: anytype) @TypeOf(x)
  • cos(x: anytype) @TypeOf(x)
  • cosh(x: anytype) @TypeOf(x)
  • tan(x: anytype) @TypeOf(x)
  • tanh(x: anytype) @TypeOf(x)
  • acos(x: anytype) @TypeOf(x)
  • acosh(x: anytype) @TypeOf(x)
  • asin(x: anytype) @TypeOf(x)
  • asinh(x: anytype) @TypeOf(x)
  • atan(x: anytype) @TypeOf(x)
  • atan2(comptime T: type, y: T, x: T) T
  • atanh(x: anytype) @TypeOf(x)

複素数

複素数型
  • Complex(T) = struct { re: T, im: T }: Tは浮動小数点型でなければなりません。

次のメソッドを実装しています。

  • new(re: T, im: T) Self: 新しいインスタンスを生成します。
  • add(self: Self, other: Self) Self: 2つの複素数値を加算します。
  • sub(self: Self, other: Self) Self: 2つの複素数値を減算します。
  • mul(self: Self, other: Self) Self: 2つの複素数値を乗算します。
  • div(self: Self, other: Self) Self: 2つの複素数値を除算します。
  • conjugate(self: Self) Self: 複素共役を計算します。
  • reciprocal(self: Self) Self: 複素数の逆数を計算します。
  • magnitude(self: Self) T: 複素数の大きさを計算します。

complex.zenモジュールは、他にも、abssinexplogsqrtなどを計算する関数を提供しています。

型定義

  • Int(comptime is_signed: bool, comptime bits: comptime_int) type: 与えられた符号の有無とビット数を持つ整数型を返します。整数型の最大ビット数は 65535 です。

examples/ch09-std/math/src/type.zen:5:17

test "Int type" {
    // 符号付き 129ビット整数型
    const I129 = math.Int(true, 129);
    ok(@typeInfo(I129) == .Int);
    ok(@typeInfo(I129).Int.is_signed == true);
    ok(@typeInfo(I129).Int.bits == 129);

    // 符号なし 7ビット整数型
    const U7 = math.Int(false, 7);
    ok(@typeInfo(U7) == .Int);
    ok(@typeInfo(U7).Int.is_signed == false);
    ok(@typeInfo(U7).Int.bits == 7);
}

Chapter 1

Chapter 2

Chapter 3

Chapter 4

Chapter 5

Chapter 6

Chapter 7

Chapter 8

Chapter 9

Chapter 10

Chapter 11

Chapter 12

Chapter 13

Chapter 14

Chapter 15

Appendix

Error Explanation

☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 connectFree Corporation. All rights reserved. | 特定商取引法に基づく表示
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.