Vector — 数値ベクトル

概要

Vector<T> は calx の動的サイズ数値ベクトルテンプレートクラスである。 StaticVector<T,N> はコンパイル時固定サイズの変種。 どちらもヘッダオンリーで、追加のライブラリリンクは不要。

  • 式テンプレートa + 2.0 * b のような式は中間オブジェクトを生成せず、代入時に単一ループで評価
  • SIMD 自動ベクタライズPacketTraits<T> を通じた SIMD パケット評価 (SSE/AVX2)。4 アキュムレータ展開で帯域を最大化
  • ブロック操作head, tail, segment によるゼロコピービュー (Eigen スタイル)
  • BLAS Level-1 融合axpy, axpby を単一ループで実行
  • VectorMap — 外部メモリへのゼロコピービュー (Eigen::Map 相当)

クラス一覧

クラス説明
Vector<T>動的サイズベクトル。std::vector ベースのストレージ
StaticVector<T,N>コンパイル時固定サイズベクトル。std::array<T,N> ベース
VectorMap<T>外部メモリへの読み書き可能なビュー
ConstVectorMap<T>外部メモリへの読み取り専用ビュー

すべて namespace calx に所属。VectorStaticVectorVecExpr<Derived> (CRTP) を継承し、式テンプレートに参加する。

Vector<T> クラス

コンストラクタ

シグネチャ説明
Vector()デフォルト構築。空ベクトル (size = 0)
Vector(size_type n)サイズ n のゼロ初期化ベクトル
Vector(size_type n, const T& value)サイズ n、全要素を value で初期化
Vector(size_type n, uninitialized_t)サイズ n、メモリ確保のみ (値は未初期化)。POD 型のパフォーマンス最適化用
Vector(std::initializer_list<T> init)初期化子リストから構築
Vector(const Vector&)コピーコンストラクタ
Vector(Vector&&) noexceptムーブコンストラクタ
Vector(const VecExpr<E>& expr)式テンプレートからの暗黙変換。SIMD パケット評価で代入

要素アクセス

メンバ関数説明
operator[](size_type i)要素参照 (assert による範囲チェック)
at(size_type i)要素参照 (例外による範囲チェック)
front()先頭要素。空なら IndexError
back()末尾要素。空なら IndexError
data()内部バッファへの生ポインタ

イテレータ

メンバ関数説明
begin() / end()可変イテレータ
cbegin() / cend()const イテレータ

容量

メンバ関数説明
size()要素数
empty()空か
capacity()確保済み容量
reserve(size_type n)容量を事前確保
resize(size_type n)サイズ変更
resize(size_type n, const T& value)サイズ変更 (新要素を value で初期化)
shrink_to_fit()余分な容量を解放
clear()全要素を削除 (size = 0)

算術演算

演算説明
v += wベクトル加算 (要素ごと)
v -= wベクトル減算 (要素ごと)
v *= scalarスカラー乗算
v /= scalarスカラー除算 (ゼロ除算時 invalid_argument)
v += expr式テンプレートからの複合加算 (SIMD パケット評価)
v -= expr式テンプレートからの複合減算 (SIMD パケット評価)

式テンプレート演算

以下の二項演算子は式テンプレートノードを返し、代入時に一括評価される。中間 Vector は生成されない。

説明
a + bベクトル加算
a - bベクトル減算
scalar * aスカラー・ベクトル乗算
a * scalarベクトル・スカラー乗算
Vector<double> a{1.0, 2.0, 3.0};
Vector<double> b{4.0, 5.0, 6.0};
Vector<double> c = a + 2.0 * b;  // 一時オブジェクトなしで評価

内積・ノルム

メンバ関数説明
T dot(const Vector& rhs) const内積 $\langle \mathbf{a}, \mathbf{b} \rangle = \sum a_i b_i$。SIMD 4 アキュムレータ展開
T norm() constL2 ノルム $\|\mathbf{v}\| = \sqrt{\sum v_i^2}$
T norm_l1() constL1 ノルム $\|\mathbf{v}\|_1 = \sum |v_i|$
T norm_linf() const$L_\infty$ ノルム $\|\mathbf{v}\|_\infty = \max |v_i|$
T norm_lp(double p) const一般 $L_p$ ノルム $\|\mathbf{v}\|_p = \left(\sum |v_i|^p\right)^{1/p}$。$p \ge 1$ が必要

正規化

メンバ関数説明
Vector normalized() const正規化されたコピーを返す ($\|\mathbf{v}\| = 0$ のときゼロベクトル)
void normalize()自身を正規化 (in-place)

ブロック操作

ゼロコピービュー (VectorView / ConstVectorView) を返す。ビュー経由の書き込みは元のベクトルに反映される。

メンバ関数説明
head(size_type n)先頭 n 要素のビュー
tail(size_type n)末尾 n 要素のビュー
segment(size_type offset, size_type count)位置 offset から count 要素のビュー

その他

メンバ関数説明
void zero()全要素をゼロに設定
void assign(size_type n, const T& value)サイズ n、全要素を value に再設定

StaticVector<T,N> クラス

コンパイル時固定サイズのベクトル。内部ストレージは std::array<T,N>。 ヒープ割り当てなしで、小さいベクトル (3D 座標、クォータニオン等) に最適。

コンストラクタ

