core API

根包 Luna-Flow/luna-complex 定义了 Complex[T],即任意标量类型 T 上的复数 a+bia + bi,并提供构造、原地修改、共轭、算术运算符以及 luna-generic 结构 trait。它不包含解析函数;这些函数位于 float_backend。这些实例背后的代数原理见核心设计。

源码: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)

其值为 re+im i\texttt{re} + \texttt{im}\,i,其中 i2=−1i^2 = -1。两个字段都是公开且可变的,且该结构体为 pub(all),因此包外代码可以读取、写入它,并用记录字面量构造它。Complex[T] 是引用类型:绑定到同一个值的两个变量能看到彼此的修改。

derive(Eq) 使用 T 的相等性比较两个部分(对于 Double,0.0 == -0.0,且 NaN 不等于自身)。derive(Debug) 打印记录形式 { re: …, im: … }。

构造与修改

Complex::new

构造 re+im ire + im\,i。

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

返回 0+0i0 + 0i。

pub fn[T : @luna-generic.Zero] Complex::zero() -> Complex[T]

Complex::one

返回 1+0i1 + 0i。

pub fn[T : @luna-generic.One + @luna-generic.Zero] Complex::one() -> Complex[T]

两者分别是 Zero 和 One 实例的提升方法。

算术

每种运算既可作为运算符使用,也可作为提升方法使用。

项目运算符结果对 T 的约束
Complex::addz + w(a+c)+(b+d)i(a + c) + (b + d)iAdd
Complex::subz - w(a−c)+(b−d)i(a - c) + (b - d)iSub
Complex::neg-z−a−bi-a - biNeg
Complex::mulz * w(ac−bd)+(ad+bc)i(ac - bd) + (ad + bc)iMul + Add + Sub
Complex::divz / w(ac+bd)+(bc−ad)ic2+d2\dfrac{(ac + bd) + (bc - ad)i}{c^2 + d^2}Field

此处 z=a+biz = a + bi,w=c+diw = c + di。

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

按 i2=−1i^2 = -1 相乘,使用四次乘法。

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

通过乘以模平方的倒数来做除法。

pub fn[T : @luna-generic.Field] Complex::div(Complex[T], Complex[T]) -> Complex[T]
pub impl[T : @luna-generic.Field] Div for Complex[T]

它先计算 n=c2+d2n = c^2 + d^2,再计算 Inverse::inv(n),并用它乘以 zwˉz\bar w 的两个部分。该公式未做缩放:对于 Double,当 ∣w∣≳10154|w| \gtrsim 10^{154} 时 c2+d2c^2 + d^2 上溢,当 ∣w∣≲10−162|w| \lesssim 10^{-162} 时下溢;而当 nn 为零(包括下溢导致为零)时,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

返回 zˉ=a−bi\bar z = a - bi。

pub fn[T : Neg] Complex::conjugate(Complex[T]) -> Complex[T]
pub impl[T : Neg] @luna-generic.Conjugate for Complex[T]

Complex::inv

返回 z−1=zˉ/(a2+b2)z^{-1} = \bar z / (a^2 + b^2)。

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

比较两个部分;是派生的 Eq 的提升方法。建议使用 ==。

pub fn[T : Eq] Complex::equal(Complex[T], Complex[T]) -> Bool

Complex::to_string

使用 T 的 Show 将 zz 格式化为 "<re> + <im>i"。

pub fn[T : Show] Complex::to_string(Complex[T]) -> String
pub impl[T : Show] Show for Complex[T]

虚部的符号由 T 打印,因此 1−2i1 - 2i 打印为 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 的结构 trait。核心设计推导了每条定律。

实例对 T 的约束
ZeroZero
OneOne + Zero
AddMonoidAdd + Zero
AddGroupAdd + Zero + Neg + Sub
MulMonoidRing
SemiringRing
RingRing
InverseField
MulGroupField
FieldField
ConjugateNeg
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))
}

已弃用

这些方法形式来自 trait 实例,并在接口文件中隐藏;在包外使用时会发出警告。

已弃用的方法替代方案
z.not_equal(w)z != w
z.output(logger)z.to_string() 或 "\{z}"
z.to_repr()Repr(z) 或 @debug.Debug::to_repr(z)