immut API

Luna-Flow/linear-algebra/immut 提供面向值的稠密线性代数:Matrix[T] 和 Vector[T] 是由持久化向量支撑的不可变值,MatrixFn[T] 是由坐标函数给出的惰性矩阵。每个操作都返回新值,并保持参数不变。

源码:src/immut。值语义、行列式算法和开销模型见 immut 设计;mutable 是与之对应的原地修改版本,核心名称相同。

导入

///|
import {
  "Luna-Flow/linear-algebra/immut",
}

约定

  • 形状。 矩阵有 row() 行和 col() 列,两者均非负。0×n0 \times n 和 n×0n \times 0 都是合法且互不相同的形状;== 比较形状和元素。
  • 存储。 元素按行主序存储在持久化向量(moonbitlang/core/immut/vector,一种 32 路 trie)中。读取或替换一个元素的开销为 O(log⁡32(rc))O(\log_{32}(rc));整矩阵操作的开销为 O(rc)O(rc)。
  • 索引。 m[r][c] 读取一个元素:m[r](Matrix::at)返回一个 Indexed[T] 行访问器,[c](Indexed::at)从中读取。两个索引都会做边界检查,越界时中止。不存在 m[r][c] = x;请使用 set,它返回一个新矩阵。
  • 受检与非受检。 matmul、trace、determinant 和 pow 返回 Result[_, LinearAlgebraError]。它们对应的 unchecked_* 版本以及运算符 +、-、* 在前置条件不满足时中止。两者之间的关系见 error 设计。
  • 标量。 约束来自 luna-generic:Zero、One、Semiring、Num(带 abs 和 signum 的环)、Conjugate。

类型

Matrix

Matrix[T] 是不可变的稠密 r×cr \times c 矩阵。

type Matrix[T] derive(Eq)

该类型是抽象的:请使用下文的构造函数构建它。在相应方法的元素约束下,它实现了 Eq、Show(各行打印为 |a, b|,以换行分隔)、Add、Sub、Neg、Mul(矩阵乘积)。

Indexed

Indexed[T] 是 m[r] 返回的行访问器。

type Indexed[T]

它是从列索引到元素的函数;不持有该行的副本。

Indexed::at

Indexed::at(row, c) 返回第 c 列的元素;它是 m[r][c] 的底层实现。

#alias("_[_]")
pub fn[T] Indexed::at(Self[T], Int) -> T

超出 0..<col() 的列索引会导致中止。

MatrixFn

MatrixFn[T] 是惰性矩阵:由一个形状和一个函数 (i,j)↦aij(i, j) \mapsto a_{ij} 组成。

type MatrixFn[T]

元素在每次读取时计算,从不存储。它的方法列在 MatrixFn 操作中。

Vector

Vector[T] 是不可变的稠密向量。

#alias(VecLib)
type Vector[T] derive(Eq)

它实现了 Eq、Show(打印为 |a, b, c|)、Add、Mul(按元素)、Neg、Debug 以及 quickcheck 的 Arbitrary。

VecLib

VecLib[T] 是 Vector[T] 的别名。

#alias(VecLib)
type Vector[T]

VecCore

VecCore[T] 是支撑 Vector 的核心持久化向量 @moonbitlang/core/immut/vector.Vector[T] 的别名。

pub using @vector {type Vector as VecCore}

矩阵构造

Matrix::make

Matrix::make(r, c, f) 构建元素为 aij=f(i,j)a_{ij} = f(i, j) 的 r×cr \times c 矩阵。

pub fn[T] Matrix::make(Int, Int, (Int, Int) -> T) -> Self[T]

f 按行主序对每个元素调用一次;当 r=0r = 0 或 c=0c = 0 时完全不会调用。负的维度会导致中止。

Matrix::new

Matrix::new(r, c, x) 构建一个所有元素均为 x 的 r×cr \times c 矩阵。

pub fn[T] Matrix::new(Int, Int, T) -> Self[T]

Matrix::from_2d_array

Matrix::from_2d_array(rows) 从按行组织的嵌套数组构造矩阵。

pub fn[T] Matrix::from_2d_array(Array[Array[T]]) -> Self[T]

[] 得到 0×00 \times 0;[[], []] 得到 2×02 \times 0。各行长度不同会导致中止。输入会被复制。

