Boost.MultiArray 參考手冊

Ronald Garcia

Indiana University
Open Systems Lab

目錄

本庫概要
MultiArray 概念
符號
相關類型
有效表達式
複雜度保證
不變式
視圖的相關類型
Models
數組組件
multi_array
multi_array_ref
const_multi_array_ref
輔助組件
multi_array_types
extent_range
extent_gen
全局對像
視圖和子數組生成器
內存佈局指示符
範圍檢查

Boost.MultiArray 由多個組件組成。MultiArray 概念定義了多維容器的一個泛型接口。multi_array 是一個參照 MultiArray 的通用容器類。multi_array_refconst_multi_array_ref 則是適配器類。通過使用它們,你可以像操作一個 multi_array 一樣操作任意的連續數據塊。const_multi_array_refmulti_array_ref 的區別在於其元素不可以通過接口來修改。最後還有幾個輔助類用於創建和特化數組,還有一些全局對像被定義為本庫接口的一部分。

本庫概要

要使用 Boost.MultiArray, 你必須在你的源程序中包含頭文件 boost/multi_array.hpp. 該文件將以下聲明帶入到當前域:

namespace boost {

namespace multi_array_types {
typedef *unspecified* index;
typedef *unspecified* size_type;
typedef *unspecified* difference_type;
typedef *unspecified* index_range;
typedef *unspecified* extent_range;
typedef *unspecified* index_gen;
typedef *unspecified* extent_gen;
}

template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class multi_array;

template <typename ValueType,
std::size_t NumDims>
class multi_array_ref;

template <typename ValueType,
std::size_t NumDims>
class const_multi_array_ref;

multi_array_types::extent_gen extents;
multi_array_types::index_gen indices;

template <typename Array, int N> class subarray_gen;
template <typename Array, int N> class const_subarray_gen;
template <typename Array, int N> class array_view_gen;
template <typename Array, int N> class const_array_view_gen;

class c_storage_order;
class fortran_storage_order;
template <std::size_t NumDims> class general_storage_order;

}

MultiArray 概念

MultiArray 概念定義了一個分層嵌套容器的接口。它指定了訪問元素、遍歷容器和創建數據視圖等操作。MultiArray 定義了一個靈活的內存模式以適應不同的數據佈局。

在一個 MultiArray 容器層次的每一層(或每一維)都可視為一組有序的容器,其中每一個都包含相同數量和類型的值。容器層次的深度就是 MultiArray 的 維度。MultiArray 是遞歸定義的;每一層的容器都符合 MultiArray。一個 MultiArray 的每個維度都有各自的大小,由所有維度的大小所組成的列表定義了整個 MultiArray 的 形狀。該容器層次的基礎可以視為1維的 MultiArrays. 它們的值是所有被容器包含的元素,而不是其中一部分。它們就是 MultiArray 的元素。

與其它容器概念一樣,MultiArray 提供了迭代器來遍歷它的值。另外,也可以用方括號來直接訪問這些值。

MultiArray 還提供了創建特定視圖的方法。視圖 可以讓你將一個 MultiArray 中的元素的子集視為一個獨立的 MultiArray. 由於視圖是引向同一組底層元素的,所以對視圖的元素進行修改地反映到原來的 MultiArray 中。例如,給定一組3維"立體"的元素,它的一個2維切片可以被視為一個無關的 MultiArray. 視圖可以用 index_genindex_range 對像來創建。index_range 代表了某個維度被包含在視圖中的元素範圍。index_gen 則將這些範圍數據集合起來,並進行簿記工作,以確定返回的視圖類型。MultiArray 的 operator[] 必須被傳入對 index_gen::operator[]N 次鏈式調用的結果,即:

indices[a0][a1]...[aN];

其中 N 為 MultiArray 的維度,而 indices 是一個類型為 index_gen 的對象。視圖的類型取決於 index_gen 所指定的退化的維度數量。一個退化的維度表示對某個維度向 index_gen 指定單個值。例如,如果 indices 是一個類型為 index_gen 的對象,那麼以下例子:

indices[index_range(0,5)][2][index_range(0,4)];

其中第二個維度是退化的。由以上語句生成的視圖具有2個維度,形狀為 5 x 4. 如果上面的 "2" 被替換為另一個 index_range 對象,例如:

indices[index_range(0,5)][index_range(0,2)][index_range(0,4)];

那麼該視圖有3個維度。

MultiArray 還提供了關於所含元素的內存佈局的信息。它存儲元素的內存模式由4個屬性來定義:原點、形狀、索引基數和步幅。原點是以 a[0][0]...[0]來訪問的元素在內存中的地址,其中 a 為一個 MultiArray. 形狀是一個數字列表,指定容器的各個維度的大小。例如,列表中第一個數字是最外層容器的大小,第二個數字是下一層容器的大小,依此類推。索引基數是一個有 符號整數的列表,指定了容器中第一個值的索引。在同一個維度的所有容器共享一個相同的索引基數。注意,由於索引基數可以為正,所以原點不一定位於 MultiArray 的元素的內存中。步幅決定了索引值如何映射到內存的偏移量。它們適應多種可能的元素佈局。例如,一個2維數組的元素可以按行存儲(即每一行的元素被連續存 儲)或者按列存儲(即每一列的元素被連續存儲)。

符號

以下是將用於 MultiArray 接口說明的符號描述。

表 1. 符號

