frontend/testfloat_expr API

frontend/testfloat_expr は Berkeley TestFloat のテストベクタを構文解析し、binary16、binary32、binary64、binary128 の交換形式で bin_float に対して実行します。TestFloatSpec はベクタファイルを生成した関数、丸めモード、極小性の規則、厳密性を記述します。parse_testfloat がベクタを読み込み、execute_document がそれを実行します。このパッケージは IO を行わず、ランナーは cli/testfloat_expr_cli です。ワークフローはチュートリアルで示し、合格規則は設計ページで規定します。

moon.pkg でパッケージをインポートします:

import {
  "Luna-Flow/floating/frontend/testfloat_expr",
}

関数の指定

TestFloatOperation

TestFloatOperation はエグゼキュータがサポートする TestFloat の関数を列挙します。

pub(all) enum TestFloatOperation {
  Add
  Subtract
  Multiply
  Divide
  SquareRoot
  MulAdd
  Remainder
  RoundToInt
  ToInt32
  ToInt64
  ToUInt32
  ToUInt64
  Equal
  LessEqual
  Less
  EqualSignaling
  LessEqualQuiet
  LessQuiet
} derive(Eq, @debug.Debug)
コンストラクタTestFloat での名前オペランドbin_float のメソッド
Add, Subtract, Multiply, Divideadd, sub, mul, div2add_ctx, sub_ctx, mul_ctx, div_ctx
SquareRootsqrt1sqrt_ctx
MulAddmulAdd3fma_ctx
Remainderrem2remainder_ctx
RoundToIntroundToInt1厳密版なら to_integral_exact_ctx、そうでなければ to_integral_value_ctx
ToInt32, ToInt64, ToUInt32, ToUInt64to_i32, to_i64, to_ui32, to_ui641exact~ 付きの to_int_ctx、to_int64_ctx、to_uint_ctx、to_uint64_ctx
Equal, LessEqual, Lesseq, le, lt2equal_quiet, less_equal_signaling, less_signaling
EqualSignaling, LessEqualQuiet, LessQuieteq_signaling, le_quiet, lt_quiet2equal_signaling, less_equal_quiet, less_quiet

TestFloatSpec

TestFloatSpec は 1 回の TestFloat 実行の構成です。

pub struct TestFloatSpec {
  // private fields
} derive(Eq, @debug.Debug)

TestFloatSpec::parse

TestFloatSpec::parse(function_name, rounding, tininess?, exact?) は TestFloat の名前から仕様を構築します。

pub fn TestFloatSpec::parse(String, String, tininess? : String, exact? : Bool) -> Result[Self, String]

function_name は FORMAT_OPERATION の形です。最初の _ より前の部分が形式(f16、f32、f64、f128)、残りが演算(add、mulAdd、to_ui64、le_quiet、…)です。名前は -、_、空白を除去したうえで大文字小文字を区別せずに照合されます。rounding は rnear_even、rnear_maxMag、rminMag、rmin、rmax のいずれかです(先頭の r を省いた形や、IEEE の名前 roundTiesToEven、roundTiesToAway、roundTowardZero、roundTowardNegative、roundTowardPositive も受け付けます)。tininess は "after"(デフォルト)または "before" です(tininessAfter、tininessBefore も可)。exact(デフォルト false)は、roundToInt と整数変換について TestFloat の -exact 版を選択します。エラーは "unsupported TestFloat function name …"、"… format …"、"… operation …"、"… rounding mode …"、"… tininess mode …" です。

///|
test "spec parse" {
  let spec = @testfloat_expr.TestFloatSpec::parse(
    "f128_mulAdd",
    "rminMag",
    tininess="before",
  ).unwrap()
  inspect(spec.operation() == @testfloat_expr.MulAdd, content="true")
  inspect(spec.format() == @bin_float.Binary128, content="true")
  inspect(spec.rounding() == @bin_float.RoundTowardZero, content="true")
  inspect(
    @testfloat_expr.TestFloatSpec::parse("f64_mul", "rodd") is Err(_),
    content="true",
  )
}

TestFloatSpec::function_name, format, operation, rounding, tininess, exact

これらのアクセサは構文解析された構成を返します。

pub fn TestFloatSpec::function_name(Self) -> String
pub fn TestFloatSpec::format(Self) -> @bin_float.BinaryInterchangeFormat
pub fn TestFloatSpec::operation(Self) -> TestFloatOperation
pub fn TestFloatSpec::rounding(Self) -> @bin_float.BinaryRoundingMode
pub fn TestFloatSpec::tininess(Self) -> @bin_float.TininessDetection
pub fn TestFloatSpec::exact(Self) -> Bool

function_name は与えられたとおりの名前です。

解析

parse_testfloat

parse_testfloat(source, text, spec) は 1 つの関数のベクタを構文解析します。