Matrix::from_array

Matrix::from_array(r, c, v) 将向量 v 用作 r×cr \times c 矩阵按行主序排列的元素。

pub fn[T] Matrix::from_array(Int, Int, Vector[T]) -> Self[T]

负的维度或 v.length() != r * c 会导致中止。不会进行复制;v 是不可变的。

Matrix::identity

Matrix::identity(n) 构建 n×nn \times n 单位矩阵 InI_n。

pub fn[T : @luna-generic.One + @luna-generic.Zero] Matrix::identity(Int) -> Self[T]

负的 n 会导致中止。

///|
test "immut matrix construction" {
  let a = @immut.Matrix::make(2, 3, (i, j) => 10 * i + j)
  inspect(a, content="|0, 1, 2|\n|10, 11, 12|")
  let b = @immut.Matrix::from_array(
    2,
    2,
    @immut.Vector::from_array([1, 2, 3, 4]),
  )
  inspect(b, content="|1, 2|\n|3, 4|")
  let i3 : @immut.Matrix[Int] = @immut.Matrix::identity(3)
  inspect(i3, content="|1, 0, 0|\n|0, 1, 0|\n|0, 0, 1|")
  let empty : @immut.Matrix[Int] = @immut.Matrix::from_2d_array([[], []])
  debug_inspect(empty.shape(), content="(2, 0)")
}

形状与访问

Matrix::row, Matrix::col

row 和 col 返回行数和列数。

pub fn[T] Matrix::row(Self[T]) -> Int
pub fn[T] Matrix::col(Self[T]) -> Int

Matrix::shape

Matrix::shape(m) 返回 (row, col)。

pub fn[T] Matrix::shape(Self[T]) -> (Int, Int)

Matrix::is_square

Matrix::is_square(m) 返回 row() == col();0×00 \times 0 矩阵是方阵。

pub fn[T] Matrix::is_square(Self[T]) -> Bool

Matrix::null

当每个元素都等于 Zero::zero() 时,Matrix::null(m) 返回 true;空矩阵视为零矩阵。

pub fn[T : Compare + @luna-generic.Zero] Matrix::null(Self[T]) -> Bool

Matrix::at

Matrix::at(m, r) 返回第 r 行的访问器;它是 m[r] 的底层实现。

#alias("_[_]")
pub fn[T] Matrix::at(Self[T], Int) -> Indexed[T]

超出 0..<row() 的行索引会立即导致中止。

Matrix::set

Matrix::set(m, r, c, x) 返回一个除元素 (r,c)(r, c) 为 x 外其余都与 m 相等的矩阵。

pub fn[T] Matrix::set(Self[T], Int, Int, T) -> Self[T]

m 保持不变。越界索引会导致中止。开销为 O(log⁡32(rc))O(\log_{32}(rc));新矩阵与 m 共享其余全部存储。

Matrix::equal

Matrix::equal(a, b) 比较形状和元素;它是 == 的底层实现。

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

Matrix::to_string

Matrix::to_string(m) 将各行渲染为 |a, b| 形式的行,并以 \n 连接。

pub fn[T : Show] Matrix::to_string(Self[T]) -> String

空矩阵渲染为空字符串。

///|
test "immut access and update" {
  let m = @immut.Matrix::from_2d_array([[1, 2], [3, 4]])
  let m2 = m.set(0, 1, 20)
  inspect(m[0][1], content="2")
  inspect(m2[0][1], content="20")
  inspect(m == m2, content="false")
  inspect(m.is_square(), content="true")
  inspect(@immut.Matrix::new(2, 2, 0).null(), content="true")
}

按元素变换

Matrix::map

Matrix::map(m, f) 对每个元素应用 f;元素类型可以改变。

pub fn[T, U] Matrix::map(Self[T], (T) -> U) -> Self[U]

Matrix::mapi

Matrix::mapi(m, f) 对每个元素应用 f(i, j, a_ij)。

pub fn[T, U] Matrix::mapi(Self[T], (Int, Int, T) -> U) -> Self[U]

Matrix::scale

Matrix::scale(m, a) 将每个元素右乘 a:(aija)(a_{ij} a)。

pub fn[T : Mul] Matrix::scale(Self[T], T) -> Self[T]

Matrix::add_constant

Matrix::add_constant(m, a) 给每个元素加上 a。