A 一個參照 MultiArray 的類型
a,b 類型 A 的對象
NumDims A 的維度數
Dims 某個滿足 0<Dims<NumDims 的數字,用作維度參數
indices 一個由對 index_gen::operator[](index_range) 的多次鏈式調用所創建的對象
index_list 一個對象,其類型參照了 Collection
idx 一個有符號整數值
tmp 類型 boost::array<index,NumDims> 的對象

相關類型

表 2. 相關類型

類型 說明
value_type 容器的值類型。如果 NumDims == 1, 則它就是 element. 否則,它是最直接的嵌套容器的值類型。
reference 所含值的引用類型。如果 NumDims == 1, 則它就是 element&. 否則,它與 template subarray<NumDims-1>::type 類型相同。
const_reference 所含值的常量引用類型。如果 NumDims == 1, 則它就是 const element&. 否則,它與 template const_subarray<NumDims-1>::type 類型相同。
size_type 這是一個無符號整數類型。主要用於指定數組的形狀。
difference_type 這是一個有符號整數類型,用於表示兩個迭代器間的距離。它與 std::iterator_traits<iterator>::difference_type 類型相同。
iterator A 的迭代器。如果 NumDims == 1, 則它符合 隨機訪問迭代器。否則,它符合 隨機訪問遍歷迭代器可讀迭代器 可寫迭代器
const_iterator A 的常量迭代器。
reverse_iterator 反向迭代器,用於對 A 進行反向迭代。
const_reverse_iterator A 的反向常量迭代器。
element 存儲在 MultiArray 的基礎層的對象的類型。類型與 template subarray<1>::value_type 相同
index 這是一個有符號整數類型,用於 A 中的索引。也被用於表示步幅和索引基數。
index_gen 該類型用於創建一個 index_range 的 tuple,傳遞給 operator[],以創建一個 array_view<Dims>::type 對象。
index_range 該類型指定一個 MultiArray 的某些維度的索引範圍。該範圍對於一個 array_view<Dims>::type 對象是可見的。
template subarray<Dims>::type 這是 Dims 維度的子數組類型。它是 A(NumDims - Dims) 維度的引用類型,同樣符合 MultiArray.
template const_subarray<Dims>::type 這是常量的子數組類型。
template array_view<Dims>::type 這是 Dims 維度的視圖類型。通過調用 operator[](indices) 返回。它符合 MultiArray.
template const_array_view<Dims>::type 這是 Dims 維度的常量視圖類型。

有效表達式

表 3. 有效表達式

表達式 返回類型 語義
a.shape() const size_type* 返回由 NumDims 個元素組成的列表,表示每個維度的長度。
a.strides() const index* 返回由 NumDims 個元素組成的列表,表示與每個維度相關的步幅。在訪問數組中的值時,步幅用於計算一個元素在內存中的位置。
a.index_bases() const index* 返回由 NumDims 個元素組成的列表,表示每個維度第一個元素的索引。
a.origin() element* 如果 a 是可變的,否則為 const element*  返回由表達式 a[0][0]...[0]所訪問的元素的地址。如果有某個索引基數是正的,該元素將不存在,但該地址還是可以用來定位一個給定索引的有效元素。
a.num_dimensions() size_type 返回數組的維數(注意 a.num_dimensions() == NumDims)。
a.num_elements() size_type 返回數組中包含的元素數量。等價於以下代碼:
std::accumulate(a.shape(),a.shape+a.num_dimensions(),
size_type(1),std::multiplies<size_type>());
a.size() size_type 返回 a 中包含的值的數量。等價於 a.shape()[0];
a(index_list) element& 如果 a 是可變的,否則為 const element&  該表達式訪問 a 的某個特定元素。index_list 是表示所返回的元素的唯一索引組合。它等價於以下代碼(忽略其中的臨時對像):
    // 用步幅與索引相乘
std::transform(index_list.begin(), index_list.end(),
a.strides(), tmp.begin(), std::multiplies<index>()),

// 將積的總和加到原點上
*std::accumulate(tmp.begin(), tmp.end(), a.origin());
a.begin() iterator 如果 a 是可變的,否則為 const_iterator  返回指向 a 的始端的迭代器。
a.end() iterator 如果 a 是可變的,否則為 const_iterator  返回指向 a 的末端的迭代器。
a.rbegin() reverse_iterator 如果 a 是可變的,否則為 const_reverse_iterator  返回一個反向迭代器,指向反向 a 的始端。
a.rend() reverse_iterator 如果 a 是可變的,否則為 const_reverse_iterator  返回一個反向迭代器,指向反向 a 的末端。
a[idx] reference 如果 a 是可變的,否則為 const_reference  返回一個引用類型,綁定到 a 中索引為 idx 的值。注意,如果 i 為該維度的索引基數,以上表達式將返回第 (idx-i)個元素(從零起計)。該表達式等價於 *(a.begin()+idx-a.index_bases()[0]);.
a[indices] array_view<Dims>::type 如果 a 是可變的,否則為 const_array_view<Dims>::type  該表達式生成一個數組的視圖,依據構成 indicesindex_rangeindex 值。
a == b bool 執行對 ab 中各個值的逐一比較。元素類型必須是 相等性可比較的,該表達式才有效。
a < b bool 執行對 ab 中各個值的逐一比較。元素類型必須是 小於關係可比較的,該表達式才有效。
a <= b bool 執行對 ab 中各個值的逐一比較。元素類型必須是 相等性可比較的小於關係可比較的,該表達式才有效。
a > b bool 執行對 ab 中各個值的逐一比較。元素類型必須是 相等性可比較的小於關係可比較的,該表達式才有效。
a >= b bool 執行對 ab 中各個值的逐一比較。元素類型必須是 小於關係可比較的,該表達式才有效。

