Tensor — 任意階数テンソル
目次
概要
Tensor<T> は sangi の任意階数 (rank) ・任意シェイプの動的テンソルクラスである。
Matrix / Vector / 3D グリッドを統一的に扱える設計で、機械学習や物理シミュレーションでの多次元配列の表現に用いる。
ヘッダオンリーで、追加のライブラリリンクは不要。
動的ランク・動的シェイプ — Tensor<T>({3, 4, 5}) のように任意次元を実行時に指定可能
ストライドベースのビュー — transpose / reshape はデータコピーなしでビューを返す
shared_ptr によるデータ共有 — 複数のテンソルが安全に同じバッファを参照可能。書き込み時に必要なら独立コピーを作成 (copy-on-write 風)
Matrix / Vector 相互変換 — rank-2 ↔ Matrix<T>、rank-1 ↔ Vector<T>、rank-0 ↔ スカラー
C++23 concepts — TensorScalar コンセプトで要素型を制約
テンソルの理論的背景は
テンソル (線形代数・中級) /
行列・テンソル微分 を参照。
TensorScalar コンセプト
Tensor<T> の要素型 T は次のコンセプトを満たす必要がある。
template<typename T>
concept TensorScalar = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
{ a - b } -> std::convertible_to<T>;
{ a * b } -> std::convertible_to<T>;
{ -a } -> std::convertible_to<T>;
{ T(0) };
};
すなわち加減乗算と単項マイナス、ゼロ初期化が可能な型。組み込みの float, double, std::complex<T> はもちろん、sangi の多倍長型 Int , Float , Rational , Complex も満たす。
Tensor<T> クラス
template<TensorScalar T>
class Tensor;
コンストラクタ
シグネチャ 説明
Tensor()デフォルト構築。rank-0 スカラー (値 0)
Tensor(std::vector<size_t> shape)shape 指定のゼロ初期化テンソル
Tensor(std::initializer_list<size_t> shape)同上 (初期化子リスト版)
Tensor(std::vector<size_t> shape, const T& value)全要素を value で初期化
Tensor(std::vector<size_t> shape, std::vector<T> data)フラットデータから構築 (row-major 順)。サイズ不一致で DimensionError
Tensor(const T& scalar) (explicit)rank-0 スカラーテンソル
Tensor(const Matrix<T>& matrix) (explicit)Matrix から rank-2 テンソルへ変換
Tensor(const Vector<T>& vec) (explicit)Vector から rank-1 テンソルへ変換
Tensor(const Tensor&) / Tensor(Tensor&&) noexceptコピー / ムーブ (内部の shared_ptr を共有)
Tensor<double> t0; // rank-0 スカラー (値 0)
Tensor<double> t1({3, 4, 5}); // rank-3 ゼロ初期化 (60 要素)
Tensor<double> t2({2, 3}, 1.0); // rank-2、全要素 1.0
Tensor<double> t3({2, 3}, {1,2,3,4,5,6}); // フラットデータから (row-major)
Tensor<double> s(3.14); // rank-0 スカラー
要素アクセス
メンバ関数 説明
operator()(Indices... indices)variadic template 版。rank と引数個数の不一致で DimensionError
at(std::span<const size_t> indices)境界チェック付きアクセス
at(std::initializer_list<size_t> indices)同上 (初期化子リスト版)
flat(size_t index)論理フラットインデックスアクセス (ストライドに基づく順序)
data()内部バッファへの生ポインタ (offset_ 加算済)
Tensor<double> t({2, 3}, {1,2,3,4,5,6});
double x = t(1, 2); // 6 (row 1, col 2)
double y = t.at({0, 1}); // 2 (境界チェック)
double z = t.flat(3); // 4 (フラット index)
double* p = t.data(); // raw pointer
プロパティ
メンバ関数 返り値型 説明
rank()size_t階数 (次元数)。rank-0 スカラーは 0
shape()const std::vector<size_t>&各軸のサイズ
shape(size_t axis)size_t特定軸のサイズ
strides()const std::vector<size_t>&ストライド (要素単位)
size()size_t全要素数
empty()bool要素数 0 (いずれかの軸が 0)
isContiguous()boolメモリが row-major に連続か (transpose 後は false)
isScalar()boolrank-0 スカラーか
isView()boolデータを他テンソルと共有中か (use_count > 1)
useCount()long内部 shared_ptr の参照カウント
変更操作
メンバ関数 説明
fill(const T& value)全要素を value で埋める。ビューの場合は独立コピーを作成
zero()全要素をゼロに設定
形状変更
メンバ関数 説明
reshape(std::vector<size_t> newShape)要素数が一致する場合のみ形状変更。contiguous ならビュー (データ共有)、そうでなければコピー。不一致で DimensionError
transpose(std::vector<size_t> perm)軸を perm で置換したビューを返す (データコピーなし)。perm は 0..rank-1 の置換
transpose()全軸を反転 (rank-2 なら通常の行列転置)
contiguous()コンティギュアスな独立コピーを返す。既にコンティギュアスで単独所有なら *this を返す
Tensor<double> t({2, 3, 4});
auto r = t.reshape({6, 4}); // ビュー (データ共有)
auto tT = t.transpose({2, 1, 0}); // 軸 (0,1,2) → (2,1,0) のビュー
auto m = t.transpose(); // 全軸反転 (rank-3 なら {2,1,0})
auto c = tT.contiguous(); // 物理的に row-major な独立コピー
算術演算子 (複合代入)
演算 説明
t += rhsshape 一致のテンソル加算。不一致で DimensionError
t -= rhsshape 一致のテンソル減算
t *= scalarスカラー乗算
t /= scalarスカラー除算 (ゼロ除算時 invalid_argument)
Matrix / Vector / スカラー変換
メンバ関数 説明
toMatrix()rank-2 テンソルを Matrix<T> へ変換。rank ≠ 2 で DimensionError
toVector()rank-1 テンソルを Vector<T> へ変換。rank ≠ 1 で DimensionError
toScalar()rank-0 テンソルをスカラー T へ変換。rank ≠ 0 で DimensionError
出力
メンバ関数 説明
to_string()shape と値を含む文字列表現。要素数が多い場合は先頭 5 + 末尾 3 を表示
非メンバの operator<< も提供 (to_string() を呼ぶ)。
フリー関数
算術演算子
シグネチャ 説明
Tensor<T> operator+(const Tensor<T>& lhs, const Tensor<T>& rhs)テンソル加算
Tensor<T> operator-(const Tensor<T>& lhs, const Tensor<T>& rhs)テンソル減算
Tensor<T> operator*(const Tensor<T>&, const T&) / 左版スカラー乗算 (両側オーバーロード)
Tensor<T> operator/(const Tensor<T>&, const T&)スカラー除算
Tensor<T> operator-(const Tensor<T>&)単項マイナス (全要素の符号反転)
テンソル演算
シグネチャ 説明
Tensor<T> hadamard(const Tensor<T>& a, const Tensor<T>& b)要素ごとの積 (Hadamard 積)。shape 一致が必要
Tensor<T> contract(const Tensor<T>& a, const Tensor<T>& b, const std::vector<std::pair<size_t,size_t>>& axes)指定した軸ペア群で縮約。axes[i] = {axis_of_a, axis_of_b}
Tensor<T> outerProduct(const Tensor<T>& a, const Tensor<T>& b)外積 (テンソル積)。結果の rank = rank(a) + rank(b)、shape は連結
// Hadamard 積 (要素積)
Tensor<double> a({2,3}, {1,2,3,4,5,6});
Tensor<double> b({2,3}, {6,5,4,3,2,1});
auto h = hadamard(a, b); // shape = {2,3}, data = {6, 10, 12, 12, 10, 6}
// 行列積 (rank-2 × rank-2 を axis 1 と axis 0 で縮約)
Tensor<double> M({3,4}, 1.0);
Tensor<double> N({4,5}, 2.0);
auto C = contract(M, N, {{1, 0}}); // shape = {3, 5}, 全要素 = 8 (= 4×1×2)
// 外積 (rank-1 × rank-1 で rank-2)
Tensor<double> u({3}, {1,2,3});
Tensor<double> v({2}, {10,20});
auto K = outerProduct(u, v); // shape = {3,2}, data = {10,20,20,40,30,60}
// = {{10,20},{20,40},{30,60}}
// 実行結果 (build & run 検証済):
// h shape=[2,3] data=[6,10,12,12,10,6]
// C shape=[3,5] data=[8,8,8,8,8, 8,8,8,8,8, 8,8,8,8,8]
// K shape=[3,2] data=[10,20,20,40,30,60]
ファクトリ関数
sangi::tensor 名前空間に提供。
シグネチャ 説明
tensor::zeros<T>(std::vector<size_t> shape)全要素 0 のテンソル
tensor::ones<T>(std::vector<size_t> shape)全要素 1 のテンソル
型特性
template<typename T> struct is_tensor;
template<typename T> inline constexpr bool is_tensor_v = is_tensor<T>::value;
is_tensor_v<X> は X が Tensor<T> のインスタンスのときに true。SFINAE / concepts で分岐に使う。
使用例
#include <math/core/Tensor.hpp>
using namespace sangi;
int main() {
// 3 階テンソルを作成し reshape ビューを取得
Tensor<double> t({2, 3, 4}, 1.0);
auto t_flat = t.reshape({24}); // ビュー
t_flat(0) = 42.0; // t(0,0,0) も 42.0 (データ共有)
// 軸の置換 (transpose) はビュー、contiguous() でコピー
auto t_perm = t.transpose({2, 0, 1}); // shape {4,2,3}, データコピーなし
auto t_copy = t_perm.contiguous(); // 物理的に row-major な独立コピー
// Hadamard 積
Tensor<double> a({2,2}, {1,2,3,4});
Tensor<double> b({2,2}, {5,6,7,8});
auto c = hadamard(a, b); // {5, 12, 21, 32}
// テンソル縮約 (行列積として)
Tensor<double> X({3, 4}, 1.0);
Tensor<double> Y({4, 5}, 2.0);
auto Z = contract(X, Y, {{1, 0}}); // shape {3,5}, 各要素 = 8.0
// Matrix / Vector との相互変換
Matrix<double> M(3, 3, 1.0);
Tensor<double> tM(M); // rank-2 テンソルへ
Matrix<double> M2 = tM.toMatrix(); // 戻す
// 実行結果 (build & run 検証済):
// t_perm rank=3, shape={4,2,3}, isContiguous=false
// c shape=[2,2], data=[5,12,21,32]
// Z shape=[3,5], 全要素 8.0
// tM.rank=2, size=9; M2(0,0)=1, M2(2,2)=1
}
関連:
Matrix /
Vector /
FFT (Tensor3D) /
Matrix 算術 — Hadamard 積 。