core API
ルートパッケージ Luna-Flow/luna-complex は、任意のスカラー型 T 上の複素数 である Complex[T] を定義し、構築、インプレースでの変更、共役、算術演算子、luna-generic の代数構造トレイトを提供します。解析関数は含まず、それらは float_backend にあります。各インスタンスの背後にある代数は core の設計 で説明しています。
ソース: src/complex.mbt、src/complex_traits.mbt、src/extends.mbt。
インポート
import {
"Luna-Flow/luna-complex" @complex,
}
例ではエイリアス @complex を使います。
型
Complex
実部 re と虚部 im を持つ複素数です。
pub(all) struct Complex[T] {
mut re : T
mut im : T
} derive(Eq, @debug.Debug)
値は のもとでの です。両フィールドとも公開かつ可変で、構造体は pub(all) なので、パッケージ外のコードからも読み書きでき、レコードリテラルで構築できます。Complex[T] は参照型であり、同じ値への 2 つの束縛は互いの更新を観測します。
derive(Eq) は両方の部分を T の等価性で比較します(Double では 0.0 == -0.0 であり、NaN は自分自身と等しくありません)。derive(Debug) はレコード形式 { re: …, im: … } を出力します。
構築と変更
Complex::new
を構築します。
pub fn[T] Complex::new(T, T) -> Complex[T]
Complex::set
両方の部分をインプレースで上書きします。
pub fn[T] Complex::set(Complex[T], T, T) -> Unit
Complex::set_re
実部をインプレースで上書きします。
pub fn[T] Complex::set_re(Complex[T], T) -> Unit
Complex::set_im
虚部をインプレースで上書きします。
pub fn[T] Complex::set_im(Complex[T], T) -> Unit
test "construct and mutate" {
let z = @complex.Complex::new(1.0, 2.0)
assert_eq(z.re, 1.0)
z.set(3.0, 4.0)
z.set_im(-1.0)
assert_eq(z, @complex.Complex::new(3.0, -1.0))
}
単位元
Complex::zero
を返します。
pub fn[T : @luna-generic.Zero] Complex::zero() -> Complex[T]
Complex::one
を返します。
pub fn[T : @luna-generic.One + @luna-generic.Zero] Complex::one() -> Complex[T]
どちらも Zero および One インスタンスから昇格されたメソッドです。
算術
各演算は演算子としても、昇格されたメソッドとしても利用できます。
| 項目 | 演算子 | 結果 | T への制約 |
|---|---|---|---|
Complex::add | z + w | Add | |
Complex::sub | z - w | Sub | |
Complex::neg | -z | Neg | |
Complex::mul | z * w | Mul + Add + Sub | |
Complex::div | z / w | Field |
ここで 、 とします。
Complex::add
成分ごとに加算します。
pub fn[T : Add] Complex::add(Complex[T], Complex[T]) -> Complex[T]
pub impl[T : Add] Add for Complex[T]
Complex::sub
成分ごとに減算します。
pub fn[T : Sub] Complex::sub(Complex[T], Complex[T]) -> Complex[T]
pub impl[T : Sub] Sub for Complex[T]
Complex::neg
両方の部分の符号を反転します。
pub fn[T : Neg] Complex::neg(Complex[T]) -> Complex[T]
pub impl[T : Neg] Neg for Complex[T]
Complex::mul
を用いて、4 回の乗算で乗算します。
pub fn[T : Mul + Add + Sub] Complex::mul(Complex[T], Complex[T]) -> Complex[T]
pub impl[T : Mul + Add + Sub] Mul for Complex[T]
Complex::div
絶対値の 2 乗の逆数を掛けることで除算します。
pub fn[T : @luna-generic.Field] Complex::div(Complex[T], Complex[T]) -> Complex[T]
pub impl[T : @luna-generic.Field] Div for Complex[T]
を計算し、次に Inverse::inv(n) を求め、 の両方の部分にそれを掛けます。この式はスケーリングされていません。Double では で がオーバーフローし、 でアンダーフローします。また Double の Inverse::inv は、 がゼロのとき(アンダーフローの結果ゼロになった場合を含む)Double::inv: division by zero で中断します。堅牢な浮動小数点除算には @fb.div を使ってください。
test "complex arithmetic" {
let z = @complex.Complex::new(1.0, 2.0)
let w = @complex.Complex::new(3.0, -1.0)
assert_eq(z + w, @complex.Complex::new(4.0, 1.0))
assert_eq(z - w, @complex.Complex::new(-2.0, 3.0))
assert_eq(z * w, @complex.Complex::new(5.0, 5.0))
assert_eq(z * w / w, z)
assert_eq(-z, @complex.Complex::new(-1.0, -2.0))
}
共役と逆数
Complex::conjugate
を返します。
pub fn[T : Neg] Complex::conjugate(Complex[T]) -> Complex[T]
pub impl[T : Neg] @luna-generic.Conjugate for Complex[T]
Complex::inv
を返します。
pub fn[T : @luna-generic.Field] Complex::inv(Complex[T]) -> Complex[T]
pub impl[T : @luna-generic.Field] @luna-generic.Inverse for Complex[T]
Complex::div と同じくスケーリングされていない式を使い、絶対値がゼロのときに同じく中断します。
test "conjugate and inverse" {
let z = @complex.Complex::new(3.0, 4.0)
assert_eq(z.conjugate(), @complex.Complex::new(3.0, -4.0))
assert_eq(z * z.conjugate(), @complex.Complex::new(25.0, 0.0))
assert_eq(z.inv(), @complex.Complex::new(0.12, -0.16))
}
等価性とテキスト
Complex::equal
両方の部分を比較します。derive された Eq から昇格されたメソッドです。== を使うことを推奨します。
pub fn[T : Eq] Complex::equal(Complex[T], Complex[T]) -> Bool
Complex::to_string
T の Show を使って を "<re> + <im>i" の形式に整形します。
pub fn[T : Show] Complex::to_string(Complex[T]) -> String
pub impl[T : Show] Show for Complex[T]
虚部の符号は T が出力するため、 は 1 + -2i と出力されます。文字列補間 "\{z}" も同じテキストを使います。
test "text form" {
inspect(@complex.Complex::new(1.5, -2.0), content="1.5 + -2i")
debug_inspect(@complex.Complex::new(1, 2), content="{ re: 1, im: 2 }")
}
構造インスタンス
Complex[T] は以下の制約のもとで luna-generic の代数構造トレイトを実装します。各法則の導出は core の設計 にあります。
| インスタンス | T への制約 |
|---|---|
Zero | Zero |
One | One + Zero |
AddMonoid | Add + Zero |
AddGroup | Add + Zero + Neg + Sub |
MulMonoid | Ring |
Semiring | Ring |
Ring | Ring |
Inverse | Field |
MulGroup | Field |
Field | Field |
Conjugate | Neg |
fn[T : @lg.Field] average(a : T, b : T) -> T {
let two = @lg.One::one() + @lg.One::one()
(a + b) / two
}
test "generic field code accepts complex numbers" {
let m = average(@complex.Complex::new(1.0, 2.0), @complex.Complex::new(3.0, 0.0))
assert_eq(m, @complex.Complex::new(2.0, 1.0))
}
非推奨
これらのメソッド形式はトレイトインスタンスに由来し、インターフェースファイルからは隠されています。パッケージ外で使うと警告が出ます。
| 非推奨のメソッド | 代替 |
|---|---|
z.not_equal(w) | z != w |
z.output(logger) | z.to_string() または "\{z}" |
z.to_repr() | Repr(z) または @debug.Debug::to_repr(z) |