複雜度保證

begin()end() 具有分期常量時間複雜度。size() 則具有與 MultiArray 的大小線性相關的時間複雜度。

不變式

表 4. 不變式

有效範圍 [a.begin(),a.end()) 為有效範圍。
範圍大小 a.size() == std::distance(a.begin(),a.end());.
完整性 對區間 [a.begin(),a.end()) 進行迭代,將遍歷 a 中的每一個 value_type.
等價的訪問方法 調用 a[a1][a2]...[aN],其中 N==NumDims,產生的結果與調用 a(index_list),其中 index_list 是由值 a1...aN 組成的 Collection 是相同的。

視圖的相關類型

以下 MultiArray 相關類型定義了創建已有 MultiArray 的視圖的接口。以下描述其接口及規則。

index_range

index_range 對像表示一個指定步幅的半開區間。它們可以被聚集起來(用一個 index_gen 對像)傳遞給某個 MultiArray 的 operator[] 以創建一個數組視圖。在創建視圖時,每個 index_range 代表 MultiArray 的某個維度上的有效索引範圍。通過這些範圍組合可以訪問到的元素構成了這個視圖。在某些情況下,可以創建一個沒有指定開始和結束值的 index_range. 這樣,該對象就被解釋為從 MultiArray 的某個維度的始端開始,在該維度的末端結束。

index_range 對像有多種方式進行構造和修改,為索引範圍提供方便且清晰的表達方式。為了指定區間,index_range 提供了一組構造函數,可變成員函數,以及一種新穎的不等式操作符。使用這種不等式操作符,可以這樣來表示非開區間 [5,10):

5 <= index_range() < 10;

4 < index_range() <= 9;

等等。以下描述 index_range 的接口。

表 5. 符號

i 類型 index_range 的一個對像
idx,idx1,idx2,idx3 類型 index 的一個對像

表 6. 相關類型

類型 說明
index 一個有符號整數類型。用於指定開始值、結束值和步幅值。
size_type 一個無符號整數類型。用於報告一個 index_range 所代表的範圍大小。

表 7. 有效表達式

表達式 返回類型 語義
index_range(idx1,idx2,idx3) index_range 構造一個 index_range,表示步幅為 idx3 的區間 [idx1,idx2)
index_range(idx1,idx2) index_range 構造一個 index_range,表示單位步幅的區間 [idx1,idx2). 等價於 index_range(idx1,idx2,1).
index_range() index_range 構造一個 index_range,不指定開始值和結束值。
i.start(idx1) index& i 的開始索引設為 idx.
i.finish(idx) index& 將 i 的結束索引設為 idx.
i.stride(idx) index& 將 i 的步幅設為 idx.
i.start() index 返回 i 的開始索引。
i.finish() index 返回 i 的結束索引。
i.stride() index 返回 i 的步幅。
i.get_start(idx) index 如果 i 指定了開始值,則等價於 i.start(). 否則返回 idx.
i.get_finish(idx) index 如果 i 指定了結束值,則等價於 i.finish(). 否則返回 idx.
i.size(idx) size_type 如果 i 指定了開始值和結束值,則等價於 (i.finish()-i.start())/i.stride(). 否則返回 idx.
i < idx index 指定結束值的另一種語法。表示有效索引的區間不包含 idx. 等價於 index_range(r.start(), idx, r.stride())
i <= idx index 指定結束值的另一種語法。表示有效索引的區間包含 idx. 等價於 index_range(r.start(), idx + 1, r.stride())
idx < i index 指定開始值的另一種語法。表示有效索引的區間不包含 idx. 等價於 index_range(idx + 1, i.finish(), i.stride()).
idx <= i index 指定開始值的另一種語法。表示有效索引的區間包含 idx. 等價於 index_range(idx, i.finish(), i.stride()).
i + idx index 該表達式將 i 的開始值和結束值都增加 idx. 等價於 index_range(r.start()+idx, r.finish()+idx, r.stride())
i - idx index 該表達式將 i 的開始值和結束值都減少 idx. 等價於 index_range(r.start()-idx, r.finish()-idx, r.stride())

index_gen

index_genindex_range 對像聚集起來用作指定視圖的參數。通過對 operator[] 的鏈式調用,保存相關的區間和維度信息,用於在 MultiArray 中初始化一個新的視圖。

表 8. 符號

Dims,Ranges 無符號整數值。
x 類型 template gen_type<Dims,Ranges>::type 的對象
i 類型 index_range 的對象。
idx 類型 index 的對象

表 9. 相關類型

類型 說明
index 有符號整數類型。用於指定退化的維度。
size_type 無符號整數類型。用於報告 index_range 所表示的範圍大小。
template gen_type::<Dims,Ranges>::type 該類型生成器命名了對 index_gen::operator[] 進行 Dims 次鏈式調用的結果。 Ranges 參數由退化的區間(即調用 operator[](index))的數量所決定。注意,index_gengen_type<0,0>::type 是相同的類型。

表 10. 有效表達式

表達式 返回類型 語義
index_gen() gen_type<0,0>::type 構造一個 index_gen 對象。該對象可用於生成 多個 index_range 值所組成的 tuple.
x[i] gen_type<Dims+1,Ranges+1>::type 返回一個新對象,包含所有以前的 index_range 對像再外加 i.operator[] 的鏈式調用就是聚集 index_range 對象的方法。
x[idx] gen_type<Dims,Ranges>::type 返回一個新對象,包含所有以前的 index_range 對像再外加一個退化區間 index_range(idx,idx). 注意,這並不等價於 x[index_range(idx,idx)],後者的返回類型為 gen_type<Dims+1,Ranges+1>::type.