pub fn[T : Add] Matrix::add_constant(Self[T], T) -> Self[T]

Matrix::adjoint

Matrix::adjoint(m) 返回共轭转置 A∗A^{*},(A∗)ij=aji‾(A^{*})_{ij} = \overline{a_{ji}}。

pub fn[T : @luna-generic.Conjugate] Matrix::adjoint(Self[T]) -> Self[T]

它需要实现了 Conjugate 的标量类型,例如复数类型;内置实数类型没有实现。

///|
test "immut element-wise transforms" {
  let m = @immut.Matrix::from_2d_array([[1, 2], [3, 4]])
  inspect(m.map(x => x * x), content="|1, 4|\n|9, 16|")
  inspect(
    m.mapi((i, j, x) => if i == j { x } else { 0 }),
    content="|1, 0|\n|0, 4|",
  )
  inspect(m.scale(10).add_constant(1), content="|11, 21|\n|31, 41|")
}

算术运算

Matrix::add, Matrix::sub, Matrix::neg

按元素的 A+BA + B、A−BA - B 和 −A-A;它们是相应运算符的底层实现。

pub fn[T : Add] Matrix::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] Matrix::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] Matrix::neg(Self[T]) -> Self[T]

形状不同的操作数会导致中止。

Matrix::mul

Matrix::mul(a, b) 是 a * b 背后的矩阵乘积;它就是 unchecked_matmul。

pub fn[T : Mul + Add + @luna-generic.Zero] Matrix::mul(Self[T], Self[T]) -> Self[T]

Matrix::matmul

当 cols⁡(A)=rows⁡(B)\operatorname{cols}(A) = \operatorname{rows}(B) 时,Matrix::matmul(a, b) 返回 Ok(AB),否则返回 kind 为 DimensionMismatch 的 Err。

pub fn[T : Mul + Add + @luna-generic.Zero] Matrix::matmul(Self[T], Self[T]) -> Result[Self[T], @error.LinearAlgebraError]

(AB)ik=∑jaijbjk(AB)_{ik} = \sum_{j} a_{ij} b_{jk},按 jj 递增的顺序求和。当内部维度为 00 时,结果是形状为 rows⁡(A)×cols⁡(B)\operatorname{rows}(A) \times \operatorname{cols}(B) 的零矩阵,即空和。开销:rcnrcn 次乘加,外加一次 O(cn)O(cn) 的 BB 转置复制。

Matrix::unchecked_matmul

Matrix::unchecked_matmul(a, b) 返回 ABAB,形状不兼容时中止。

pub fn[T : Mul + Add + @luna-generic.Zero] Matrix::unchecked_matmul(Self[T], Self[T]) -> Self[T]

Matrix::pow

对于方阵和 k≥0k \ge 0,Matrix::pow(a, k) 返回 Ok(A^k),其中 A0=IA^0 = I。

pub fn[T : @luna-generic.Semiring] Matrix::pow(Self[T], Int) -> Result[Self[T], @error.LinearAlgebraError]

非方阵得到 NonSquareMatrix(优先检查);负指数得到 NegativeExponent。幂通过二进制求幂计算,最多进行 2⌊log⁡2k⌋+12\lfloor\log_2 k\rfloor + 1 次矩阵乘法。

Matrix::unchecked_pow

Matrix::unchecked_pow(a, k) 返回 AkA^k,遇到非方阵或负指数时中止。

pub fn[T : @luna-generic.Semiring] Matrix::unchecked_pow(Self[T], Int) -> Self[T]

Matrix::trace

对于方阵,Matrix::trace(a) 返回 Ok(tr A),即 ∑iaii\sum_i a_{ii};否则返回 NonSquareMatrix。

pub fn[T : Add + @luna-generic.Zero] Matrix::trace(Self[T]) -> Result[T, @error.LinearAlgebraError]

0×00 \times 0 矩阵的迹为 Zero::zero()。

Matrix::unchecked_trace

Matrix::unchecked_trace(a) 返回 tr⁡A\operatorname{tr} A,遇到非方阵时中止。

pub fn[T : Add + @luna-generic.Zero] Matrix::unchecked_trace(Self[T]) -> T

Matrix::determinant

对于方阵,Matrix::determinant(a) 返回 Ok(det A);否则返回 NonSquareMatrix。