シグネチャ説明
StaticVector()デフォルト構築。全要素ゼロ
StaticVector(const T& value)全要素を value で初期化
StaticVector(std::initializer_list<T>)初期化子リストから構築
StaticVector(const VecExpr<E>&)式テンプレートからの構築

API

Vector<T> と同様のインタフェースを提供する。

  • 要素アクセス: operator[], at, data
  • イテレータ: begin, end, cbegin, cend
  • 容量: size() (constexpr), empty()
  • 算術演算: +=, -=, *=, /= (Vector 同士 + スカラー + 式テンプレート)
  • 内積・ノルム: dot, norm, norm_l1, norm_linf, norm_lp
  • 正規化: normalized, normalize
  • ブロック操作: head, tail, segment
  • その他: zero()

size()constexpr であり、コンパイル時にサイズが確定する。capacity, reserve, resize, shrink_to_fit, clear は提供されない。

フリー関数

以下のフリー関数は Vector<T>StaticVector<T,N> の両方に対応する。

内積・ノルム

関数説明
T dot(a, b)内積 $\sum a_i b_i$
T norm(v)L2 ノルム $\|\mathbf{v}\|$
T norm2(v)norm の別名 (ODE ソルバー等の汎用インタフェース用)
T norm_l1(v)L1 ノルム
T norm_linf(v)$L_\infty$ ノルム
T norm_lp(v, p)一般 $L_p$ ノルム
Vector<T> normalized(v)正規化されたコピー

normnorm2VecExpr<E> (式テンプレートノード) も直接受け付ける。具体化せずにパケット評価でノルムを計算。

外積

関数説明
StaticVector<T,3> cross(a, b)3D 外積。StaticVector<T,3> 専用

BLAS Level-1 融合関数

一時オブジェクトを生成せず、単一ループで処理する。コンパイラの SIMD 自動ベクタライズが有効。

関数説明
void axpy(alpha, x, y)$\mathbf{y} \mathrel{+}= \alpha \mathbf{x}$ (DAXPY 相当)
void axpby(alpha, x, beta, y, result)$\mathbf{result} = \alpha \mathbf{x} + \beta \mathbf{y}$ (out-of-place)
void axpby(alpha, x, beta, y)$\mathbf{y} = \alpha \mathbf{x} + \beta \mathbf{y}$ (in-place)

axpyaxpbyVector<T> 版と StaticVector<T,N> 版の両方がある。

VectorMap / ConstVectorMap

外部メモリ上の連続配列をコピーなしでベクトルとして参照するビュークラス。

VectorMap<T>

メンバ説明
VectorMap(T* data, size_type size)外部バッファからビューを構築
size()要素数
data()バッファへのポインタ
operator[](i)要素参照 (読み書き可能)
operator Vector<T>() constVector へのコピー変換
operator=(const Vector<T>&)Vector からの要素コピー代入

ConstVectorMap<T>

メンバ説明
ConstVectorMap(const T* data, size_type size)外部バッファからビューを構築
size()要素数
data()バッファへの const ポインタ
operator[](i) const要素参照 (読み取り専用)
operator Vector<T>() constVector へのコピー変換
double raw[] = {1.0, 2.0, 3.0};
auto v = calx::VectorMap<double>(raw, 3);
v[1] = 5.0;  // raw[1] が 5.0 に変更される

使用例

#include <math/core/vector.hpp>
#include <iostream>
using namespace calx;

int main() {
    // コンストラクタ
    Vector<double> a{1.0, 2.0, 3.0};
    Vector<double> b{4.0, 5.0, 6.0};

    // 式テンプレート — 中間オブジェクトなし
    Vector<double> c = a + 2.0 * b;  // {9, 12, 15}

    // 内積・ノルム
    std::cout << "dot(a,b) = " << dot(a, b) << std::endl;       // 32
    std::cout << "norm(a)  = " << norm(a) << std::endl;          // 3.74166
    std::cout << "norm_l1  = " << norm_l1(a) << std::endl;      // 6
    std::cout << "norm_inf = " << norm_linf(a) << std::endl;    // 3

    // 正規化
    Vector<double> u = normalized(a);
    std::cout << "norm(normalized(a)) = " << norm(u) << std::endl;  // 1

    // StaticVector + 外積
    StaticVector<double, 3> x{1.0, 0.0, 0.0};
    StaticVector<double, 3> y{0.0, 1.0, 0.0};
    auto z = cross(x, y);  // {0, 0, 1}
    std::cout << "cross = [" << z[0] << ", " << z[1] << ", " << z[2] << "]" << std::endl;

    // ブロック操作
    Vector<double> v{10.0, 20.0, 30.0, 40.0, 50.0};
    auto h = v.head(3);       // [10, 20, 30] — ゼロコピービュー
    auto t = v.tail(2);       // [40, 50]
    auto s = v.segment(1, 3); // [20, 30, 40]

    // BLAS Level-1
    Vector<double> p{1.0, 2.0, 3.0};
    Vector<double> q{4.0, 5.0, 6.0};
    axpy(2.0, p, q);  // q = {6, 9, 12}

    // VectorMap (外部メモリビュー)
    double raw[] = {1.0, 2.0, 3.0};
    auto map = VectorMap<double>(raw, 3);
    map[0] = 99.0;  // raw[0] が 99.0 に変更
}