Models

  • multi_array
  • multi_array_ref
  • const_multi_array_ref
  • template array_view<Dims>::type
  • template const_array_view<Dims>::type
  • template subarray<Dims>::type
  • template const_subarray<Dims>::type

數組組件

Boost.MultiArray 定義了一個數組類 multi_array, 以及兩個適配器類 multi_array_refconst_multi_array_ref. 這三個類均符合 MultiArray 概念,所以它們共享了多項功能。multi_array_refmulti_array 的區別在於,multi_array 管理它所擁有的內存,而 multi_array_ref 則被傳入一塊內存且該塊內存是由外部管理的。const_multi_array_refmulti_array_ref 的區別在於它所適配的底層元素不可以通過其接口進行修改,雖然某些數組屬性,包括數組的形狀和索引基數,可以被修改。這些類所具備的共有功能說明如下。

註:前提條件、作用和實現。在以下幾節中,我們會用一些C++代碼片斷來說明象前提條件、作用和後續條件等約束。沒有必要對數組組件 的底層實現進行描述;這些代碼描述了所需的輸入以及特定操作的行為。不滿足前提條件將導致未定義的行為。不是所有列出的作用(如複製構造函數等)都必須精 確模仿。這些代碼片斷的主要意圖是捉住所描述的操作的本質。

查詢

element* data();
const element* data() const;

返回一個指針,指向數組的數據所在的連續內存塊的開頭。如果所有數組的所有維度都是從零起計的,且均按升序存儲,則它等價於 origin(). 注意,const_multi_array_ref 只提供該函數的 const 版本。

element* origin();
const element* origin() const;

返回 multi_array 的原點元素。注意,const_multi_array_ref 只提供該函數的 const 版本。(MultiArray 所必需的)

const index* index_bases();

返回 multi_array 的索引基數。(MultiArray 所必需的)

const index* strides();

返回 multi_array 的步幅。(MultiArray 所必需的)

const size_type* shape();

返回 multi_array 的形狀。(MultiArray 所必需的)

比較操作

bool operator==(const *array-type*& rhs);
bool operator!=(const *array-type*& rhs);
bool operator<(const *array-type*& rhs);
bool operator>(const *array-type*& rhs);
bool operator>=(const *array-type*& rhs);
bool operator<=(const *array-type*& rhs);

每個比較操作按兩個數組的值類型進行比較。(MultiArray 所必需的)

前提條件:element 必須支持在 multi_array 上調用的相應比較操作。

複雜度:O(num_elements()).

修改操作

template <typename SizeList>
void reshape(const SizeList& sizes)

該操作修改 multi_array 的形狀。元素數量及索引基數保持不變,但嵌套容器層次中各層的值數量可能被改變。

SizeList 的要求:SizeList 必須符合 Collection.

前提條件:

std::accumulate(sizes.begin(),sizes.end(),size_type(1),std::times<size_type>()) == this->num_elements();
sizes.size() == NumDims;

後續條件:std::equal(sizes.begin(),sizes.end(),this->shape) == true;

template <typename BaseList>
void reindex(const BaseList& values);

該操作根據 values 的值修改 multi_array 的索引基數。

BaseList 的要求:BaseList 必須符合 Collection.

前提條件:values.size() == NumDims;

後續條件:std::equal(values.begin(),values.end(),this->index_bases());

void reindex(index value);

該操作將
multi_array 所有維度的索引基數改為 value.

後續條件:

std::count_if(this->index_bases(),this->index_bases()+this->num_dimensions(),
std::bind_2nd(std::equal_to<index>(),value)) ==
this->num_dimensions();

multi_array

multi_array 是一個支持隨機訪問迭代的多維容器。它的維數在編譯期是固定的,但它的形狀和所包含的元素數量可以在構造時指定。元素的數量在 multi_array 的生命週期內是固定的,但容器的形狀可以改變。multi_array 用一個可替換的分配器(allocator)來管理其數據元素。

符合的概念:MultiArray, 可複製構造。根據其元素類型,也可能符合 相等性可比較小於關係可比較

摘要:

namespace boost {

template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class multi_array {
public:
// types:
typedef ValueType element;
typedef *unspecified* value_type;
typedef *unspecified* reference;
typedef *unspecified* const_reference;
typedef *unspecified* difference_type;
typedef *unspecified* iterator;
typedef *unspecified* const_iterator;
typedef *unspecified* reverse_iterator;
typedef *unspecified* const_reverse_iterator;
typedef multi_array_types::size_type size_type;
typedef multi_array_types::index index;
typedef multi_array_types::index_gen index_gen;
typedef multi_array_types::index_range index_range;
typedef multi_array_types::extent_gen extent_gen;
typedef multi_array_types::extent_range extent_range;
typedef *unspecified* storage_order_type;


// template typedefs
template <std::size_t Dims> struct subarray;
template <std::size_t Dims> struct const_subarray;
template <std::size_t Dims> struct array_view;
template <std::size_t Dims> struct const_array_view;


// constructors and destructors

multi_array();

template <typename ExtentList>
explicit multi_array(const ExtentList& sizes,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());
explicit multi_array(const extents_tuple& ranges,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());
multi_array(const multi_array& x);
multi_array(const const_multi_array_ref<ValueType,NumDims>& x);
multi_array(const const_subarray<NumDims>::type& x);
multi_array(const const_array_view<NumDims>::type& x);

multi_array(const multi_array_ref<ValueType,NumDims>& x);
multi_array(const subarray<NumDims>::type& x);
multi_array(const array_view<NumDims>::type& x);

~multi_array();

// modifiers

multi_array& operator=(const multi_array& x);
template <class Array> multi_array& operator=(const Array& x);

// iterators:
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;

// capacity:
size_type size() const;
size_type num_elements() const;
size_type num_dimensions() const;

// element access:
template <typename IndexList>
element& operator()(const IndexList& indices);
template <typename IndexList>
const element& operator()(const IndexList& indices) const;
reference operator[](index i);
const_reference operator[](index i) const;
array_view<Dims>::type operator[](const indices_tuple& r);
const_array_view<Dims>::type operator[](const indices_tuple& r) const;

// queries
element* data();
const element* data() const;
element* origin();
const element* origin() const;
const size_type* shape() const;
const index* strides() const;
const index* index_bases() const;
const storage_order_type& storage_order() const;

// comparators
bool operator==(const multi_array& rhs);
bool operator!=(const multi_array& rhs);
bool operator<(const multi_array& rhs);
bool operator>(const multi_array& rhs);
bool operator>=(const multi_array& rhs);
bool operator<=(const multi_array& rhs);

// modifiers:
template <typename InputIterator>
void assign(InputIterator begin, InputIterator end);
template <typename SizeList>
void reshape(const SizeList& sizes)
template <typename BaseList> void reindex(const BaseList& values);
void reindex(index value);
template <typename ExtentList>
multi_array& resize(const ExtentList& extents);
multi_array& resize(extents_tuple& extents);
};

構造函數

template <typename ExtentList>
explicit multi_array(const ExtentList& sizes,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());

用給定參數構造一個 multi_array. sizes 指定了被構造 multi_array 的形狀。store 指定了存儲的順序或各維度的內存佈局。alloc 用於分配被包含的元素。

ExtentList 的要求:ExtentList 必須符合 Collection.

前提條件:sizes.size() == NumDims;

explicit multi_array(extent_gen::gen_type<NumDims>::type ranges,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());

用給定參數構造一個 multi_array. ranges 指定了被構造 multi_array 的形狀和索引基數。它是對 extent_gen::operator[] 進行 NumDims 次鏈式調用所得到的結果。store 指定了存儲的順序或各維度的內存佈局。alloc 用於分配存儲在 multi_array 中的元素的內存。

multi_array(const multi_array& x);
multi_array(const const_multi_array_ref<ValueType,NumDims>& x);
multi_array(const const_subarray<NumDims>::type& x);
multi_array(const const_array_view<NumDims>::type& x);
multi_array(const multi_array_ref<ValueType,NumDims>& x);
multi_array(const subarray<NumDims>::type& x);
multi_array(const array_view<NumDims>::type& x);

這些構造函數都是用於構造一個 multi_array 並執行一次對 x 的深拷貝。

複雜度:執行 O(x.num_elements()) 次 element 的複製構造函數。

multi_array();

構造一個 multi_array,其形狀為 (0,...,0),不包含任何元素。

關於構造函數的補充說明:multi_array 構造表達式

     multi_array<int,3> A(boost::extents[5][4][3]);