pub fn[T : Compare + @luna-generic.Num + Div] Matrix::determinant(Self[T]) -> Result[T, @error.LinearAlgebraError]

当 n≤4n \le 4 时,它使用封闭的余子式公式求值;当 n≥5n \ge 5 时,它执行带行选主元的无分数(Bareiss)消元,其中的除法在整环中都是精确的。因此,对于 BigInt 结果是精确的;对于 Int 和 Int64,只要中间子式不溢出,结果也是精确的。0×00 \times 0 矩阵的 det⁡\det 为 One::one()。开销为 O(n3)O(n^3)。推导见 immut 设计。

Matrix::unchecked_determinant

Matrix::unchecked_determinant(a) 返回 det⁡A\det A,遇到非方阵时中止。

pub fn[T : Compare + @luna-generic.Num + Div] Matrix::unchecked_determinant(Self[T]) -> T
///|
test "immut checked algebra" {
  let a = @immut.Matrix::from_2d_array([[1, 1], [1, 0]])
  inspect(a.pow(10).unwrap(), content="|89, 55|\n|55, 34|")
  inspect(a.trace().unwrap(), content="1")
  inspect(a.determinant().unwrap(), content="-1")
  let r = @immut.Matrix::from_2d_array([[1, 2, 3]])
  inspect(r.matmul(r) is Err(_), content="true")
  inspect(r.matmul(r.transpose()).unwrap(), content="|14|")
}

///|
test "exact determinant with BigInt" {
  let h = @immut.Matrix::make(6, 6, (i, j) => BigInt::from_int(i * i + j + 1))
  let v = @immut.Matrix::make(6, 6, (i, j) => {
    let mut p = 1N
    for _ in 0..<j {
      p = p * BigInt::from_int(i + 2)
    }
    p
  })
  inspect(h.determinant().unwrap(), content="0")
  inspect(v.determinant().unwrap(), content="34560")
}

第二个矩阵是节点为 2,…,72, \dots, 7 的 Vandermonde 矩阵,其行列式为 ∏i<j(xj−xi)=1! 2! 3! 4! 5!=34560\prod_{i<j}(x_j - x_i) = 1!\,2!\,3!\,4!\,5! = 34560。

结构操作

Matrix::transpose

Matrix::transpose(m) 返回实化后的转置 ATA^{\mathsf T}。

pub fn[T] Matrix::transpose(Self[T]) -> Self[T]

Matrix::horizontal_combine

Matrix::horizontal_combine(a, b) 将 b 放在 a 的右侧:得到分块矩阵 [A  B][A \; B]。

pub fn[T] Matrix::horizontal_combine(Self[T], Self[T]) -> Self[T]

行数不同会导致中止。

Matrix::vertical_combine

Matrix::vertical_combine(a, b) 将 b 放在 a 的下方。

pub fn[T] Matrix::vertical_combine(Self[T], Self[T]) -> Self[T]

列数不同会导致中止。

Matrix::swap_rows, Matrix::swap_cols

swap_rows(i, j) 和 swap_cols(i, j) 返回交换了两行或两列的矩阵。

pub fn[T] Matrix::swap_rows(Self[T], Int, Int) -> Self[T]
pub fn[T] Matrix::swap_cols(Self[T], Int, Int) -> Self[T]

越界索引会导致中止。将某个索引与自身交换时直接返回 m 本身。否则会重建整个矩阵,开销为 O(rc)O(rc)。

///|
test "immut structural operations" {
  let a = @immut.Matrix::from_2d_array([[1, 2], [3, 4]])
  let b = @immut.Matrix::from_2d_array([[5], [6]])
  inspect(a.horizontal_combine(b), content="|1, 2, 5|\n|3, 4, 6|")
  inspect(
    a.vertical_combine(a.swap_rows(0, 1)),
    content="|1, 2|\n|3, 4|\n|3, 4|\n|1, 2|",
  )
  inspect(a.transpose().swap_cols(0, 1), content="|3, 1|\n|4, 2|")
}

迭代与转换

Matrix::iter

Matrix::iter(m) 按行主序遍历所有元素。

pub fn[T] Matrix::iter(Self[T]) -> Iter[T]

Matrix::iter_row, Matrix::iter_col

iter_row(r) 从左到右遍历第 r 行;iter_col(c) 从上到下遍历第 c 列。