pub fn parse_testfloat(String, String, TestFloatSpec) -> Result[TestFloatDocument, Array[ParseDiagnostic]]

各行は前後の空白が除去され、空行と # で始まる行はスキップされます。ベクタは空白区切りの k+2k + 2 個のフィールドからなります。ここで kk は演算のオペランド数で、内訳は kk 個のオペランドのエンコーディング、期待結果、および 2 桁の 16 進フラグマスクです。オペランドのエンコーディングは spec.format() の 16 進ビットパターンです。期待結果は、算術演算ではエンコーディング、変換では最大 16 桁の 16 進整数、比較では 0 または 1 です。フィールド数が誤っていると "unexpected TestFloat field count"、読み取れないフィールドがあると "invalid TestFloat hexadecimal field" になります。結果が Ok になるのは無効な行が 1 つもない場合だけです。

TestFloatDocument

TestFloatDocument は構文解析済みのベクタファイルです。

pub struct TestFloatDocument {
  // private fields
}
pub fn TestFloatDocument::source(Self) -> String
pub fn TestFloatDocument::spec(Self) -> TestFloatSpec
pub fn TestFloatDocument::cases(Self) -> Array[TestFloatCase]
pub fn TestFloatDocument::case_count(Self) -> Int

cases はベクタのコピーをファイル順に返します。

TestFloatCase

TestFloatCase は 1 つのベクタです。

pub struct TestFloatCase {
  // private fields
}
pub fn TestFloatCase::id(Self) -> String
pub fn TestFloatCase::line(Self) -> Int

id は FUNCTION:LINE で、例えば f64_mulAdd:17 です。

ParseDiagnostic

ParseDiagnostic は 1 つの無効な行です。

pub struct ParseDiagnostic {
  // private fields
} derive(Eq, @debug.Debug)
pub fn ParseDiagnostic::source(Self) -> String
pub fn ParseDiagnostic::line(Self) -> Int
pub fn ParseDiagnostic::message(Self) -> String

実行

execute_document

execute_document(document, options?) は選択されたベクタを実行します。

pub fn execute_document(TestFloatDocument, options? : RunOptions) -> RunSummary

ベクタ kk(ファイル順に 0 から数える)は、シャード数 nn、インデックス ii に対して k mod n=ik \bmod n = i のとき実行されます。オペランドは BinFloat にデコードされ、演算は spec.format().context(rounding~, tininess~) のもとで実行されます。ベクタは次の場合に合格です。

  • 算術演算: 結果を同じ丸めと極小性でその形式に再エンコードしたものが期待されるビットパターンとちょうど一致するか、期待結果が任意の NaN で実際の結果が quiet NaN であること。かつ、演算のフラグとエンコーディングのフラグを合わせた SoftFloat マスクが期待マスクと等しいこと。
  • 整数変換: 期待マスクに invalid ビット 10 が立っている場合、変換は invalid(None)を報告しなければならず、値フィールドは無視されます。そうでなければ、変換は期待される整数を返さなければなりません(符号付きの結果は 2 の補数のビットパターンとして比較)。いずれの場合もフラグマスクが等しくなければなりません。
  • 比較: 真偽値とフラグマスクが等しいこと。

選択されたベクタはすべて実行対象であり、スキップされるベクタはありません。

RunOptions

RunOptions はシャードを選択します。

pub struct RunOptions {
  // private fields
}
pub fn RunOptions::new(shard_count? : Int, shard_index? : Int) -> Self
pub fn RunOptions::shard_count(Self) -> Int
pub fn RunOptions::shard_index(Self) -> Int

デフォルト:シャード 1 つ、インデックス 0。RunOptions::new は shard_count > 0 かつ 0 <= shard_index < shard_count でなければ異常終了します。

結果

CaseResult

CaseResult は 1 つのベクタの結果です。

pub struct CaseResult {
  // private fields
}
pub fn CaseResult::id(Self) -> String
pub fn CaseResult::passed(Self) -> Bool
pub fn CaseResult::message(Self) -> String

メッセージ:合格なら空。それ以外は "value mismatch: expected HEX, actual HEX"、"integer mismatch: …"、"comparison mismatch: …"、または "flags mismatch: expected M, actual M"(マスクは 10 進表記)。

RunSummary

RunSummary は 1 回の実行を集計します。

pub struct RunSummary {
  // private fields
}
pub fn RunSummary::total_cases(Self) -> Int
pub fn RunSummary::selected_cases(Self) -> Int
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[CaseResult]
pub fn RunSummary::success(Self) -> Bool

total_cases は文書中のベクタ数、selected_cases = passed_cases + failed_cases はこのシャードで実行された数で、success はどれも失敗しなかったとき真です。

トレイト実装

TestFloatOperation、TestFloatSpec、ParseDiagnostic の等価性と Debug