     boost::array<multi_array_base::index,3> my_extents = {{5, 4, 3}};
multi_array<int,3> A(my_extents);

是等價的。

修改操作

multi_array& operator=(const multi_array& x);
template <class Array> multi_array& operator=(const Array& x);

將 x 的各個元素的複製到當前的 multi_array.

Array 的要求:Array 必須符合 MultiArray.

前提條件:

std::equal(this->shape(),this->shape()+this->num_dimensions(),
x.shape());

後續條件:

(*.this) == x;

複雜度:賦值操作執行 O(x.num_elements()) 次 element 的複製構造函數。

template <typename InputIterator>
void assign(InputIterator begin, InputIterator end);

將區間 [begin,end) 中的元素複製到數組中。等價於 std::copy(begin,end,this->data()).

前提條件:std::distance(begin,end) == this->num_elements();

複雜度:assign 成員函數執行 O(this->num_elements()) 次 ValueType 的複製構造函數。

multi_array& resize(extent_gen::gen_type<NumDims>::type extents);
template <typename ExtentList>
multi_array& resize(const ExtentList& extents);

該函數將數組的大小修改為由 extents 指定的形狀,extents 可以是生成的長度列表或符合 Collection 概念。數組中的內容盡可能保持不變;如果新的數組大小變小了,則會丟失部分數據。因數組大小改變而新創建的元素均由 element 的缺省構造函數進行初始化。

查詢

storage_order_type& storage_order() const;

該查詢返回與 multi_array 相關聯的存儲順序對象。它可以用於構造另一個具有相同存儲順序的新數組。

multi_array_ref

multi_array_ref 是一個多維容器適配器。它為任意存儲了某種元素的連續內存塊提供 MultiArray 的接口。multi_array_ref 給出了與 multi_array 相同的接口,除了構造函數以外。

符合的概念:multi_array_ref 符合 MultiArray, 可複製構造,並且依據其元素類型,還可能符合 相等性可比較小於關係可比較。這裡只對在 multi_array 中沒有的操作給出詳細說明。

摘要

namespace boost {

template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class multi_array_ref {
public:
// types:
typedef ValueType element;
typedef *unspecified* value_type;
typedef *unspecified* reference;
typedef *unspecified* const_reference;
typedef *unspecified* difference_type;
typedef *unspecified* iterator;
typedef *unspecified* const_iterator;
typedef *unspecified* reverse_iterator;
typedef *unspecified* const_reverse_iterator;
typedef multi_array_types::size_type size_type;
typedef multi_array_types::index index;
typedef multi_array_types::index_gen index_gen;
typedef multi_array_types::index_range index_range;
typedef multi_array_types::extent_gen extent_gen;
typedef multi_array_types::extent_range extent_range;
typedef *unspecified* storage_order_type;

// template typedefs
template <std::size_t Dims> struct subarray;
template <std::size_t Dims> struct const_subarray;
template <std::size_t Dims> struct array_view;
template <std::size_t Dims> struct const_array_view;


// structors

template <typename ExtentList>
explicit multi_array_ref(element* data, const ExtentList& sizes,
const storage_order_type& store = c_storage_order());
explicit multi_array_ref(element* data, const extents_tuple& ranges,
const storage_order_type& store = c_storage_order());
multi_array_ref(const multi_array_ref& x);
~multi_array_ref();

// modifiers

multi_array_ref& operator=(const multi_array_ref& x);
template <class Array> multi_array_ref& operator=(const Array& x);

// iterators:
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;

// capacity:
size_type size() const;
size_type num_elements() const;
size_type num_dimensions() const;

// element access:
template <typename IndexList>
element& operator()(const IndexList& indices);
template <typename IndexList>
const element& operator()(const IndexList& indices) const;
reference operator[](index i);
const_reference operator[](index i) const;
array_view<Dims>::type operator[](const indices_tuple& r);
const_array_view<Dims>::type operator[](const indices_tuple& r) const;

// queries
element* data();
const element* data() const;
element* origin();
const element* origin() const;
const size_type* shape() const;
const index* strides() const;
const index* index_bases() const;
const storage_order_type& storage_order() const;

// comparators
bool operator==(const multi_array_ref& rhs);
bool operator!=(const multi_array_ref& rhs);
bool operator<(const multi_array_ref& rhs);
bool operator>(const multi_array_ref& rhs);
bool operator>=(const multi_array_ref& rhs);
bool operator<=(const multi_array_ref& rhs);

// modifiers:
template <typename InputIterator>
void assign(InputIterator begin, InputIterator end);
template <typename SizeList>
void reshape(const SizeList& sizes)
template <typename BaseList> void reindex(const BaseList& values);
void reindex(index value);
};

構造函數

template <typename ExtentList>
explicit multi_array_ref(element* data,
const ExtentList& sizes,
const storage_order& store = c_storage_order());

以給定參數構造一個 multi_array_ref. sizes 指定了被構造 multi_array_ref 的形狀。store 指定了存儲順序或數組各維度的內存佈局。(譯註:原文中有一個alloc參數,應為筆誤)

ExtentList 的要求:ExtentList 必須符合 Collection.

前提條件:sizes.size() == NumDims;

explicit multi_array_ref(element* data,
extent_gen::gen_type<NumDims>::type ranges,
const storage_order& store = c_storage_order());

以給定參數構造一個 multi_array_ref. ranges 指定了被構造 multi_array_ref 的形狀和索引基數。它是對 extent_gen::operator[] 進行 NumDims 次鏈式調用所得到的結果。store 指定了存儲順序或數組各維度的內存佈局。

multi_array_ref(const multi_array_ref& x);

構造 x 的一個淺拷貝。

複雜度:常量時間(作為對比,將其與 multi_array 類的複製構造函數進行比較)。

修改操作

multi_array_ref& operator=(const multi_array_ref& x);
template <class Array> multi_array_ref& operator=(const Array& x);

x 中的元素複製到當前的 multi_array_ref.

Array 的要求:Array 必須符合 MultiArray.

前提條件:

std::equal(this->shape(),this->shape()+this->num_dimensions(),
x.shape());

後續條件:

(*.this) == x;

複雜度:賦值操作執行 O(x.num_elements()) 次 element 的複製構造函數。

const_multi_array_ref

const_multi_array_ref 是一個多維容器適配器。它為任意存儲了某種元素的連續內存塊提供 MultiArray 的接口。給出了與 multi_array 相同的接口,除了構造函數以外。 

符合的概念:const_multi_array_ref 符合 MultiArray, 可複製構造,並且依據其元素類型,還可能符合 相等性可比較小於關係可比較。這裡只對在 multi_array 中沒有的操作給出詳細說明。

摘要

namespace boost {

template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class const_multi_array_ref {
public:
// types:
typedef ValueType element;
typedef *unspecified* value_type;
typedef *unspecified* reference;
typedef *unspecified* const_reference;
typedef *unspecified* difference_type;
typedef *unspecified* iterator;
typedef *unspecified* const_iterator;
typedef *unspecified* reverse_iterator;
typedef *unspecified* const_reverse_iterator;
typedef multi_array_types::size_type size_type;
typedef multi_array_types::index index;
typedef multi_array_types::index_gen index_gen;
typedef multi_array_types::index_range index_range;
typedef multi_array_types::extent_gen extent_gen;
typedef multi_array_types::extent_range extent_range;
typedef *unspecified* storage_order_type;

// template typedefs
template <std::size_t Dims> struct subarray;
template <std::size_t Dims> struct const_subarray;
template <std::size_t Dims> struct array_view;
template <std::size_t Dims> struct const_array_view;


// structors

template <typename ExtentList>
explicit const_multi_array_ref(const element* data, const ExtentList& sizes,
const storage_order_type& store = c_storage_order());
explicit const_multi_array_ref(const element* data, const extents_tuple& ranges,
const storage_order_type& store = c_storage_order());
const_multi_array_ref(const const_multi_array_ref& x);
~const_multi_array_ref();



// iterators:
const_iterator begin() const;
const_iterator end() const;
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;

// capacity:
size_type size() const;
size_type num_elements() const;
size_type num_dimensions() const;

// element access:
template <typename IndexList>
const element& operator()(const IndexList& indices) const;
const_reference operator[](index i) const;
const_array_view<Dims>::type operator[](const indices_tuple& r) const;

// queries
const element* data() const;
const element* origin() const;
const size_type* shape() const;
const index* strides() const;
const index* index_bases() const;
const storage_order_type& storage_order() const;

// comparators
bool operator==(const const_multi_array_ref& rhs);
bool operator!=(const const_multi_array_ref& rhs);
bool operator<(const const_multi_array_ref& rhs);
bool operator>(const const_multi_array_ref& rhs);
bool operator>=(const const_multi_array_ref& rhs);
bool operator<=(const const_multi_array_ref& rhs);

// modifiers:
template <typename SizeList>
void reshape(const SizeList& sizes)
template <typename BaseList> void reindex(const BaseList& values);
void reindex(index value);
};

構造函數

template <typename ExtentList>
explicit const_multi_array_ref(const element* data,
const ExtentList& sizes,
const storage_order& store = c_storage_order());

以給定參數構造一個 const_multi_array_ref. sizes 指定了被構造 const_multi_array_ref 的形狀。store 指定了存儲順序或數組各維度的內存佈局。

ExtentList 的要求:ExtentList 必須符合 Collection.

前提條件:sizes.size() == NumDims;

explicit const_multi_array_ref(const element* data,
extent_gen::gen_type<NumDims>::type ranges,
const storage_order& store = c_storage_order());

作用:以給定參數構造一個 const_multi_array_ref. ranges 指定了被構造 const_multi_array_ref 的形狀和索引基數。它是對 extent_gen::operator[] 進行 NumDims 次鏈式調用所得到的結果。store 指定了存儲順序或數組各維度的內存佈局。

const_multi_array_ref(const const_multi_array_ref& x);

作用:構造 x 的一個淺拷貝。

輔助組件

multi_array_types

namespace multi_array_types {
typedef *unspecified* index;
typedef *unspecified* size_type;
typedef *unspecified* difference_type;
typedef *unspecified* index_range;
typedef *unspecified* extent_range;
typedef *unspecified* index_gen;
typedef *unspecified* extent_gen;
}

名字空間 multi_array_types 定義了一些與 multi_array, multi_array_ref, 和 const_multi_array_ref 相關的類型,這些類型不依賴於模板參數。這些類型被所有 Boost.Multiarray 組件共同使用。它們被定義在一個可以方便訪問的名字空間中。除了 extent_genextent_range 以外,這些類型遵循 MultiArray 所要求且在其概念定義中被描述的同名規則。extent_genextent_range 則描述如下。

extent_range

extent_range 對像定義了一個半開區間。它為 multi_array, multi_array_ref, 和 const_multi_array_ref 的構造函數提供形狀和索引的信息。多個 extent_range 被聚集起來傳遞給數組的構造函數(詳細說明請見 extent_gen)。

摘要

class extent_range {
public:
typedef multi_array_types::index index;
typedef multi_array_types::size_type size_type;

// Structors
extent_range(index start, index finish);
extent_range(index finish);
~extent_range();

// Queries
index start();
index finish();
size_type size();
};

符合的概念:可缺省構造,可複製構造

方法與類型

extent_range(index start, index finish)

該構造函數定義一個半開區間 [start,finish). 表達式 finish 必須大於 start.

extent_range(index finish)

該構造函數定義一個半開區間 [0,finish)finish 的值必須為正。

index start()

該函數返回表示該區間的第一個索引。

index finish()

該函數返回半開區間的上界值。注意,該區間不包含該值。

size_type size()

該函數返回指定區間的大小。它等價於 finish()-start().

extent_gen

extent_gen 類定義了一個接口,用於聚集數組的形狀和索引信息,以傳遞給 multi_array, multi_array_ref, 或 const_multi_array_ref 的構造函數。該接口模仿了C++中聲明內建數組類型的語法。例如,在C++中,一個3維 int 數組聲明如下:

int A[3][4][5],

類似的 multi_array 則聲明如下:

multi_array<int,3> A(extents[3][4][5]).

摘要

template <std::size_t NumRanges>
class *implementation_defined* {
public:
typedef multi_array_types::index index;
typedef multi_array_types::size_type size_type;

template <std::size_t NumRanges> class gen_type;

gen_type<NumRanges+1>::type operator[](const range& a_range) const;
gen_type<NumRanges+1>::type operator[](index idx) const;
};

typedef *implementation_defined*<0> extent_gen;

方法與類型

template gen_type::<Ranges>::type

該類型生成器用於指定對 extent_gen::operator[]Ranges 次鏈式調用的結果。類型 extent_gengen_type<0>::type 相同。

gen_type<NumRanges+1>::type operator[](const extent_range& a_range) const;

該函數返回一個新的對象,包含所有以前的 extent_range 對象並加上 a_range. extent_range 對像通過對 operator[] 的鏈式調用來聚集。

gen_type<NumRanges+1>::type operator[](index idx) const;

該函數返回一個新的對象,包含所有以前的 extent_range 對象並加上 extent_range(0,idx). 該函數使得數組構造函數具有與傳統C的多維數組聲明類似的語法。

全局對像

為了語法上的方便,Boost.MultiArray 定義了兩個全局對像作為其接口的一部分。這些對像扮演了對象生成器的角色;包含它們的表達式可以創建其它所需的對象。

在某些情形下,這兩個全局對象可能被認為開銷太大。可以通過在包含 boost/multi_array.hpp 之前定義預處理符號 BOOST_MULTI_ARRAY_NO_GENERATORS 來禁止它們的構造。

extents

namespace boost {
multi_array_base::extent_gen extents;
}

Boost.MultiArray 的數組類使用 extents 全局對像來在構造時指定數組的形狀。例如,一個 3 乘 3 乘 3 的 multi_array 構造如下:

multi_array<int,3> A(extents[3][3][3]);

同樣的數組也可以通過顯式一個局部的 extent_gen 對像來創建,不過使用全局對象可以不需要進行聲明。

indices

namespace boost {
multi_array_base::index_gen indices;
}

MultiArray 概念給出了一個 index_gen 相關類型用於創建視圖。indices 是一個全局對象,擔任了本庫所提供的所有數組組件及其相關子數組和視圖的 index_gen 角色。

例如,使用 indices 對象,數組 A 的一個視圖可以構造如下:

A[indices[index_range(0,5)][2][index_range(2,4)]];

視圖與子數組生成器

Boost.MultiArray 提供了 traits 類 subarray_gen, const_subarray_gen, array_view_gen, 和 const_array_view_gen, 用於在函數模板中表示數組的各個相關類型。通常,沒有比使用嵌套類型生成器更為方便的方法了,不過本庫的作者發現,有些C++編譯器不能正確處理嵌套在函數模板的參數類型中的模板。為此,這些生成器需要另外的解決方法。以下代碼片斷示範了 array_view_gen traits 類和相關數組的 array_view 類型之間的對應關係:

template <typename Array>
void my_function() {
typedef typename Array::template array_view<3>::type view1_t;
typedef typename boost::array_view_gen<Array,3>::type view2_t;
// ...
}

在上例中,view1_tview2_t 具有相同類型。

內存佈局指示符

多維數組表示了由多個元素容器組成的層次結構,而這些元素必須被置於內存中。所以,一個多維數組可以用多種方法在內存中表示。

例如,有以下矩陣所表示的一個2維數組:

這個數組在C++中可以表示為:

int a[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };

這是一個行優先存儲的例子,每行的元素被連續存儲。除了讓C++來處理對數組元素的訪問以外,你也可以自己手工管理這個數組以及它的索引。其中一種方法可能是這樣:

int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int s[] = { 4, 1 };

在聲明了 a 和步幅 s 之後,數組的元素 a(i,j) 可以用以下表達式來訪問:

*a+i*s[0]+j*s[1]

.

同一個2維數組也可以按列存儲如下:

int a[] = { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11 };
int s[] = { 3, 1 };

注意,這裡的步幅有所不同。所以,前面給出的訪問元素的表達式必須與該數據和步幅一起使用。

除了維度的順序,還有可能以降序方式保存某個維度。例如,回到第一個例子,數組的第一個維度,即行,可能以相反的順序保存如下:

int data[] = { 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3 };
int *a = data + 8;
int s[] = { -4, 1 };

注意,在這個例子中,a 必須顯式地設置為原點。在前面的例子中,保存在內存中的第一個元素即為原點;而這裡不再是如此了。

另外,第二個維度,即列,也可能以相反的順序保存,而行則以升序保存:

int data[] = { 3, 2, 1, 0,  7, 6, 5, 4, 11, 10, 9, 8 };
int *a = data + 3;
int s[] = { 4, -1 };

最後,也可能兩個維度均以降序保存:

int data[] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
int *a = data + 11;
int s[] = { -4, -1 };

以上各個數組都是等價的。前面給出的訪問 a(i,j) 的表達式在各種內存佈局下均得到相同的值。Boost.MultiArray 數組可以按以上所說的各種定制的存儲參數來創建。因此,已有的數據可以被適配(通過 multi_array_refconst_multi_array_ref)以適應數組的抽像。該特性的一個常見用法是,包裝一個需要與Fortran程序交互的數組,使它可以被C++和Fortran同時操作。下面幾節將講述用於指定內存佈局的 Boost.MultiArray 組件。

c_storage_order

class c_storage_order {
c_storage_order();
};

c_storage_order 用於指定一個數組以與原生C++多維數組相同的內存佈局來存儲其元素,即從最後一維到第一維。這是本庫所提供的各種數組的缺省存儲順序。

fortran_storage_order

class fortran_storage_order {
fortran_storage_order();
};

fortran_storage_order 用於指定一個數組以與Fortran多維數組相同的內存佈局來存儲其元素,即從第一維到最後一維。

general_storage_order

template <std::size_t NumDims> 
class general_storage_order {

template <typename OrderingIter, typename AscendingIter>
general_storage_order(OrderingIter ordering, AscendingIter ascending);
};

general_storage_order 允許用戶為一個數組中的內容指定各種不同的內存佈局。構造出來的對象將被傳遞給數組的構造函數,以指定存儲順序。

OrderingIterAscendingIter 必須符合 InputIterator 概念。這兩個迭代器都必須引向包含 NumDims 個元素的區間。AscendingIter 指向一組可轉換為 bool 的對象。對像值為 true 代表該維以升序存儲,為 false 則代表該維以降序存儲。OrderingIter 則指定保存各個維度的順序。

範圍檢查

缺省情況下,數組訪問方法 operator()operator[] 都執行範圍檢查。如果給定的索引值超出了數組所定義的範圍,將引發一個斷言並退出程序。要關閉範圍檢查(為了產品發佈版本的性能原因),請在應用程序包含 multi_array.hpp 之前定義 BOOST_DISABLE_ASSERTS 預處理器宏。