pub fn[T] Matrix::iter_row(Self[T], Int) -> Iter[T]
pub fn[T] Matrix::iter_col(Self[T], Int) -> Iter[T]

越界索引会在创建迭代器时导致中止。

Matrix::to_array

Matrix::to_array(m) 将元素复制到一个按行主序排列的扁平数组中。

pub fn[T] Matrix::to_array(Self[T]) -> Array[T]

Matrix::to_2d_array

Matrix::to_2d_array(m) 将元素复制到按行组织的嵌套数组中。

pub fn[T] Matrix::to_2d_array(Self[T]) -> Array[Array[T]]

对于 r×0r \times 0 矩阵,结果包含 rr 个空行。

///|
test "immut iteration" {
  let m = @immut.Matrix::from_2d_array([[1, 2], [3, 4]])
  debug_inspect(m.iter_col(1).to_array(), content="[2, 4]")
  debug_inspect(m.iter().fold(init=0, (s, x) => s + x), content="10")
  debug_inspect(m.to_2d_array(), content="[[1, 2], [3, 4]]")
}

MatrixFn 操作

所有 MatrixFn 操作都是惰性的:它们只组合函数,在读取元素之前不做任何计算。形状检查会立即进行;边界检查在读取时进行。

MatrixFn::make

MatrixFn::make(r, c, f) 构建元素为 f(i,j)f(i, j) 的惰性矩阵。

pub fn[T] MatrixFn::make(Int, Int, (Int, Int) -> T) -> Self[T]

负的维度会导致中止。读取形状范围之外的元素会导致中止。

MatrixFn::new

MatrixFn::new(r, c) 构建一个元素均为 T::default() 的 r×cr \times c 惰性矩阵。

pub fn[T : Default] MatrixFn::new(Int, Int) -> Self[T]

MatrixFn::from_2d_array

MatrixFn::from_2d_array(rows) 构建嵌套行数组的惰性视图。

pub fn[T] MatrixFn::from_2d_array(Array[Array[T]]) -> Self[T]

参差不齐的输入会导致中止。数组会被捕获而不是复制:之后对它们的写入可以通过 MatrixFn 观察到。

MatrixFn::identity

MatrixFn::identity(n) 是惰性的 n×nn \times n 单位矩阵。

pub fn[T : @luna-generic.One + @luna-generic.Zero] MatrixFn::identity(Int) -> Self[T]

MatrixFn::shape

MatrixFn::shape(m) 返回 (rows, cols)。

pub fn[T] MatrixFn::shape(Self[T]) -> (Int, Int)

MatrixFn::at

MatrixFn::at(m, r) 返回 m[r][c] 背后的行访问器。

#alias("_[_]")
pub fn[T] MatrixFn::at(Self[T], Int) -> Indexed[T]

行索引会立即检查,列索引在读取时检查。

MatrixFn::map

MatrixFn::map(m, f) 在每个元素之后复合 f。

pub fn[T, U] MatrixFn::map(Self[T], (T) -> U) -> Self[U]

MatrixFn::map_row, MatrixFn::map_col

map_row(r, f) 和 map_col(c, f) 对某一行或某一列应用 f。

pub fn[T] MatrixFn::map_row(Self[T], Int, (T) -> T) -> Self[T]
pub fn[T] MatrixFn::map_col(Self[T], Int, (T) -> T) -> Self[T]

越界索引会立即导致中止。

MatrixFn::zip_with

MatrixFn::zip_with(a, b, f) 逐元素组合两个惰性矩阵。

pub fn[T, U, W] MatrixFn::zip_with(Self[T], Self[U], (T, U) -> W) -> Self[W]

形状不同会导致中止。

MatrixFn::fold

MatrixFn::fold(m, init~, f) 按行主序归约所有元素。

pub fn[T, U] MatrixFn::fold(Self[T], init~ : U, (U, T) -> U) -> U

这会对每个元素求值一次。

MatrixFn::add, MatrixFn::sub, MatrixFn::neg, MatrixFn::scale

惰性的按元素 A+BA + B、A−BA - B、−A-A 和 AaA a。

pub fn[T : Add] MatrixFn::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] MatrixFn::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] MatrixFn::neg(Self[T]) -> Self[T]
pub fn[T : Mul] MatrixFn::scale(Self[T], T) -> Self[T]