これらのメソッドはすべてのフィールドを比較し、値を Debug 用に描画します。新しいコードでは ==、!=、debug_inspect を使ってください。

pub fn TestFloatOperation::equal(Self, Self) -> Bool
pub fn TestFloatOperation::not_equal(Self, Self) -> Bool
pub fn TestFloatOperation::to_repr(Self) -> @debug.Repr
pub fn TestFloatSpec::equal(Self, Self) -> Bool
pub fn TestFloatSpec::not_equal(Self, Self) -> Bool
pub fn TestFloatSpec::to_repr(Self) -> @debug.Repr
pub fn ParseDiagnostic::equal(Self, Self) -> Bool
pub fn ParseDiagnostic::not_equal(Self, Self) -> Bool
pub fn ParseDiagnostic::to_repr(Self) -> @debug.Repr

公開インターフェース全体

このスナップショットは、パッケージの生成された pkg.generated.mbti です。説明文とインターフェースが食い違う場合は、こちらが正となります。

// Generated using `moon info`, DON'T EDIT IT
package "Luna-Flow/floating/frontend/testfloat_expr"

import {
  "Luna-Flow/floating/bin_float",
  "moonbitlang/core/debug",
}

// Values
pub fn execute_document(TestFloatDocument, options? : RunOptions) -> RunSummary

pub fn parse_testfloat(String, String, TestFloatSpec) -> Result[TestFloatDocument, Array[ParseDiagnostic]]

// Errors

// Types and methods
pub struct CaseResult {
  // private fields
}
pub fn CaseResult::id(Self) -> String
pub fn CaseResult::message(Self) -> String
pub fn CaseResult::passed(Self) -> Bool

pub struct ParseDiagnostic {
  // private fields
} derive(Eq, @debug.Debug)
pub fn ParseDiagnostic::equal(Self, Self) -> Bool
pub fn ParseDiagnostic::line(Self) -> Int
pub fn ParseDiagnostic::message(Self) -> String
pub fn ParseDiagnostic::not_equal(Self, Self) -> Bool
pub fn ParseDiagnostic::source(Self) -> String
pub fn ParseDiagnostic::to_repr(Self) -> @debug.Repr

pub struct RunOptions {
  // private fields
}
pub fn RunOptions::new(shard_count? : Int, shard_index? : Int) -> Self
pub fn RunOptions::shard_count(Self) -> Int
pub fn RunOptions::shard_index(Self) -> Int

pub struct RunSummary {
  // private fields
}
pub fn RunSummary::failed_cases(Self) -> Int
pub fn RunSummary::passed_cases(Self) -> Int
pub fn RunSummary::results(Self) -> Array[CaseResult]
pub fn RunSummary::selected_cases(Self) -> Int
pub fn RunSummary::success(Self) -> Bool
pub fn RunSummary::total_cases(Self) -> Int

pub struct TestFloatCase {
  // private fields
}
pub fn TestFloatCase::id(Self) -> String
pub fn TestFloatCase::line(Self) -> Int

pub struct TestFloatDocument {
  // private fields
}
pub fn TestFloatDocument::case_count(Self) -> Int
pub fn TestFloatDocument::cases(Self) -> Array[TestFloatCase]
pub fn TestFloatDocument::source(Self) -> String
pub fn TestFloatDocument::spec(Self) -> TestFloatSpec

pub(all) enum TestFloatOperation {
  Add
  Subtract
  Multiply
  Divide
  SquareRoot
  MulAdd
  Remainder
  RoundToInt
  ToInt32
  ToInt64
  ToUInt32
  ToUInt64
  Equal
  LessEqual
  Less
  EqualSignaling
  LessEqualQuiet
  LessQuiet
} derive(Eq, @debug.Debug)
pub fn TestFloatOperation::equal(Self, Self) -> Bool
pub fn TestFloatOperation::not_equal(Self, Self) -> Bool
pub fn TestFloatOperation::to_repr(Self) -> @debug.Repr

pub struct TestFloatSpec {
  // private fields
} derive(Eq, @debug.Debug)
pub fn TestFloatSpec::equal(Self, Self) -> Bool
pub fn TestFloatSpec::exact(Self) -> Bool
pub fn TestFloatSpec::format(Self) -> @bin_float.BinaryInterchangeFormat
pub fn TestFloatSpec::function_name(Self) -> String
pub fn TestFloatSpec::not_equal(Self, Self) -> Bool
pub fn TestFloatSpec::operation(Self) -> TestFloatOperation
pub fn TestFloatSpec::parse(String, String, tininess? : String, exact? : Bool) -> Result[Self, String]
pub fn TestFloatSpec::rounding(Self) -> @bin_float.BinaryRoundingMode
pub fn TestFloatSpec::tininess(Self) -> @bin_float.TininessDetection
pub fn TestFloatSpec::to_repr(Self) -> @debug.Repr

// Type aliases

// Traits