MatrixFn 没有公开的 * 运算符;请使用 pow 或转换为 Matrix。

MatrixFn::pow

MatrixFn::pow(a, k) 通过二进制求幂返回惰性幂 AkA^k。

pub fn[T : @luna-generic.Semiring] MatrixFn::pow(Self[T], Int) -> Self[T]

非方阵输入或负指数会导致中止。由于不做任何缓存,读取 AkA^{k} 的一个元素会重新计算嵌套的乘积,对于深度为 d≈log⁡2kd \approx \log_2 k 的乘积树,需要 O(nd)O(n^{d}) 次元素读取;如果需要读取多个元素,请先将所有元素读入一个 Matrix。

MatrixFn::determinant

MatrixFn::determinant(a) 将矩阵实化,并用 Matrix::determinant 的算法返回其行列式。

pub fn[T : Compare + @luna-generic.Num + Div] MatrixFn::determinant(Self[T]) -> T

非方阵会导致中止;没有受检形式。

MatrixFn::transpose, MatrixFn::adjoint

惰性转置与共轭转置。

pub fn[T] MatrixFn::transpose(Self[T]) -> Self[T]
pub fn[T : @luna-generic.Conjugate] MatrixFn::adjoint(Self[T]) -> Self[T]

MatrixFn::swap_rows, MatrixFn::swap_cols

惰性的行交换与列交换;越界索引会导致中止。

pub fn[T] MatrixFn::swap_rows(Self[T], Int, Int) -> Self[T]
pub fn[T] MatrixFn::swap_cols(Self[T], Int, Int) -> Self[T]

MatrixFn::horizontal_combine, MatrixFn::vertical_combine

惰性分块拼接;行数或列数不匹配会导致中止。

pub fn[T] MatrixFn::horizontal_combine(Self[T], Self[T]) -> Self[T]
pub fn[T] MatrixFn::vertical_combine(Self[T], Self[T]) -> Self[T]

MatrixFn::equal, MatrixFn::to_string

equal 比较形状和每个元素(会对它们求值);to_string 的渲染方式与 Matrix 相同。

pub fn[T : Eq] MatrixFn::equal(Self[T], Self[T]) -> Bool
pub fn[T : Show] MatrixFn::to_string(Self[T]) -> String
///|
test "lazy matrices" {
  let hilbert_denominators = @immut.MatrixFn::make(3, 3, (i, j) => i + j + 1)
  inspect(hilbert_denominators, content="|1, 2, 3|\n|2, 3, 4|\n|3, 4, 5|")
  let fib = @immut.MatrixFn::from_2d_array([[1, 1], [1, 0]]).pow(20)
  inspect(fib[0][1], content="6765")
  let total = hilbert_denominators.fold(init=0, (s, x) => s + x)
  inspect(total, content="27")
  inspect(
    hilbert_denominators.transpose() == hilbert_denominators,
    content="true",
  )
}

向量

Vector::from_array

Vector::from_array(xs) 将数组复制到一个新向量中。

pub fn[T] Vector::from_array(Array[T]) -> Self[T]

Vector::make, Vector::makei

make(n, x) 构建 nn 个 x 的副本;makei(n, f) 构建 (f(0),…,f(n−1))(f(0), \dots, f(n-1))。

pub fn[T] Vector::make(Int, T) -> Self[T]
pub fn[T] Vector::makei(Int, (Int) -> T) -> Self[T]

Vector::length

Vector::length(v) 返回元素个数。

pub fn[T] Vector::length(Self[T]) -> Int

Vector::at

Vector::at(v, i) 返回第 i 个元素;它是 v[i] 的底层实现。越界索引会导致中止。

#alias("_[_]")
pub fn[T] Vector::at(Self[T], Int) -> T

Vector::set

Vector::set(v, i, x) 以 O(log⁡32n)O(\log_{32} n) 的开销返回一个除 i 处外其余都与 v 相等的向量;v 保持不变。

pub fn[T] Vector::set(Self[T], Int, T) -> Self[T]

Vector::iter

Vector::iter(v) 按顺序遍历元素。

pub fn[T] Vector::iter(Self[T]) -> Iter[T]

Vector::map, Vector::zip_with

map(f) 对每个元素应用 f;zip_with(w, f) 逐元素组合两个向量,长度不同时中止。

pub fn[T, U] Vector::map(Self[T], (T) -> U) -> Self[U]
pub fn[T, U, V] Vector::zip_with(Self[T], Self[U], (T, U) -> V) -> Self[V]

Vector::add, Vector::mul, Vector::neg

按元素的 u+vu + v、Hadamard 积 u⊙vu \odot v 以及 −u-u;它们是相应运算符的底层实现。长度不同会导致中止。

pub fn[T : Add] Vector::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Mul] Vector::mul(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] Vector::neg(Self[T]) -> Self[T]

Vector 没有实现 Sub;请写作 u + -v。

Vector::add_constant

Vector::add_constant(v, a) 给每个元素加上 a。

pub fn[T : Add] Vector::add_constant(Self[T], T) -> Self[T]

Vector::left_scale, Vector::right_scale

left_scale(a) 返回 (avi)i(a v_i)_i;right_scale(a) 返回 (via)i(v_i a)_i。两者仅在标量不可交换时有所不同。

pub fn[T : Mul] Vector::left_scale(Self[T], T) -> Self[T]
pub fn[T : Mul] Vector::right_scale(Self[T], T) -> Self[T]

Vector::lerp

Vector::lerp(u, v, t) 返回 (1−t)u+tv(1 - t) u + t v,标量位于左侧。

pub fn[T : @luna-generic.One + Mul + Add + Neg] Vector::lerp(Self[T], Self[T], T) -> Self[T]

长度不同会导致中止。

lin_comb

lin_comb(a, u, b, v) 返回 au+bva u + b v,标量位于左侧。

pub fn[T : Add + Mul] lin_comb(T, Vector[T], T, Vector[T]) -> Vector[T]

Vector::to_row_matrix, Vector::to_col_matrix

将向量视为 1×n1 \times n 或 n×1n \times 1 矩阵。

pub fn[T] Vector::to_row_matrix(Self[T]) -> Matrix[T]
pub fn[T] Vector::to_col_matrix(Self[T]) -> Matrix[T]

Vector::scaled_matrix

Vector::scaled_matrix(v) 返回对角矩阵 diag⁡(v0,…,vn−1)\operatorname{diag}(v_0, \dots, v_{n-1})。

pub fn[T : @luna-generic.Zero] Vector::scaled_matrix(Self[T]) -> Matrix[T]

Vector::tensor_product

Vector::tensor_product(u, v) 返回外积 uvTu v^{\mathsf T},即元素为 uivju_i v_j 的 m×nm \times n 矩阵。

pub fn[T : Mul] Vector::tensor_product(Self[T], Self[T]) -> Matrix[T]

Vector::equal, Vector::to_string

equal 比较长度和元素;to_string 渲染为 |a, b, c|。

pub fn[T : Eq] Vector::equal(Self[T], Self[T]) -> Bool
pub fn[T : Show] Vector::to_string(Self[T]) -> String
///|
test "immut vectors" {
  let u = @immut.Vector::from_array([1, 2, 3])
  let v = @immut.Vector::makei(3, i => 10 * i)
  inspect(u + v, content="|1, 12, 23|")
  inspect(u * v, content="|0, 20, 60|")
  inspect(@immut.lin_comb(2, u, -1, v), content="|2, -6, -14|")
  inspect(u.set(0, 100), content="|100, 2, 3|")
  inspect(u, content="|1, 2, 3|")
  inspect(
    u.tensor_product(@immut.Vector::from_array([1, -1])),
    content="|1, -1|\n|2, -2|\n|3, -3|",
  )
  inspect(u.scaled_matrix(), content="|1, 0, 0|\n|0, 2, 0|\n|0, 0, 3|")
  inspect(u.lerp(@immut.Vector::make(3, 5), 2), content="|9, 8, 7|")
}

已弃用

这些方法形式仅为源码兼容而保留;它们不出现在接口中,使用时会产生警告。

项替代方案
Matrix::not_equal, MatrixFn::not_equal, Vector::not_equal!=
Matrix::output, MatrixFn::output, Vector::output字符串插值或 Show::output(x, logger)
Vector::to_reprRepr(v) 或 @debug.Debug::to_repr(v)
Vector::arbitrary@quickcheck.Arbitrary::arbitrary